summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 18:37:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 18:37:14 +0000
commitea648e70a989cca190cd7403fe892fd2dcc290b4 (patch)
treee2b6b1c647da68b0d4d66082835e256eb30970e8 /bin
parentInitial commit. (diff)
downloadbind9-upstream/1%9.11.5.P4+dfsg.tar.xz
bind9-upstream/1%9.11.5.P4+dfsg.zip
Adding upstream version 1:9.11.5.P4+dfsg.upstream/1%9.11.5.P4+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--bin/Makefile.in18
-rw-r--r--bin/check/Makefile.in101
-rw-r--r--bin/check/check-tool.c798
-rw-r--r--bin/check/check-tool.h59
-rw-r--r--bin/check/named-checkconf.8135
-rw-r--r--bin/check/named-checkconf.c671
-rw-r--r--bin/check/named-checkconf.docbook197
-rw-r--r--bin/check/named-checkconf.html158
-rw-r--r--bin/check/named-checkzone.8329
-rw-r--r--bin/check/named-checkzone.c567
-rw-r--r--bin/check/named-checkzone.docbook528
-rw-r--r--bin/check/named-checkzone.html429
-rw-r--r--bin/check/win32/checkconf.dsp.in107
-rw-r--r--bin/check/win32/checkconf.dsw29
-rw-r--r--bin/check/win32/checkconf.mak.in404
-rw-r--r--bin/check/win32/checkconf.vcxproj.filters.in27
-rw-r--r--bin/check/win32/checkconf.vcxproj.in115
-rw-r--r--bin/check/win32/checkconf.vcxproj.user3
-rw-r--r--bin/check/win32/checktool.dsp.in113
-rw-r--r--bin/check/win32/checktool.dsw29
-rw-r--r--bin/check/win32/checktool.vcxproj.filters.in18
-rw-r--r--bin/check/win32/checktool.vcxproj.in101
-rw-r--r--bin/check/win32/checktool.vcxproj.user3
-rw-r--r--bin/check/win32/checkzone.dsp.in108
-rw-r--r--bin/check/win32/checkzone.dsw29
-rw-r--r--bin/check/win32/checkzone.mak.in404
-rw-r--r--bin/check/win32/checkzone.vcxproj.filters.in27
-rw-r--r--bin/check/win32/checkzone.vcxproj.in126
-rw-r--r--bin/check/win32/checkzone.vcxproj.user3
-rw-r--r--bin/confgen/Makefile.in115
-rw-r--r--bin/confgen/ddns-confgen.8159
-rw-r--r--bin/confgen/ddns-confgen.c304
-rw-r--r--bin/confgen/ddns-confgen.docbook230
-rw-r--r--bin/confgen/ddns-confgen.html202
-rw-r--r--bin/confgen/include/confgen/os.h33
-rw-r--r--bin/confgen/keygen.c228
-rw-r--r--bin/confgen/keygen.h35
-rw-r--r--bin/confgen/rndc-confgen.8221
-rw-r--r--bin/confgen/rndc-confgen.c299
-rw-r--r--bin/confgen/rndc-confgen.docbook289
-rw-r--r--bin/confgen/rndc-confgen.html243
-rw-r--r--bin/confgen/unix/Makefile.in28
-rw-r--r--bin/confgen/unix/os.c37
-rw-r--r--bin/confgen/util.c51
-rw-r--r--bin/confgen/util.h46
-rw-r--r--bin/confgen/win32/confgentool.dsp.in135
-rw-r--r--bin/confgen/win32/confgentool.dsw29
-rw-r--r--bin/confgen/win32/confgentool.vcxproj.filters.in39
-rw-r--r--bin/confgen/win32/confgentool.vcxproj.in111
-rw-r--r--bin/confgen/win32/confgentool.vcxproj.user3
-rw-r--r--bin/confgen/win32/ddnsconfgen.dsp.in103
-rw-r--r--bin/confgen/win32/ddnsconfgen.dsw29
-rw-r--r--bin/confgen/win32/ddnsconfgen.mak.in337
-rw-r--r--bin/confgen/win32/ddnsconfgen.vcxproj.filters.in18
-rw-r--r--bin/confgen/win32/ddnsconfgen.vcxproj.in123
-rw-r--r--bin/confgen/win32/ddnsconfgen.vcxproj.user3
-rw-r--r--bin/confgen/win32/os.c28
-rw-r--r--bin/confgen/win32/rndcconfgen.dsp.in103
-rw-r--r--bin/confgen/win32/rndcconfgen.dsw29
-rw-r--r--bin/confgen/win32/rndcconfgen.mak.in336
-rw-r--r--bin/confgen/win32/rndcconfgen.vcxproj.filters.in18
-rw-r--r--bin/confgen/win32/rndcconfgen.vcxproj.in112
-rw-r--r--bin/confgen/win32/rndcconfgen.vcxproj.user3
-rw-r--r--bin/delv/Makefile.in81
-rw-r--r--bin/delv/delv.1441
-rw-r--r--bin/delv/delv.c1707
-rw-r--r--bin/delv/delv.docbook701
-rw-r--r--bin/delv/delv.html592
-rw-r--r--bin/delv/win32/delv.dsp.in103
-rw-r--r--bin/delv/win32/delv.dsw29
-rw-r--r--bin/delv/win32/delv.mak.in299
-rw-r--r--bin/delv/win32/delv.vcxproj.filters.in22
-rw-r--r--bin/delv/win32/delv.vcxproj.in110
-rw-r--r--bin/delv/win32/delv.vcxproj.user3
-rw-r--r--bin/dig/Makefile.in111
-rw-r--r--bin/dig/dig.1803
-rw-r--r--bin/dig/dig.c2293
-rw-r--r--bin/dig/dig.docbook1329
-rw-r--r--bin/dig/dig.html1075
-rw-r--r--bin/dig/dighost.c6676
-rw-r--r--bin/dig/host.1269
-rw-r--r--bin/dig/host.c921
-rw-r--r--bin/dig/host.docbook406
-rw-r--r--bin/dig/host.html333
-rw-r--r--bin/dig/include/dig/dig.h485
-rw-r--r--bin/dig/nslookup.1294
-rw-r--r--bin/dig/nslookup.c1037
-rw-r--r--bin/dig/nslookup.docbook501
-rw-r--r--bin/dig/nslookup.html386
-rw-r--r--bin/dig/win32/dig.dsp.in107
-rw-r--r--bin/dig/win32/dig.dsw29
-rw-r--r--bin/dig/win32/dig.mak.in427
-rw-r--r--bin/dig/win32/dig.vcxproj.filters.in27
-rw-r--r--bin/dig/win32/dig.vcxproj.in113
-rw-r--r--bin/dig/win32/dig.vcxproj.user3
-rw-r--r--bin/dig/win32/dighost.dsp.in113
-rw-r--r--bin/dig/win32/dighost.dsw29
-rw-r--r--bin/dig/win32/dighost.vcxproj.filters.in18
-rw-r--r--bin/dig/win32/dighost.vcxproj.in106
-rw-r--r--bin/dig/win32/dighost.vcxproj.user3
-rw-r--r--bin/dig/win32/host.dsp.in103
-rw-r--r--bin/dig/win32/host.dsw29
-rw-r--r--bin/dig/win32/host.mak.in427
-rw-r--r--bin/dig/win32/host.vcxproj.filters.in18
-rw-r--r--bin/dig/win32/host.vcxproj.in110
-rw-r--r--bin/dig/win32/host.vcxproj.user3
-rw-r--r--bin/dig/win32/nslookup.dsp.in107
-rw-r--r--bin/dig/win32/nslookup.dsw29
-rw-r--r--bin/dig/win32/nslookup.mak.in427
-rw-r--r--bin/dig/win32/nslookup.vcxproj.filters.in21
-rw-r--r--bin/dig/win32/nslookup.vcxproj.in111
-rw-r--r--bin/dig/win32/nslookup.vcxproj.user3
-rw-r--r--bin/dnssec/Makefile.in123
-rw-r--r--bin/dnssec/dnssec-dsfromkey.8182
-rw-r--r--bin/dnssec/dnssec-dsfromkey.c583
-rw-r--r--bin/dnssec/dnssec-dsfromkey.docbook305
-rw-r--r--bin/dnssec/dnssec-dsfromkey.html255
-rw-r--r--bin/dnssec/dnssec-importkey.8138
-rw-r--r--bin/dnssec/dnssec-importkey.c475
-rw-r--r--bin/dnssec/dnssec-importkey.docbook253
-rw-r--r--bin/dnssec/dnssec-importkey.html216
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.8305
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.c756
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.docbook551
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.html458
-rw-r--r--bin/dnssec/dnssec-keygen.8354
-rw-r--r--bin/dnssec/dnssec-keygen.c1126
-rw-r--r--bin/dnssec/dnssec-keygen.docbook654
-rw-r--r--bin/dnssec/dnssec-keygen.html545
-rw-r--r--bin/dnssec/dnssec-revoke.8103
-rw-r--r--bin/dnssec/dnssec-revoke.c286
-rw-r--r--bin/dnssec/dnssec-revoke.docbook169
-rw-r--r--bin/dnssec/dnssec-revoke.html137
-rw-r--r--bin/dnssec/dnssec-settime.8204
-rw-r--r--bin/dnssec/dnssec-settime.c687
-rw-r--r--bin/dnssec/dnssec-settime.docbook376
-rw-r--r--bin/dnssec/dnssec-settime.html315
-rw-r--r--bin/dnssec/dnssec-signzone.8480
-rw-r--r--bin/dnssec/dnssec-signzone.c3902
-rw-r--r--bin/dnssec/dnssec-signzone.docbook838
-rw-r--r--bin/dnssec/dnssec-signzone.html674
-rw-r--r--bin/dnssec/dnssec-verify.8117
-rw-r--r--bin/dnssec/dnssec-verify.c353
-rw-r--r--bin/dnssec/dnssec-verify.docbook203
-rw-r--r--bin/dnssec/dnssec-verify.html168
-rw-r--r--bin/dnssec/dnssectool.c1934
-rw-r--r--bin/dnssec/dnssectool.h113
-rw-r--r--bin/dnssec/win32/dnssectool.dsp.in113
-rw-r--r--bin/dnssec/win32/dnssectool.dsw29
-rw-r--r--bin/dnssec/win32/dnssectool.vcxproj.filters.in27
-rw-r--r--bin/dnssec/win32/dnssectool.vcxproj.in109
-rw-r--r--bin/dnssec/win32/dnssectool.vcxproj.user3
-rw-r--r--bin/dnssec/win32/dsfromkey.dsp.in103
-rw-r--r--bin/dnssec/win32/dsfromkey.dsw29
-rw-r--r--bin/dnssec/win32/dsfromkey.mak.in324
-rw-r--r--bin/dnssec/win32/dsfromkey.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/dsfromkey.vcxproj.in138
-rw-r--r--bin/dnssec/win32/dsfromkey.vcxproj.user3
-rw-r--r--bin/dnssec/win32/importkey.dsp.in103
-rw-r--r--bin/dnssec/win32/importkey.dsw29
-rw-r--r--bin/dnssec/win32/importkey.mak.in324
-rw-r--r--bin/dnssec/win32/importkey.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/importkey.vcxproj.in112
-rw-r--r--bin/dnssec/win32/importkey.vcxproj.user3
-rw-r--r--bin/dnssec/win32/keyfromlabel.dsp.in103
-rw-r--r--bin/dnssec/win32/keyfromlabel.dsw29
-rw-r--r--bin/dnssec/win32/keyfromlabel.mak.in324
-rw-r--r--bin/dnssec/win32/keyfromlabel.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/keyfromlabel.vcxproj.in112
-rw-r--r--bin/dnssec/win32/keyfromlabel.vcxproj.user3
-rw-r--r--bin/dnssec/win32/keygen.dsp.in103
-rw-r--r--bin/dnssec/win32/keygen.dsw29
-rw-r--r--bin/dnssec/win32/keygen.mak.in324
-rw-r--r--bin/dnssec/win32/keygen.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/keygen.vcxproj.in112
-rw-r--r--bin/dnssec/win32/keygen.vcxproj.user3
-rw-r--r--bin/dnssec/win32/revoke.dsp.in103
-rw-r--r--bin/dnssec/win32/revoke.dsw29
-rw-r--r--bin/dnssec/win32/revoke.mak.in324
-rw-r--r--bin/dnssec/win32/revoke.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/revoke.vcxproj.in112
-rw-r--r--bin/dnssec/win32/revoke.vcxproj.user3
-rw-r--r--bin/dnssec/win32/settime.dsp.in103
-rw-r--r--bin/dnssec/win32/settime.dsw29
-rw-r--r--bin/dnssec/win32/settime.mak.in324
-rw-r--r--bin/dnssec/win32/settime.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/settime.vcxproj.in112
-rw-r--r--bin/dnssec/win32/settime.vcxproj.user3
-rw-r--r--bin/dnssec/win32/signzone.dsp.in103
-rw-r--r--bin/dnssec/win32/signzone.dsw29
-rw-r--r--bin/dnssec/win32/signzone.mak.in324
-rw-r--r--bin/dnssec/win32/signzone.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/signzone.vcxproj.in112
-rw-r--r--bin/dnssec/win32/signzone.vcxproj.user3
-rw-r--r--bin/dnssec/win32/verify.dsp.in103
-rw-r--r--bin/dnssec/win32/verify.dsw29
-rw-r--r--bin/dnssec/win32/verify.mak.in324
-rw-r--r--bin/dnssec/win32/verify.vcxproj.filters.in18
-rw-r--r--bin/dnssec/win32/verify.vcxproj.in112
-rw-r--r--bin/dnssec/win32/verify.vcxproj.user3
-rw-r--r--bin/named/Makefile.in192
-rw-r--r--bin/named/bind9.xsl1019
-rw-r--r--bin/named/bind9.xsl.h1024
-rw-r--r--bin/named/builtin.c571
-rw-r--r--bin/named/client.c3964
-rw-r--r--bin/named/config.c1018
-rw-r--r--bin/named/control.c293
-rw-r--r--bin/named/controlconf.c1530
-rwxr-xr-xbin/named/convertxsl.pl51
-rw-r--r--bin/named/fuzz.c483
-rw-r--r--bin/named/geoip.c145
-rw-r--r--bin/named/include/dlz/dlz_dlopen_driver.h21
-rw-r--r--bin/named/include/named/builtin.h25
-rw-r--r--bin/named/include/named/client.h426
-rw-r--r--bin/named/include/named/config.h77
-rw-r--r--bin/named/include/named/control.h108
-rw-r--r--bin/named/include/named/fuzz.h30
-rw-r--r--bin/named/include/named/geoip.h26
-rw-r--r--bin/named/include/named/globals.h200
-rw-r--r--bin/named/include/named/interfacemgr.h183
-rw-r--r--bin/named/include/named/listenlist.h101
-rw-r--r--bin/named/include/named/log.h94
-rw-r--r--bin/named/include/named/logconf.h27
-rw-r--r--bin/named/include/named/lwaddr.h30
-rw-r--r--bin/named/include/named/lwdclient.h229
-rw-r--r--bin/named/include/named/lwresd.h117
-rw-r--r--bin/named/include/named/lwsearch.h106
-rw-r--r--bin/named/include/named/main.h36
-rw-r--r--bin/named/include/named/notify.h49
-rw-r--r--bin/named/include/named/ns_smf_globals.h39
-rw-r--r--bin/named/include/named/query.h115
-rw-r--r--bin/named/include/named/seccomp.h248
-rw-r--r--bin/named/include/named/server.h762
-rw-r--r--bin/named/include/named/sortlist.h81
-rw-r--r--bin/named/include/named/statschannel.h56
-rw-r--r--bin/named/include/named/tkeyconf.h47
-rw-r--r--bin/named/include/named/tsigconf.h44
-rw-r--r--bin/named/include/named/types.h49
-rw-r--r--bin/named/include/named/update.h44
-rw-r--r--bin/named/include/named/xfrout.h33
-rw-r--r--bin/named/include/named/zoneconf.h72
-rw-r--r--bin/named/interfacemgr.c1246
-rw-r--r--bin/named/listenlist.c135
-rw-r--r--bin/named/log.c261
-rw-r--r--bin/named/logconf.c338
-rw-r--r--bin/named/lwaddr.c88
-rw-r--r--bin/named/lwdclient.c510
-rw-r--r--bin/named/lwderror.c74
-rw-r--r--bin/named/lwdgabn.c651
-rw-r--r--bin/named/lwdgnba.c264
-rw-r--r--bin/named/lwdgrbn.c514
-rw-r--r--bin/named/lwdnoop.c81
-rw-r--r--bin/named/lwresd.8250
-rw-r--r--bin/named/lwresd.c892
-rw-r--r--bin/named/lwresd.docbook364
-rw-r--r--bin/named/lwresd.html295
-rw-r--r--bin/named/lwsearch.c199
-rw-r--r--bin/named/main.c1543
-rw-r--r--bin/named/named.8379
-rw-r--r--bin/named/named.conf.51028
-rw-r--r--bin/named/named.conf.docbook1006
-rw-r--r--bin/named/named.conf.html1002
-rw-r--r--bin/named/named.docbook547
-rw-r--r--bin/named/named.html456
-rw-r--r--bin/named/notify.c167
-rw-r--r--bin/named/query.c9615
-rw-r--r--bin/named/server.c14277
-rw-r--r--bin/named/sortlist.c164
-rw-r--r--bin/named/statschannel.c3583
-rw-r--r--bin/named/tkeyconf.c127
-rw-r--r--bin/named/tsigconf.c179
-rw-r--r--bin/named/unix/Makefile.in29
-rw-r--r--bin/named/unix/dlz_dlopen_driver.c633
-rw-r--r--bin/named/unix/include/named/os.h79
-rw-r--r--bin/named/unix/os.c1114
-rw-r--r--bin/named/update.c3501
-rw-r--r--bin/named/win32/dlz_dlopen_driver.c618
-rw-r--r--bin/named/win32/include/named/ntservice.h28
-rw-r--r--bin/named/win32/include/named/os.h76
-rw-r--r--bin/named/win32/named.dsp.in341
-rw-r--r--bin/named/win32/named.dsw29
-rw-r--r--bin/named/win32/named.mak.in1233
-rw-r--r--bin/named/win32/named.vcxproj.filters.in211
-rw-r--r--bin/named/win32/named.vcxproj.in177
-rw-r--r--bin/named/win32/named.vcxproj.user3
-rw-r--r--bin/named/win32/ntservice.c171
-rw-r--r--bin/named/win32/os.c460
-rw-r--r--bin/named/xfrout.c1714
-rw-r--r--bin/named/zoneconf.c1824
-rw-r--r--bin/nsupdate/Makefile.in95
-rw-r--r--bin/nsupdate/nsupdate.1524
-rw-r--r--bin/nsupdate/nsupdate.c3318
-rw-r--r--bin/nsupdate/nsupdate.docbook926
-rw-r--r--bin/nsupdate/nsupdate.html783
-rw-r--r--bin/nsupdate/win32/nsupdate.dsp.in103
-rw-r--r--bin/nsupdate/win32/nsupdate.dsw29
-rw-r--r--bin/nsupdate/win32/nsupdate.mak.in375
-rw-r--r--bin/nsupdate/win32/nsupdate.vcxproj.filters.in18
-rw-r--r--bin/nsupdate/win32/nsupdate.vcxproj.in110
-rw-r--r--bin/nsupdate/win32/nsupdate.vcxproj.user3
-rw-r--r--bin/pkcs11/Makefile.in103
-rw-r--r--bin/pkcs11/OLD-PKCS11-NOTES94
-rw-r--r--bin/pkcs11/openssl-0.9.8zh-patch15909
-rw-r--r--bin/pkcs11/openssl-1.0.0t-patch15889
-rw-r--r--bin/pkcs11/openssl-1.0.1t-patch15791
-rw-r--r--bin/pkcs11/openssl-1.0.2h-patch15818
-rw-r--r--bin/pkcs11/pkcs11-destroy.897
-rw-r--r--bin/pkcs11/pkcs11-destroy.c268
-rw-r--r--bin/pkcs11/pkcs11-destroy.docbook153
-rw-r--r--bin/pkcs11/pkcs11-destroy.html128
-rw-r--r--bin/pkcs11/pkcs11-keygen.8120
-rw-r--r--bin/pkcs11/pkcs11-keygen.c757
-rw-r--r--bin/pkcs11/pkcs11-keygen.docbook205
-rw-r--r--bin/pkcs11/pkcs11-keygen.html166
-rw-r--r--bin/pkcs11/pkcs11-list.898
-rw-r--r--bin/pkcs11/pkcs11-list.c272
-rw-r--r--bin/pkcs11/pkcs11-list.docbook149
-rw-r--r--bin/pkcs11/pkcs11-list.html124
-rw-r--r--bin/pkcs11/pkcs11-tokens.869
-rw-r--r--bin/pkcs11/pkcs11-tokens.c104
-rw-r--r--bin/pkcs11/pkcs11-tokens.docbook101
-rw-r--r--bin/pkcs11/pkcs11-tokens.html89
-rw-r--r--bin/pkcs11/win32/pk11destroy.dsp.in103
-rw-r--r--bin/pkcs11/win32/pk11destroy.dsw29
-rw-r--r--bin/pkcs11/win32/pk11destroy.mak.in296
-rw-r--r--bin/pkcs11/win32/pk11destroy.vcxproj.filters.in22
-rw-r--r--bin/pkcs11/win32/pk11destroy.vcxproj.in112
-rw-r--r--bin/pkcs11/win32/pk11destroy.vcxproj.user3
-rw-r--r--bin/pkcs11/win32/pk11keygen.dsp.in103
-rw-r--r--bin/pkcs11/win32/pk11keygen.dsw29
-rw-r--r--bin/pkcs11/win32/pk11keygen.mak.in296
-rw-r--r--bin/pkcs11/win32/pk11keygen.vcxproj.filters.in22
-rw-r--r--bin/pkcs11/win32/pk11keygen.vcxproj.in112
-rw-r--r--bin/pkcs11/win32/pk11keygen.vcxproj.user3
-rw-r--r--bin/pkcs11/win32/pk11list.dsp.in103
-rw-r--r--bin/pkcs11/win32/pk11list.dsw29
-rw-r--r--bin/pkcs11/win32/pk11list.mak.in296
-rw-r--r--bin/pkcs11/win32/pk11list.vcxproj.filters.in22
-rw-r--r--bin/pkcs11/win32/pk11list.vcxproj.in112
-rw-r--r--bin/pkcs11/win32/pk11list.vcxproj.user3
-rw-r--r--bin/pkcs11/win32/pk11tokens.dsp.in103
-rw-r--r--bin/pkcs11/win32/pk11tokens.dsw29
-rw-r--r--bin/pkcs11/win32/pk11tokens.mak.in296
-rw-r--r--bin/pkcs11/win32/pk11tokens.vcxproj.filters.in22
-rw-r--r--bin/pkcs11/win32/pk11tokens.vcxproj.in112
-rw-r--r--bin/pkcs11/win32/pk11tokens.vcxproj.user3
-rw-r--r--bin/python/Makefile.in80
-rw-r--r--bin/python/dnssec-checkds.887
-rw-r--r--bin/python/dnssec-checkds.docbook136
-rw-r--r--bin/python/dnssec-checkds.html115
-rw-r--r--bin/python/dnssec-checkds.py.in27
-rw-r--r--bin/python/dnssec-coverage.8156
-rw-r--r--bin/python/dnssec-coverage.docbook271
-rw-r--r--bin/python/dnssec-coverage.html236
-rw-r--r--bin/python/dnssec-coverage.py.in27
-rw-r--r--bin/python/dnssec-keymgr.8301
-rw-r--r--bin/python/dnssec-keymgr.docbook417
-rw-r--r--bin/python/dnssec-keymgr.html364
-rw-r--r--bin/python/dnssec-keymgr.py.in27
-rw-r--r--bin/python/isc/Makefile.in43
-rw-r--r--bin/python/isc/__init__.py.in24
-rw-r--r--bin/python/isc/checkds.py.in185
-rw-r--r--bin/python/isc/coverage.py.in286
-rw-r--r--bin/python/isc/dnskey.py.in507
-rw-r--r--bin/python/isc/eventlist.py.in166
-rw-r--r--bin/python/isc/keydict.py.in84
-rw-r--r--bin/python/isc/keyevent.py.in76
-rw-r--r--bin/python/isc/keymgr.py.in154
-rw-r--r--bin/python/isc/keyseries.py.in191
-rw-r--r--bin/python/isc/keyzone.py.in55
-rw-r--r--bin/python/isc/policy.py.in728
-rw-r--r--bin/python/isc/rndc.py.in188
-rw-r--r--bin/python/isc/tests/Makefile.in31
-rw-r--r--bin/python/isc/tests/dnskey_test.py.in52
-rw-r--r--bin/python/isc/tests/policy_test.py.in92
-rw-r--r--bin/python/isc/tests/test-policies/01-keysize.pol52
-rw-r--r--bin/python/isc/tests/test-policies/02-prepublish.pol42
-rw-r--r--bin/python/isc/tests/test-policies/03-postpublish.pol42
-rw-r--r--bin/python/isc/tests/test-policies/04-combined-pre-post.pol66
-rw-r--r--bin/python/isc/tests/test-policies/05-numeric-zone.pol15
-rw-r--r--bin/python/isc/tests/testdata/Kexample.com.+007+35529.key8
-rw-r--r--bin/python/isc/tests/testdata/Kexample.com.+007+35529.private18
-rw-r--r--bin/python/isc/utils.py.in71
-rw-r--r--bin/python/setup.py21
-rw-r--r--bin/rndc/Makefile.in91
-rw-r--r--bin/rndc/include/rndc/os.h33
-rw-r--r--bin/rndc/rndc.8629
-rw-r--r--bin/rndc/rndc.c984
-rw-r--r--bin/rndc/rndc.conf39
-rw-r--r--bin/rndc/rndc.conf.5234
-rw-r--r--bin/rndc/rndc.conf.docbook241
-rw-r--r--bin/rndc/rndc.conf.html234
-rw-r--r--bin/rndc/rndc.docbook1014
-rw-r--r--bin/rndc/rndc.html860
-rw-r--r--bin/rndc/util.c51
-rw-r--r--bin/rndc/util.h46
-rw-r--r--bin/rndc/win32/rndc.dsp.in107
-rw-r--r--bin/rndc/win32/rndc.dsw29
-rw-r--r--bin/rndc/win32/rndc.mak.in425
-rw-r--r--bin/rndc/win32/rndc.vcxproj.filters.in27
-rw-r--r--bin/rndc/win32/rndc.vcxproj.in113
-rw-r--r--bin/rndc/win32/rndc.vcxproj.user3
-rw-r--r--bin/rndc/win32/rndcutil.dsp.in119
-rw-r--r--bin/rndc/win32/rndcutil.dsw29
-rw-r--r--bin/rndc/win32/rndcutil.vcxproj.filters.in27
-rw-r--r--bin/rndc/win32/rndcutil.vcxproj.in104
-rw-r--r--bin/rndc/win32/rndcutil.vcxproj.user3
-rw-r--r--bin/tests/Makefile.in85
-rw-r--r--bin/tests/bigtest/README18
-rw-r--r--bin/tests/bigtest/buildzones.sh267
-rw-r--r--bin/tests/bigtest/rndc.key5
-rw-r--r--bin/tests/bigtest/tests.sh76
-rw-r--r--bin/tests/bigtest/zones18
-rw-r--r--bin/tests/cfg_test.c184
-rw-r--r--bin/tests/fromhex.pl45
-rw-r--r--bin/tests/headerdep_test.sh.in49
-rw-r--r--bin/tests/makejournal.c167
-rw-r--r--bin/tests/named.conf617
-rw-r--r--bin/tests/optional/Kchild.example.+003+04017.key1
-rw-r--r--bin/tests/optional/Kchild.example.+003+04017.private7
-rw-r--r--bin/tests/optional/Makefile.in299
-rw-r--r--bin/tests/optional/adb_test.c431
-rw-r--r--bin/tests/optional/backtrace_test.c91
-rw-r--r--bin/tests/optional/byaddr_test.c259
-rw-r--r--bin/tests/optional/byname_test.c368
-rw-r--r--bin/tests/optional/db_test.c936
-rw-r--r--bin/tests/optional/dst_test.c293
-rw-r--r--bin/tests/optional/entropy2_test.c168
-rw-r--r--bin/tests/optional/entropy_test.c133
-rw-r--r--bin/tests/optional/fsaccess_test.c70
-rw-r--r--bin/tests/optional/gsstest.c563
-rw-r--r--bin/tests/optional/gxba_test.c91
-rw-r--r--bin/tests/optional/gxbn_test.c79
-rw-r--r--bin/tests/optional/hash_test.c288
-rw-r--r--bin/tests/optional/inter_test.c130
-rw-r--r--bin/tests/optional/keyboard_test.c67
-rw-r--r--bin/tests/optional/lex_test.c153
-rw-r--r--bin/tests/optional/lfsr_test.c89
-rw-r--r--bin/tests/optional/log_test.c345
-rw-r--r--bin/tests/optional/lwres_test.c298
-rw-r--r--bin/tests/optional/lwresconf_test.c91
-rw-r--r--bin/tests/optional/master_test.c88
-rw-r--r--bin/tests/optional/mempool_test.c120
-rw-r--r--bin/tests/optional/name_test.c340
-rw-r--r--bin/tests/optional/nsecify.c208
-rw-r--r--bin/tests/optional/ratelimiter_test.c146
-rw-r--r--bin/tests/optional/rbt_test.c445
-rw-r--r--bin/tests/optional/rbt_test.out395
-rw-r--r--bin/tests/optional/rbt_test.txt85
-rw-r--r--bin/tests/optional/rwlock_test.c144
-rw-r--r--bin/tests/optional/serial_test.c44
-rw-r--r--bin/tests/optional/shutdown_test.c231
-rw-r--r--bin/tests/optional/sig0_test.c295
-rw-r--r--bin/tests/optional/sock_test.c400
-rw-r--r--bin/tests/optional/sym_test.c121
-rw-r--r--bin/tests/optional/task_test.c203
-rw-r--r--bin/tests/optional/timer_test.c181
-rw-r--r--bin/tests/optional/zone_test.c309
-rw-r--r--bin/tests/pkcs11/Makefile.in44
-rw-r--r--bin/tests/pkcs11/README15
-rw-r--r--bin/tests/pkcs11/benchmarks/Makefile.in83
-rw-r--r--bin/tests/pkcs11/benchmarks/create.c263
-rw-r--r--bin/tests/pkcs11/benchmarks/find.c232
-rw-r--r--bin/tests/pkcs11/benchmarks/genrsa.c298
-rw-r--r--bin/tests/pkcs11/benchmarks/login.c252
-rw-r--r--bin/tests/pkcs11/benchmarks/privrsa.c363
-rw-r--r--bin/tests/pkcs11/benchmarks/pubrsa.c284
-rw-r--r--bin/tests/pkcs11/benchmarks/random.c194
-rw-r--r--bin/tests/pkcs11/benchmarks/session.c216
-rw-r--r--bin/tests/pkcs11/benchmarks/sha1.c217
-rw-r--r--bin/tests/pkcs11/benchmarks/sign.c371
-rw-r--r--bin/tests/pkcs11/benchmarks/verify.c295
-rw-r--r--bin/tests/pkcs11/pkcs11-hmacmd5.c327
-rw-r--r--bin/tests/pkcs11/pkcs11-md5sum.c230
-rw-r--r--bin/tests/startperf/README17
-rw-r--r--bin/tests/startperf/clean.sh13
-rw-r--r--bin/tests/startperf/makenames.pl28
-rw-r--r--bin/tests/startperf/mkzonefile.pl45
-rw-r--r--bin/tests/startperf/setup.sh80
-rw-r--r--bin/tests/startperf/smallzone.db26
-rw-r--r--bin/tests/system/Makefile.in140
-rw-r--r--bin/tests/system/README773
-rw-r--r--bin/tests/system/acl/clean.sh23
-rw-r--r--bin/tests/system/acl/ns2/named1.conf.in59
-rw-r--r--bin/tests/system/acl/ns2/named2.conf.in63
-rw-r--r--bin/tests/system/acl/ns2/named3.conf.in72
-rw-r--r--bin/tests/system/acl/ns2/named4.conf.in71
-rw-r--r--bin/tests/system/acl/ns2/named5.conf.in60
-rw-r--r--bin/tests/system/acl/ns2/named6.conf.in50
-rw-r--r--bin/tests/system/acl/ns2/named7.conf.in60
-rw-r--r--bin/tests/system/acl/ns3/example.db19
-rw-r--r--bin/tests/system/acl/ns3/named.conf.in33
-rw-r--r--bin/tests/system/acl/ns4/example.db19
-rw-r--r--bin/tests/system/acl/ns4/existing.db19
-rw-r--r--bin/tests/system/acl/ns4/named.conf.in38
-rw-r--r--bin/tests/system/acl/setup.sh20
-rw-r--r--bin/tests/system/acl/tests.sh236
-rw-r--r--bin/tests/system/additional/clean.sh20
-rw-r--r--bin/tests/system/additional/ns1/mx.db16
-rw-r--r--bin/tests/system/additional/ns1/named.args2
-rw-r--r--bin/tests/system/additional/ns1/named1.conf.in55
-rw-r--r--bin/tests/system/additional/ns1/named2.conf.in55
-rw-r--r--bin/tests/system/additional/ns1/named3.conf.in56
-rw-r--r--bin/tests/system/additional/ns1/named4.conf.in65
-rw-r--r--bin/tests/system/additional/ns1/naptr.db18
-rw-r--r--bin/tests/system/additional/ns1/naptr2.db18
-rw-r--r--bin/tests/system/additional/ns1/nid.db19
-rw-r--r--bin/tests/system/additional/ns1/rt.db18
-rw-r--r--bin/tests/system/additional/ns1/rt2.db18
-rw-r--r--bin/tests/system/additional/ns1/srv.db16
-rw-r--r--bin/tests/system/additional/ns3/named.conf.in28
-rw-r--r--bin/tests/system/additional/ns3/root.hint11
-rw-r--r--bin/tests/system/additional/setup.sh17
-rw-r--r--bin/tests/system/additional/tests.sh330
-rw-r--r--bin/tests/system/addzone/clean.sh29
-rw-r--r--bin/tests/system/addzone/ns1/inlineslave.db24
-rw-r--r--bin/tests/system/addzone/ns1/named.conf.in35
-rw-r--r--bin/tests/system/addzone/ns2/added.db24
-rw-r--r--bin/tests/system/addzone/ns2/default.nzf.in1
-rw-r--r--bin/tests/system/addzone/ns2/hints.db12
-rw-r--r--bin/tests/system/addzone/ns2/inline.db24
-rw-r--r--bin/tests/system/addzone/ns2/named1.conf.in41
-rw-r--r--bin/tests/system/addzone/ns2/named2.conf.in65
-rw-r--r--bin/tests/system/addzone/ns2/normal.db24
-rw-r--r--bin/tests/system/addzone/ns2/previous.db24
-rw-r--r--bin/tests/system/addzone/ns2/redirect.db11
-rw-r--r--bin/tests/system/addzone/ns3/e.db12
-rw-r--r--bin/tests/system/addzone/ns3/named1.conf.in30
-rw-r--r--bin/tests/system/addzone/ns3/named2.conf.in26
-rw-r--r--bin/tests/system/addzone/setup.sh24
-rwxr-xr-xbin/tests/system/addzone/tests.sh539
-rw-r--r--bin/tests/system/allow-query/clean.sh21
-rw-r--r--bin/tests/system/allow-query/ns1/named.conf.in23
-rw-r--r--bin/tests/system/allow-query/ns1/root.db16
-rw-r--r--bin/tests/system/allow-query/ns2/generic.db24
-rw-r--r--bin/tests/system/allow-query/ns2/named01.conf.in32
-rw-r--r--bin/tests/system/allow-query/ns2/named02.conf.in33
-rw-r--r--bin/tests/system/allow-query/ns2/named03.conf.in33
-rw-r--r--bin/tests/system/allow-query/ns2/named04.conf.in33
-rw-r--r--bin/tests/system/allow-query/ns2/named05.conf.in33
-rw-r--r--bin/tests/system/allow-query/ns2/named06.conf.in33
-rw-r--r--bin/tests/system/allow-query/ns2/named07.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns2/named08.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns2/named09.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns2/named10.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named11.conf.in44
-rw-r--r--bin/tests/system/allow-query/ns2/named12.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named21.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns2/named22.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named23.conf.in37
-rw-r--r--bin/tests/system/allow-query/ns2/named24.conf.in37
-rw-r--r--bin/tests/system/allow-query/ns2/named25.conf.in37
-rw-r--r--bin/tests/system/allow-query/ns2/named26.conf.in37
-rw-r--r--bin/tests/system/allow-query/ns2/named27.conf.in40
-rw-r--r--bin/tests/system/allow-query/ns2/named28.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named29.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named30.conf.in42
-rw-r--r--bin/tests/system/allow-query/ns2/named31.conf.in49
-rw-r--r--bin/tests/system/allow-query/ns2/named32.conf.in42
-rw-r--r--bin/tests/system/allow-query/ns2/named33.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named34.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named40.conf.in107
-rw-r--r--bin/tests/system/allow-query/ns2/named53.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named54.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named55.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named56.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named57.conf.in42
-rw-r--r--bin/tests/system/allow-query/ns3/named.args2
-rw-r--r--bin/tests/system/allow-query/ns3/named.conf.in24
-rw-r--r--bin/tests/system/allow-query/setup.sh18
-rw-r--r--bin/tests/system/allow-query/tests.sh617
-rw-r--r--bin/tests/system/ans.pl519
-rw-r--r--bin/tests/system/autosign/clean.sh64
-rw-r--r--bin/tests/system/autosign/ns1/keygen.sh52
-rw-r--r--bin/tests/system/autosign/ns1/named.conf.in46
-rw-r--r--bin/tests/system/autosign/ns1/root.db.in24
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+005+30676.key5
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+005+30676.private13
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+005+30804.key5
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+005+30804.private13
-rw-r--r--bin/tests/system/autosign/ns2/bar.db.in78
-rw-r--r--bin/tests/system/autosign/ns2/child.nsec3.example.db18
-rw-r--r--bin/tests/system/autosign/ns2/child.optout.example.db18
-rw-r--r--bin/tests/system/autosign/ns2/dst.example.db.in19
-rw-r--r--bin/tests/system/autosign/ns2/example.db.in84
-rw-r--r--bin/tests/system/autosign/ns2/insecure.secure.example.db24
-rw-r--r--bin/tests/system/autosign/ns2/keygen.sh52
-rw-r--r--bin/tests/system/autosign/ns2/named.conf.in98
-rw-r--r--bin/tests/system/autosign/ns2/private.secure.example.db.in25
-rw-r--r--bin/tests/system/autosign/ns3/autonsec3.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/delay.example.db24
-rw-r--r--bin/tests/system/autosign/ns3/delzsk.example.db.in23
-rw-r--r--bin/tests/system/autosign/ns3/inacksk2.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/inacksk3.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/inaczsk.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/inaczsk2.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/inaczsk3.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/insecure.example.db24
-rw-r--r--bin/tests/system/autosign/ns3/keygen.sh318
-rw-r--r--bin/tests/system/autosign/ns3/named.conf.in284
-rw-r--r--bin/tests/system/autosign/ns3/nozsk.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/nsec.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/nsec3.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/nsec3.optout.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/oldsigs.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/optout.example.db.in36
-rw-r--r--bin/tests/system/autosign/ns3/optout.nsec3.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/optout.optout.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/rsasha256.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/rsasha512.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/secure-to-insecure2.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/secure.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/secure.nsec3.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/secure.optout.example.db.in33
-rw-r--r--bin/tests/system/autosign/ns3/sync.example.db.in32
-rw-r--r--bin/tests/system/autosign/ns3/ttl1.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/ttl2.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/ttl3.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns3/ttl4.example.db.in24
-rw-r--r--bin/tests/system/autosign/ns4/named.conf.in34
-rw-r--r--bin/tests/system/autosign/ns5/named.conf.in33
-rw-r--r--bin/tests/system/autosign/prereq.sh15
-rw-r--r--bin/tests/system/autosign/setup.sh26
-rwxr-xr-xbin/tests/system/autosign/tests.sh1428
-rw-r--r--bin/tests/system/builtin/clean.sh17
-rw-r--r--bin/tests/system/builtin/ns1/named.conf.in28
-rw-r--r--bin/tests/system/builtin/ns2/named.conf.in29
-rw-r--r--bin/tests/system/builtin/ns3/named.conf.in31
-rw-r--r--bin/tests/system/builtin/setup.sh18
-rw-r--r--bin/tests/system/builtin/tests.sh242
-rw-r--r--bin/tests/system/cacheclean/clean.sh23
-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.db2940
-rw-r--r--bin/tests/system/cacheclean/ns1/expire-test.db19
-rw-r--r--bin/tests/system/cacheclean/ns1/flushtest.db42
-rw-r--r--bin/tests/system/cacheclean/ns1/named.conf.in38
-rw-r--r--bin/tests/system/cacheclean/ns2/named.conf.in47
-rw-r--r--bin/tests/system/cacheclean/setup.sh17
-rwxr-xr-xbin/tests/system/cacheclean/tests.sh257
-rw-r--r--bin/tests/system/case/clean.sh21
-rw-r--r--bin/tests/system/case/dynamic.good6
-rw-r--r--bin/tests/system/case/ns1/dynamic.db.in25
-rw-r--r--bin/tests/system/case/ns1/example.db22
-rw-r--r--bin/tests/system/case/ns1/named.conf.in37
-rw-r--r--bin/tests/system/case/ns2/named.conf.in37
-rw-r--r--bin/tests/system/case/postns1.good14
-rw-r--r--bin/tests/system/case/postupdate.good6
-rw-r--r--bin/tests/system/case/setup.sh16
-rw-r--r--bin/tests/system/case/tests.sh138
-rw-r--r--bin/tests/system/catz/clean.sh24
-rw-r--r--bin/tests/system/catz/ns1/catalog.example.db.in12
-rw-r--r--bin/tests/system/catz/ns1/named.conf.in65
-rw-r--r--bin/tests/system/catz/ns2/named.conf.in74
-rw-r--r--bin/tests/system/catz/ns3/dom5.example.db11
-rw-r--r--bin/tests/system/catz/ns3/dom6.example.db11
-rw-r--r--bin/tests/system/catz/ns3/named.conf.in55
-rw-r--r--bin/tests/system/catz/setup.sh26
-rw-r--r--bin/tests/system/catz/tests.sh1999
-rw-r--r--bin/tests/system/chain/README15
-rw-r--r--bin/tests/system/chain/ans3/ans.pl101
-rw-r--r--bin/tests/system/chain/ans4/README.anspy17
-rwxr-xr-xbin/tests/system/chain/ans4/ans.py347
-rwxr-xr-xbin/tests/system/chain/clean.sh15
-rw-r--r--bin/tests/system/chain/ns1/named.conf.in25
-rw-r--r--bin/tests/system/chain/ns1/root.db45
-rw-r--r--bin/tests/system/chain/ns2/example.db67
-rw-r--r--bin/tests/system/chain/ns2/generic.db17
-rw-r--r--bin/tests/system/chain/ns2/named.conf.in51
-rw-r--r--bin/tests/system/chain/ns2/sign.sh20
-rw-r--r--bin/tests/system/chain/ns2/sub.db24
-rw-r--r--bin/tests/system/chain/ns5/named.conf.in39
-rw-r--r--bin/tests/system/chain/ns5/sub.db24
-rw-r--r--bin/tests/system/chain/ns7/named.conf.in43
-rw-r--r--bin/tests/system/chain/ns7/root.hint12
-rw-r--r--bin/tests/system/chain/prereq.sh50
-rw-r--r--bin/tests/system/chain/setup.sh25
-rw-r--r--bin/tests/system/chain/tests.sh269
-rw-r--r--bin/tests/system/checkconf/altdb.conf17
-rw-r--r--bin/tests/system/checkconf/altdlz.conf25
-rw-r--r--bin/tests/system/checkconf/bad-also-notify.conf20
-rw-r--r--bin/tests/system/checkconf/bad-catz-zone.conf16
-rw-r--r--bin/tests/system/checkconf/bad-dnssec.conf29
-rw-r--r--bin/tests/system/checkconf/bad-hint.conf16
-rw-r--r--bin/tests/system/checkconf/bad-in-view-dup.conf19
-rw-r--r--bin/tests/system/checkconf/bad-inline-slave.conf20
-rw-r--r--bin/tests/system/checkconf/bad-keep-response-order.conf16
-rw-r--r--bin/tests/system/checkconf/bad-lifetime.conf14
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf14
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf14
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf14
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf14
-rw-r--r--bin/tests/system/checkconf/bad-many.conf46
-rw-r--r--bin/tests/system/checkconf/bad-master-request-ixfr.conf20
-rw-r--r--bin/tests/system/checkconf/bad-maxttlmap.conf17
-rw-r--r--bin/tests/system/checkconf/bad-noddns.conf17
-rw-r--r--bin/tests/system/checkconf/bad-options-also-notify.conf19
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-acl.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-slip.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-window.conf16
-rw-r--r--bin/tests/system/checkconf/bad-rpz-zone.conf16
-rw-r--r--bin/tests/system/checkconf/bad-sharedwritable1.conf20
-rw-r--r--bin/tests/system/checkconf/bad-sharedwritable2.conf21
-rw-r--r--bin/tests/system/checkconf/bad-sharedzone1.conf29
-rw-r--r--bin/tests/system/checkconf/bad-sharedzone2.conf31
-rw-r--r--bin/tests/system/checkconf/bad-sharedzone3.conf23
-rw-r--r--bin/tests/system/checkconf/bad-tsig.conf17
-rw-r--r--bin/tests/system/checkconf/bad-update-policy1.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy10.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy11.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy12.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy13.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy14.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy15.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy2.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy3.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy4.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy5.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy6.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy7.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy8.conf18
-rw-r--r--bin/tests/system/checkconf/bad-update-policy9.conf18
-rw-r--r--bin/tests/system/checkconf/bad-view-also-notify.conf18
-rw-r--r--bin/tests/system/checkconf/check-dlv-ksk-key.conf20
-rw-r--r--bin/tests/system/checkconf/check-dup-records-fail.conf21
-rw-r--r--bin/tests/system/checkconf/check-dup-records.db31
-rw-r--r--bin/tests/system/checkconf/check-mx-cname-fail.conf20
-rw-r--r--bin/tests/system/checkconf/check-mx-cname.db24
-rw-r--r--bin/tests/system/checkconf/check-mx-fail.conf20
-rw-r--r--bin/tests/system/checkconf/check-mx.db22
-rw-r--r--bin/tests/system/checkconf/check-names-fail.conf20
-rw-r--r--bin/tests/system/checkconf/check-names.db26
-rw-r--r--bin/tests/system/checkconf/check-root-ksk-2010.conf24
-rw-r--r--bin/tests/system/checkconf/check-root-ksk-2017.conf27
-rw-r--r--bin/tests/system/checkconf/check-root-ksk-both.conf39
-rw-r--r--bin/tests/system/checkconf/check-srv-cname-fail.conf20
-rw-r--r--bin/tests/system/checkconf/check-srv-cname.db26
-rw-r--r--bin/tests/system/checkconf/clean.sh15
-rw-r--r--bin/tests/system/checkconf/dlz-bad.conf25
-rw-r--r--bin/tests/system/checkconf/dnssec.115
-rw-r--r--bin/tests/system/checkconf/dnssec.229
-rw-r--r--bin/tests/system/checkconf/dnssec.339
-rw-r--r--bin/tests/system/checkconf/good-acl.conf19
-rw-r--r--bin/tests/system/checkconf/good-class.conf12
-rw-r--r--bin/tests/system/checkconf/good-dlv-dlv.example.com.conf14
-rw-r--r--bin/tests/system/checkconf/good-lmdb-mapsize-largest.conf14
-rw-r--r--bin/tests/system/checkconf/good-lmdb-mapsize-smallest.conf14
-rw-r--r--bin/tests/system/checkconf/good-nested.conf18
-rw-r--r--bin/tests/system/checkconf/good-options-also-notify.conf20
-rw-r--r--bin/tests/system/checkconf/good-response-dot.conf21
-rw-r--r--bin/tests/system/checkconf/good-update-policy1.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy10.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy11.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy12.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy2.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy3.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy4.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy5.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy6.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy7.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy8.conf18
-rw-r--r--bin/tests/system/checkconf/good-update-policy9.conf18
-rw-r--r--bin/tests/system/checkconf/good-view-also-notify.conf19
-rw-r--r--bin/tests/system/checkconf/good.conf158
-rw-r--r--bin/tests/system/checkconf/hint-nofile.conf15
-rw-r--r--bin/tests/system/checkconf/in-view-good.conf23
-rw-r--r--bin/tests/system/checkconf/inline-bad.conf25
-rw-r--r--bin/tests/system/checkconf/inline-good.conf26
-rw-r--r--bin/tests/system/checkconf/inline-no.conf25
-rw-r--r--bin/tests/system/checkconf/max-cache-size-good.conf14
-rw-r--r--bin/tests/system/checkconf/max-ttl.conf32
-rw-r--r--bin/tests/system/checkconf/maxttl-bad.conf22
-rw-r--r--bin/tests/system/checkconf/maxttl-bad.db23
-rw-r--r--bin/tests/system/checkconf/maxttl.db23
-rw-r--r--bin/tests/system/checkconf/notify.conf82
-rw-r--r--bin/tests/system/checkconf/portrange-good.conf20
-rw-r--r--bin/tests/system/checkconf/range.conf23
-rw-r--r--bin/tests/system/checkconf/shared.example.db11
-rw-r--r--bin/tests/system/checkconf/tests.sh394
-rw-r--r--bin/tests/system/checkconf/view-class-any1.conf12
-rw-r--r--bin/tests/system/checkconf/view-class-any2.conf12
-rw-r--r--bin/tests/system/checkconf/view-class-in1.conf12
-rw-r--r--bin/tests/system/checkconf/view-class-in2.conf12
-rw-r--r--bin/tests/system/checkconf/warn-dlv-auto.conf14
-rw-r--r--bin/tests/system/checkconf/warn-dlv-dlv.isc.org.conf14
-rw-r--r--bin/tests/system/checkconf/warn-keydir.conf23
-rw-r--r--bin/tests/system/checkds/clean.sh15
-rwxr-xr-xbin/tests/system/checkds/dig.bat38
-rw-r--r--bin/tests/system/checkds/dig.pl45
-rwxr-xr-xbin/tests/system/checkds/dig.sh26
-rw-r--r--bin/tests/system/checkds/missing.example.dlv.example.dlv.db2
-rw-r--r--bin/tests/system/checkds/missing.example.dnskey.db3
-rw-r--r--bin/tests/system/checkds/missing.example.ds.db2
-rw-r--r--bin/tests/system/checkds/none.example.dlv.example.dlv.db0
-rw-r--r--bin/tests/system/checkds/none.example.dnskey.db3
-rw-r--r--bin/tests/system/checkds/none.example.ds.db0
-rw-r--r--bin/tests/system/checkds/ok.example.dlv.example.dlv.db2
-rw-r--r--bin/tests/system/checkds/ok.example.dnskey.db2
-rw-r--r--bin/tests/system/checkds/ok.example.ds.db2
-rw-r--r--bin/tests/system/checkds/setup.sh15
-rw-r--r--bin/tests/system/checkds/tests.sh179
-rw-r--r--bin/tests/system/checkds/wrong.example.dlv.example.dlv.db2
-rw-r--r--bin/tests/system/checkds/wrong.example.dnskey.db2
-rw-r--r--bin/tests/system/checkds/wrong.example.ds.db2
-rw-r--r--bin/tests/system/checknames/clean.sh22
-rw-r--r--bin/tests/system/checknames/ns1/fail.example.db.in15
-rw-r--r--bin/tests/system/checknames/ns1/fail.update.db.in14
-rw-r--r--bin/tests/system/checknames/ns1/ignore.example.db.in16
-rw-r--r--bin/tests/system/checknames/ns1/ignore.update.db.in14
-rw-r--r--bin/tests/system/checknames/ns1/named.conf.in67
-rw-r--r--bin/tests/system/checknames/ns1/root.db28
-rw-r--r--bin/tests/system/checknames/ns1/warn.example.db.in15
-rw-r--r--bin/tests/system/checknames/ns1/warn.update.db.in14
-rw-r--r--bin/tests/system/checknames/ns2/named.conf.in29
-rw-r--r--bin/tests/system/checknames/ns2/root.hints12
-rw-r--r--bin/tests/system/checknames/ns3/named.conf.in29
-rw-r--r--bin/tests/system/checknames/ns3/root.hints12
-rw-r--r--bin/tests/system/checknames/ns4/master-ignore.update.db.in14
-rw-r--r--bin/tests/system/checknames/ns4/named.conf.in35
-rw-r--r--bin/tests/system/checknames/ns4/root.hints12
-rw-r--r--bin/tests/system/checknames/setup.sh28
-rw-r--r--bin/tests/system/checknames/tests.sh148
-rw-r--r--bin/tests/system/checkzone/clean.sh11
-rw-r--r--bin/tests/system/checkzone/setup.sh19
-rw-r--r--bin/tests/system/checkzone/tests.sh185
-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 -> 600 bytes
-rw-r--r--bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db19
-rw-r--r--bin/tests/system/checkzone/zones/bad-generate-tkey.db15
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsap-empty.db16
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db16
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsec3-padded.db19
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-tkey.db15
-rw-r--r--bin/tests/system/checkzone/zones/bad-tsig.db15
-rw-r--r--bin/tests/system/checkzone/zones/bad-unspec.db14
-rw-r--r--bin/tests/system/checkzone/zones/bad1.dbbin0 -> 507 bytes
-rw-r--r--bin/tests/system/checkzone/zones/bad2.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad3.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad4.db17
-rw-r--r--bin/tests/system/checkzone/zones/badttl.db18
-rw-r--r--bin/tests/system/checkzone/zones/crashzone.db62
-rw-r--r--bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db22
-rw-r--r--bin/tests/system/checkzone/zones/good-dns-sd-reverse.db21
-rw-r--r--bin/tests/system/checkzone/zones/good-gc-msdcs.db14
-rw-r--r--bin/tests/system/checkzone/zones/good-nsap.db16
-rw-r--r--bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db17
-rw-r--r--bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db20
-rw-r--r--bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db20
-rw-r--r--bin/tests/system/checkzone/zones/good1.db17
-rw-r--r--bin/tests/system/checkzone/zones/inherit.db10
-rw-r--r--bin/tests/system/checkzone/zones/nowarn.inherited.owner.db11
-rw-r--r--bin/tests/system/checkzone/zones/ns-address-below-dname.db20
-rw-r--r--bin/tests/system/checkzone/zones/spf.db16
-rw-r--r--bin/tests/system/checkzone/zones/test1.db16
-rw-r--r--bin/tests/system/checkzone/zones/test2.db17
-rw-r--r--bin/tests/system/checkzone/zones/warn.inherit.origin.db12
-rw-r--r--bin/tests/system/checkzone/zones/warn.inherited.owner.db11
-rw-r--r--bin/tests/system/clean.sh51
-rw-r--r--bin/tests/system/cleanall.sh35
-rw-r--r--bin/tests/system/cleanpkcs11.sh17
-rw-r--r--bin/tests/system/common/controls.conf20
-rw-r--r--bin/tests/system/common/controls.conf.in20
-rw-r--r--bin/tests/system/common/rndc.conf19
-rw-r--r--bin/tests/system/common/rndc.key15
-rw-r--r--bin/tests/system/common/root.hint12
-rw-r--r--bin/tests/system/conf.sh.in366
-rw-r--r--bin/tests/system/conf.sh.win32344
-rw-r--r--bin/tests/system/cookie/bad-cookie-badhex.conf14
-rw-r--r--bin/tests/system/cookie/bad-cookie-badsha1.conf15
-rw-r--r--bin/tests/system/cookie/bad-cookie-badsha256.conf15
-rw-r--r--bin/tests/system/cookie/bad-cookie-toolong.conf14
-rw-r--r--bin/tests/system/cookie/clean.sh15
-rw-r--r--bin/tests/system/cookie/good-cookie-sha1.conf15
-rw-r--r--bin/tests/system/cookie/good-cookie-sha256.conf15
-rw-r--r--bin/tests/system/cookie/ns1/example.db22
-rw-r--r--bin/tests/system/cookie/ns1/named.conf.in49
-rw-r--r--bin/tests/system/cookie/ns1/root.hint12
-rw-r--r--bin/tests/system/cookie/ns2/named.conf.in29
-rw-r--r--bin/tests/system/cookie/ns2/root.db22
-rw-r--r--bin/tests/system/cookie/ns3/named.conf.in50
-rw-r--r--bin/tests/system/cookie/ns3/root.hint12
-rw-r--r--bin/tests/system/cookie/ns4/named.conf.in38
-rw-r--r--bin/tests/system/cookie/ns4/root.hint12
-rw-r--r--bin/tests/system/cookie/ns5/named.conf.in39
-rw-r--r--bin/tests/system/cookie/ns5/root.hint12
-rw-r--r--bin/tests/system/cookie/ns6/named.conf.in38
-rw-r--r--bin/tests/system/cookie/ns6/root.hint12
-rw-r--r--bin/tests/system/cookie/ns7/named.conf.in29
-rw-r--r--bin/tests/system/cookie/ns7/root.db22
-rw-r--r--bin/tests/system/cookie/setup.sh22
-rwxr-xr-xbin/tests/system/cookie/tests.sh273
-rw-r--r--bin/tests/system/coverage/01-ksk-inactive/README10
-rw-r--r--bin/tests/system/coverage/01-ksk-inactive/expect6
-rw-r--r--bin/tests/system/coverage/02-zsk-inactive/README10
-rw-r--r--bin/tests/system/coverage/02-zsk-inactive/expect6
-rw-r--r--bin/tests/system/coverage/03-ksk-unpublished/README10
-rw-r--r--bin/tests/system/coverage/03-ksk-unpublished/expect8
-rw-r--r--bin/tests/system/coverage/04-zsk-unpublished/README10
-rw-r--r--bin/tests/system/coverage/04-zsk-unpublished/expect8
-rw-r--r--bin/tests/system/coverage/05-ksk-unpub-active/README12
-rw-r--r--bin/tests/system/coverage/05-ksk-unpub-active/expect8
-rw-r--r--bin/tests/system/coverage/06-zsk-unpub-active/README12
-rw-r--r--bin/tests/system/coverage/06-zsk-unpub-active/expect8
-rw-r--r--bin/tests/system/coverage/07-ksk-ttl/README4
-rw-r--r--bin/tests/system/coverage/07-ksk-ttl/expect9
-rw-r--r--bin/tests/system/coverage/08-zsk-ttl/README4
-rw-r--r--bin/tests/system/coverage/08-zsk-ttl/expect9
-rw-r--r--bin/tests/system/coverage/09-check-zsk/README6
-rw-r--r--bin/tests/system/coverage/09-check-zsk/expect6
-rw-r--r--bin/tests/system/coverage/10-check-ksk/README7
-rw-r--r--bin/tests/system/coverage/10-check-ksk/expect6
-rw-r--r--bin/tests/system/coverage/11-cutoff/README10
-rw-r--r--bin/tests/system/coverage/11-cutoff/expect6
-rw-r--r--bin/tests/system/coverage/clean.sh16
-rw-r--r--bin/tests/system/coverage/prereq.sh15
-rw-r--r--bin/tests/system/coverage/setup.sh131
-rw-r--r--bin/tests/system/coverage/tests.sh79
-rw-r--r--bin/tests/system/database/clean.sh14
-rw-r--r--bin/tests/system/database/ns1/named1.conf.in40
-rw-r--r--bin/tests/system/database/ns1/named2.conf.in40
-rw-r--r--bin/tests/system/database/setup.sh16
-rw-r--r--bin/tests/system/database/tests.sh53
-rw-r--r--bin/tests/system/delzone/clean.sh22
-rw-r--r--bin/tests/system/delzone/ns1/inlineslave.db24
-rw-r--r--bin/tests/system/delzone/ns1/named.conf31
-rw-r--r--bin/tests/system/delzone/ns2/added.db24
-rw-r--r--bin/tests/system/delzone/ns2/named.args1
-rw-r--r--bin/tests/system/delzone/ns2/named.conf32
-rw-r--r--bin/tests/system/delzone/ns2/normal.db24
-rw-r--r--bin/tests/system/delzone/setup.sh15
-rwxr-xr-xbin/tests/system/delzone/tests.sh63
-rw-r--r--bin/tests/system/dialup/ns1/example.db17
-rw-r--r--bin/tests/system/dialup/ns1/named.conf37
-rw-r--r--bin/tests/system/dialup/ns1/root.db18
-rw-r--r--bin/tests/system/dialup/ns2/hint.db11
-rw-r--r--bin/tests/system/dialup/ns2/named.conf37
-rw-r--r--bin/tests/system/dialup/ns3/hint.db11
-rw-r--r--bin/tests/system/dialup/ns3/named.conf37
-rw-r--r--bin/tests/system/dialup/setup.sh11
-rw-r--r--bin/tests/system/dialup/tests.sh63
-rw-r--r--bin/tests/system/digcomp.pl118
-rw-r--r--bin/tests/system/digdelv/ans4/startme0
-rw-r--r--bin/tests/system/digdelv/clean.sh17
-rw-r--r--bin/tests/system/digdelv/ns1/named.conf.in29
-rw-r--r--bin/tests/system/digdelv/ns1/root.db24
-rw-r--r--bin/tests/system/digdelv/ns2/example.db57
-rw-r--r--bin/tests/system/digdelv/ns2/named.conf.in33
-rw-r--r--bin/tests/system/digdelv/ns3/named.conf.in28
-rw-r--r--bin/tests/system/digdelv/prereq.sh21
-rw-r--r--bin/tests/system/digdelv/setup.sh18
-rw-r--r--bin/tests/system/digdelv/tests.sh652
-rw-r--r--bin/tests/system/ditch.pl85
-rw-r--r--bin/tests/system/dlv/clean.sh42
-rw-r--r--bin/tests/system/dlv/ns1/named.conf.in26
-rw-r--r--bin/tests/system/dlv/ns1/root.db.in19
-rw-r--r--bin/tests/system/dlv/ns1/rootservers.utld.db13
-rwxr-xr-xbin/tests/system/dlv/ns1/sign.sh36
-rw-r--r--bin/tests/system/dlv/ns2/druz.db.in47
-rw-r--r--bin/tests/system/dlv/ns2/hints11
-rw-r--r--bin/tests/system/dlv/ns2/named.conf.in27
-rwxr-xr-xbin/tests/system/dlv/ns2/sign.sh37
-rw-r--r--bin/tests/system/dlv/ns2/utld.db49
-rw-r--r--bin/tests/system/dlv/ns3/child.db.in17
-rw-r--r--bin/tests/system/dlv/ns3/dlv.db.in13
-rw-r--r--bin/tests/system/dlv/ns3/hints11
-rw-r--r--bin/tests/system/dlv/ns3/named.conf.in42
-rwxr-xr-xbin/tests/system/dlv/ns3/sign.sh286
-rw-r--r--bin/tests/system/dlv/ns4/child.db34
-rw-r--r--bin/tests/system/dlv/ns4/hints11
-rw-r--r--bin/tests/system/dlv/ns4/named.conf.in27
-rw-r--r--bin/tests/system/dlv/ns5/hints11
-rw-r--r--bin/tests/system/dlv/ns5/named.conf.in31
-rw-r--r--bin/tests/system/dlv/ns5/rndc.conf20
-rw-r--r--bin/tests/system/dlv/ns6/child.db.in15
-rw-r--r--bin/tests/system/dlv/ns6/hints11
-rw-r--r--bin/tests/system/dlv/ns6/named.conf.in41
-rwxr-xr-xbin/tests/system/dlv/ns6/sign.sh251
-rw-r--r--bin/tests/system/dlv/prereq.sh15
-rw-r--r--bin/tests/system/dlv/setup.sh24
-rw-r--r--bin/tests/system/dlv/tests.sh55
-rw-r--r--bin/tests/system/dlz/clean.sh16
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/DNAME=10=example.net.=6
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/NS=10=example.com.=6
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/SOA=10=ns.example.com.=root.example.com.=None=None=None=None=None=6
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/DNAME=10=example.net.=6
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/NS=10=example.com.=6
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/SOA=10=ns.example.com.=root.example.com.=2010062900=0=0=0=10=6
-rw-r--r--bin/tests/system/dlz/ns1/dns-root/com/example/xfr.d/10.53.0.16
-rw-r--r--bin/tests/system/dlz/ns1/named.conf.in25
-rw-r--r--bin/tests/system/dlz/prereq.sh.in19
-rw-r--r--bin/tests/system/dlz/setup.sh16
-rw-r--r--bin/tests/system/dlz/tests.sh75
-rw-r--r--bin/tests/system/dlzexternal/Makefile.in46
-rw-r--r--bin/tests/system/dlzexternal/clean.sh23
-rw-r--r--bin/tests/system/dlzexternal/driver.c830
-rw-r--r--bin/tests/system/dlzexternal/driver.h30
-rw-r--r--bin/tests/system/dlzexternal/ns1/dlzs.conf.in33
-rw-r--r--bin/tests/system/dlzexternal/ns1/named.conf.in51
-rw-r--r--bin/tests/system/dlzexternal/ns1/root.db24
-rw-r--r--bin/tests/system/dlzexternal/prereq.sh19
-rw-r--r--bin/tests/system/dlzexternal/setup.sh19
-rw-r--r--bin/tests/system/dlzexternal/tests.sh210
-rw-r--r--bin/tests/system/dns64/clean.sh19
-rw-r--r--bin/tests/system/dns64/conf/bad1.conf14
-rw-r--r--bin/tests/system/dns64/conf/bad2.conf14
-rw-r--r--bin/tests/system/dns64/conf/bad3.conf14
-rw-r--r--bin/tests/system/dns64/conf/bad4.conf14
-rw-r--r--bin/tests/system/dns64/conf/bad5.conf14
-rw-r--r--bin/tests/system/dns64/conf/bad6.conf14
-rw-r--r--bin/tests/system/dns64/conf/bad7.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad8.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad9.conf16
-rw-r--r--bin/tests/system/dns64/conf/good1.conf20
-rw-r--r--bin/tests/system/dns64/conf/good2.conf19
-rw-r--r--bin/tests/system/dns64/conf/good3.conf19
-rw-r--r--bin/tests/system/dns64/conf/good4.conf19
-rw-r--r--bin/tests/system/dns64/conf/good5.conf16
-rw-r--r--bin/tests/system/dns64/ns1/example.db54
-rw-r--r--bin/tests/system/dns64/ns1/named.conf.in53
-rw-r--r--bin/tests/system/dns64/ns1/root.db17
-rw-r--r--bin/tests/system/dns64/ns1/sign.sh24
-rw-r--r--bin/tests/system/dns64/ns2/named.conf.in70
-rw-r--r--bin/tests/system/dns64/ns2/rpz.db21
-rw-r--r--bin/tests/system/dns64/prereq.sh15
-rw-r--r--bin/tests/system/dns64/setup.sh22
-rw-r--r--bin/tests/system/dns64/tests.sh1404
-rw-r--r--bin/tests/system/dnssec/README19
-rw-r--r--bin/tests/system/dnssec/clean.sh95
-rw-r--r--bin/tests/system/dnssec/dnssec_update_test.pl97
-rw-r--r--bin/tests/system/dnssec/ns1/named.conf.in35
-rw-r--r--bin/tests/system/dnssec/ns1/root.db.in29
-rw-r--r--bin/tests/system/dnssec/ns1/sign.sh53
-rw-r--r--bin/tests/system/dnssec/ns2/algroll.db.in24
-rw-r--r--bin/tests/system/dnssec/ns2/badparam.db.in19
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in12
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in12
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey.secure.db.in12
-rw-r--r--bin/tests/system/dnssec/ns2/cds-auto.secure.db.in12
-rw-r--r--bin/tests/system/dnssec/ns2/cds-update.secure.db.in12
-rw-r--r--bin/tests/system/dnssec/ns2/cds.secure.db.in12
-rw-r--r--bin/tests/system/dnssec/ns2/child.nsec3.example.db18
-rw-r--r--bin/tests/system/dnssec/ns2/child.optout.example.db18
-rw-r--r--bin/tests/system/dnssec/ns2/dlv.db.in19
-rw-r--r--bin/tests/system/dnssec/ns2/dst.example.db.in19
-rw-r--r--bin/tests/system/dnssec/ns2/example.db.in160
-rw-r--r--bin/tests/system/dnssec/ns2/in-addr.arpa.db.in17
-rw-r--r--bin/tests/system/dnssec/ns2/insecure.secure.example.db24
-rw-r--r--bin/tests/system/dnssec/ns2/named.conf.in136
-rw-r--r--bin/tests/system/dnssec/ns2/private.secure.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns2/rfc2335.example.db103
-rw-r--r--bin/tests/system/dnssec/ns2/sign.sh239
-rw-r--r--bin/tests/system/dnssec/ns2/single-nsec3.db.in19
-rw-r--r--bin/tests/system/dnssec/ns3/auto-nsec.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/bogus.example.db.in25
-rw-r--r--bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in28
-rw-r--r--bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in27
-rw-r--r--bin/tests/system/dnssec/ns3/dynamic.example.db.in23
-rw-r--r--bin/tests/system/dnssec/ns3/expired.example.db.in42
-rw-r--r--bin/tests/system/dnssec/ns3/expiring.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/future.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/generic.example.db.in21
-rw-r--r--bin/tests/system/dnssec/ns3/inline.example.db24
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.below-cname.example.db24
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.example.db24
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.nsec3.example.db24
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.optout.example.db24
-rw-r--r--bin/tests/system/dnssec/ns3/kskonly.example.db.in24
-rw-r--r--bin/tests/system/dnssec/ns3/lower.example.db.in19
-rw-r--r--bin/tests/system/dnssec/ns3/managed-future.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/multiple.example.db.in27
-rw-r--r--bin/tests/system/dnssec/ns3/named.conf.in298
-rw-r--r--bin/tests/system/dnssec/ns3/nosign.example.db.in21
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in27
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.example.db.in36
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in33
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in33
-rw-r--r--bin/tests/system/dnssec/ns3/optout-unknown.example.db.in27
-rw-r--r--bin/tests/system/dnssec/ns3/optout.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in33
-rw-r--r--bin/tests/system/dnssec/ns3/optout.optout.example.db.in33
-rw-r--r--bin/tests/system/dnssec/ns3/publish-inactive.example.db.in24
-rw-r--r--bin/tests/system/dnssec/ns3/rsasha256.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/rsasha512.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in24
-rw-r--r--bin/tests/system/dnssec/ns3/secure.example.db.in46
-rw-r--r--bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in33
-rw-r--r--bin/tests/system/dnssec/ns3/secure.optout.example.db.in33
-rw-r--r--bin/tests/system/dnssec/ns3/siginterval.example.db.in19
-rw-r--r--bin/tests/system/dnssec/ns3/siginterval1.conf18
-rw-r--r--bin/tests/system/dnssec/ns3/siginterval2.conf18
-rw-r--r--bin/tests/system/dnssec/ns3/sign.sh545
-rw-r--r--bin/tests/system/dnssec/ns3/split-dnssec.example.db.in36
-rw-r--r--bin/tests/system/dnssec/ns3/split-smart.example.db.in36
-rw-r--r--bin/tests/system/dnssec/ns3/ttlpatch.example.db.in24
-rw-r--r--bin/tests/system/dnssec/ns3/update-nsec3.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/upper.example.db.in19
-rw-r--r--bin/tests/system/dnssec/ns4/named1.conf.in53
-rw-r--r--bin/tests/system/dnssec/ns4/named2.conf.in42
-rw-r--r--bin/tests/system/dnssec/ns4/named3.conf.in42
-rw-r--r--bin/tests/system/dnssec/ns4/named4.conf.in42
-rw-r--r--bin/tests/system/dnssec/ns4/named5.conf.in76
-rw-r--r--bin/tests/system/dnssec/ns5/named1.conf.in43
-rw-r--r--bin/tests/system/dnssec/ns5/named2.conf.in50
-rw-r--r--bin/tests/system/dnssec/ns5/sign.sh29
-rw-r--r--bin/tests/system/dnssec/ns5/trusted.conf.bad14
-rw-r--r--bin/tests/system/dnssec/ns6/named.args1
-rw-r--r--bin/tests/system/dnssec/ns6/named.conf.in41
-rw-r--r--bin/tests/system/dnssec/ns6/optout-tld.db.in20
-rw-r--r--bin/tests/system/dnssec/ns6/sign.sh23
-rw-r--r--bin/tests/system/dnssec/ns7/named.conf.in75
-rw-r--r--bin/tests/system/dnssec/ns7/named.nosoa5
-rw-r--r--bin/tests/system/dnssec/ns7/nosoa.secure.example.db20
-rw-r--r--bin/tests/system/dnssec/ns7/sign.sh28
-rw-r--r--bin/tests/system/dnssec/ns7/split-rrsig.db.in19
-rwxr-xr-xbin/tests/system/dnssec/ntadiff.pl22
-rw-r--r--bin/tests/system/dnssec/prereq.sh26
-rw-r--r--bin/tests/system/dnssec/setup.sh41
-rw-r--r--bin/tests/system/dnssec/signer/example.db.in15
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.key1
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.private10
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.key1
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.private10
-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.zone17
-rw-r--r--bin/tests/system/dnssec/signer/general/test2.zone16
-rw-r--r--bin/tests/system/dnssec/signer/general/test3.zone16
-rw-r--r--bin/tests/system/dnssec/signer/general/test4.zone18
-rw-r--r--bin/tests/system/dnssec/signer/general/test5.zone17
-rw-r--r--bin/tests/system/dnssec/signer/general/test6.zone19
-rw-r--r--bin/tests/system/dnssec/signer/general/test7.zone17
-rw-r--r--bin/tests/system/dnssec/signer/general/test8.zone17
-rw-r--r--bin/tests/system/dnssec/signer/remove.db.in16
-rw-r--r--bin/tests/system/dnssec/signer/remove2.db.in14
-rw-r--r--bin/tests/system/dnssec/tests.sh3529
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf17
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf14
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf14
-rw-r--r--bin/tests/system/dnstap/clean.sh24
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf14
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf14
-rw-r--r--bin/tests/system/dnstap/ns1/named.conf.in43
-rw-r--r--bin/tests/system/dnstap/ns1/root.db22
-rw-r--r--bin/tests/system/dnstap/ns2/example.db28
-rw-r--r--bin/tests/system/dnstap/ns2/named.conf.in49
-rw-r--r--bin/tests/system/dnstap/ns3/named.conf.in45
-rw-r--r--bin/tests/system/dnstap/ns4/named.conf.in45
-rw-r--r--bin/tests/system/dnstap/setup.sh19
-rw-r--r--bin/tests/system/dnstap/tests.sh591
-rw-r--r--bin/tests/system/dnstap/ydump.py26
-rw-r--r--bin/tests/system/dscp/clean.sh15
-rw-r--r--bin/tests/system/dscp/ns1/named.args1
-rw-r--r--bin/tests/system/dscp/ns1/named.conf.in28
-rw-r--r--bin/tests/system/dscp/ns1/root.db17
-rw-r--r--bin/tests/system/dscp/ns2/named.args1
-rw-r--r--bin/tests/system/dscp/ns2/named.conf.in29
-rw-r--r--bin/tests/system/dscp/ns3/hint.db14
-rw-r--r--bin/tests/system/dscp/ns3/named.args1
-rw-r--r--bin/tests/system/dscp/ns3/named.conf.in27
-rw-r--r--bin/tests/system/dscp/ns4/named.args1
-rw-r--r--bin/tests/system/dscp/ns4/named.conf.in28
-rw-r--r--bin/tests/system/dscp/ns4/root.db17
-rw-r--r--bin/tests/system/dscp/ns5/named.args1
-rw-r--r--bin/tests/system/dscp/ns5/named.conf.in30
-rw-r--r--bin/tests/system/dscp/ns6/hint.db14
-rw-r--r--bin/tests/system/dscp/ns6/named.args1
-rw-r--r--bin/tests/system/dscp/ns6/named.conf.in27
-rw-r--r--bin/tests/system/dscp/ns7/named.args1
-rw-r--r--bin/tests/system/dscp/ns7/named.conf.in33
-rw-r--r--bin/tests/system/dscp/setup.sh22
-rw-r--r--bin/tests/system/dscp/tests.sh38
-rw-r--r--bin/tests/system/dsdigest/clean.sh21
-rw-r--r--bin/tests/system/dsdigest/ns1/named.conf.in35
-rw-r--r--bin/tests/system/dsdigest/ns1/root.db.in24
-rw-r--r--bin/tests/system/dsdigest/ns1/sign.sh35
-rw-r--r--bin/tests/system/dsdigest/ns2/bad.db.in21
-rw-r--r--bin/tests/system/dsdigest/ns2/good.db.in21
-rw-r--r--bin/tests/system/dsdigest/ns2/named.conf.in45
-rw-r--r--bin/tests/system/dsdigest/ns2/sign.sh46
-rw-r--r--bin/tests/system/dsdigest/ns3/named.conf.in38
-rw-r--r--bin/tests/system/dsdigest/ns4/named.conf.in36
-rw-r--r--bin/tests/system/dsdigest/prereq.sh28
-rw-r--r--bin/tests/system/dsdigest/setup.sh22
-rw-r--r--bin/tests/system/dsdigest/tests.sh52
-rw-r--r--bin/tests/system/dupsigs/check_journal.pl209
-rw-r--r--bin/tests/system/dupsigs/clean.sh19
-rw-r--r--bin/tests/system/dupsigs/ns1/named.args1
-rw-r--r--bin/tests/system/dupsigs/ns1/named.conf.in31
-rw-r--r--bin/tests/system/dupsigs/ns1/reset_keys.sh97
-rw-r--r--bin/tests/system/dupsigs/ns1/signing.test.db.in16
-rw-r--r--bin/tests/system/dupsigs/prereq.sh15
-rw-r--r--bin/tests/system/dupsigs/setup.sh20
-rw-r--r--bin/tests/system/dupsigs/tests.sh35
-rw-r--r--bin/tests/system/dyndb/Makefile.in21
-rw-r--r--bin/tests/system/dyndb/clean.sh22
-rw-r--r--bin/tests/system/dyndb/driver/AUTHORS8
-rw-r--r--bin/tests/system/dyndb/driver/COPYING19
-rw-r--r--bin/tests/system/dyndb/driver/Makefile.in57
-rw-r--r--bin/tests/system/dyndb/driver/README65
-rw-r--r--bin/tests/system/dyndb/driver/db.c822
-rw-r--r--bin/tests/system/dyndb/driver/db.h15
-rw-r--r--bin/tests/system/dyndb/driver/driver.c141
-rw-r--r--bin/tests/system/dyndb/driver/instance.c158
-rw-r--r--bin/tests/system/dyndb/driver/instance.h49
-rw-r--r--bin/tests/system/dyndb/driver/lock.c56
-rw-r--r--bin/tests/system/dyndb/driver/lock.h17
-rw-r--r--bin/tests/system/dyndb/driver/log.c21
-rw-r--r--bin/tests/system/dyndb/driver/log.h27
-rw-r--r--bin/tests/system/dyndb/driver/syncptr.c266
-rw-r--r--bin/tests/system/dyndb/driver/syncptr.h15
-rw-r--r--bin/tests/system/dyndb/driver/util.h57
-rw-r--r--bin/tests/system/dyndb/driver/zone.c194
-rw-r--r--bin/tests/system/dyndb/driver/zone.h15
-rw-r--r--bin/tests/system/dyndb/ns1/named.conf.in37
-rw-r--r--bin/tests/system/dyndb/prereq.sh19
-rw-r--r--bin/tests/system/dyndb/setup.sh16
-rw-r--r--bin/tests/system/dyndb/tests.sh153
-rw-r--r--bin/tests/system/ecdsa/clean.sh18
-rw-r--r--bin/tests/system/ecdsa/ns1/named.conf35
-rw-r--r--bin/tests/system/ecdsa/ns1/root.db.in19
-rw-r--r--bin/tests/system/ecdsa/ns1/sign.sh29
-rw-r--r--bin/tests/system/ecdsa/ns2/named.conf35
-rw-r--r--bin/tests/system/ecdsa/prereq.sh15
-rw-r--r--bin/tests/system/ecdsa/setup.sh17
-rw-r--r--bin/tests/system/ecdsa/tests.sh35
-rw-r--r--bin/tests/system/eddsa/clean.sh18
-rw-r--r--bin/tests/system/eddsa/ns1/named.conf35
-rw-r--r--bin/tests/system/eddsa/ns1/root.db.in19
-rw-r--r--bin/tests/system/eddsa/ns1/sign.sh32
-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.db23
-rw-r--r--bin/tests/system/eddsa/ns2/named.conf35
-rw-r--r--bin/tests/system/eddsa/ns2/sign.sh26
-rw-r--r--bin/tests/system/eddsa/prereq.sh15
-rw-r--r--bin/tests/system/eddsa/setup.sh17
-rw-r--r--bin/tests/system/eddsa/tests.sh47
-rw-r--r--bin/tests/system/ednscompliance/clean.sh16
-rw-r--r--bin/tests/system/ednscompliance/ns1/named.conf.in26
-rw-r--r--bin/tests/system/ednscompliance/ns1/root.db19
-rw-r--r--bin/tests/system/ednscompliance/setup.sh16
-rw-r--r--bin/tests/system/ednscompliance/tests.sh111
-rw-r--r--bin/tests/system/emptyzones/clean.sh14
-rw-r--r--bin/tests/system/emptyzones/ns1/empty.db11
-rw-r--r--bin/tests/system/emptyzones/ns1/named1.conf.in44
-rw-r--r--bin/tests/system/emptyzones/ns1/named2.conf.in47
-rw-r--r--bin/tests/system/emptyzones/ns1/rfc1918.zones30
-rw-r--r--bin/tests/system/emptyzones/ns1/root.hint12
-rw-r--r--bin/tests/system/emptyzones/setup.sh14
-rw-r--r--bin/tests/system/emptyzones/tests.sh44
-rw-r--r--bin/tests/system/feature-test.c195
-rw-r--r--bin/tests/system/fetchlimit/ans4/ans.pl84
-rw-r--r--bin/tests/system/fetchlimit/clean.sh16
-rw-r--r--bin/tests/system/fetchlimit/ns1/named.conf.in32
-rw-r--r--bin/tests/system/fetchlimit/ns1/root.db22
-rw-r--r--bin/tests/system/fetchlimit/ns2/example.db35
-rw-r--r--bin/tests/system/fetchlimit/ns2/named.conf.in38
-rw-r--r--bin/tests/system/fetchlimit/ns3/named.args2
-rw-r--r--bin/tests/system/fetchlimit/ns3/named1.conf.in40
-rw-r--r--bin/tests/system/fetchlimit/ns3/named2.conf.in38
-rw-r--r--bin/tests/system/fetchlimit/ns3/named3.conf.in38
-rw-r--r--bin/tests/system/fetchlimit/ns3/root.hint12
-rw-r--r--bin/tests/system/fetchlimit/prereq.sh21
-rw-r--r--bin/tests/system/fetchlimit/setup.sh19
-rw-r--r--bin/tests/system/fetchlimit/tests.sh186
-rw-r--r--bin/tests/system/filter-aaaa/clean.sh27
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad1.conf15
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad2.conf24
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad3.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad4.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad5.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad6.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/good1.conf14
-rw-r--r--bin/tests/system/filter-aaaa/conf/good2.conf14
-rw-r--r--bin/tests/system/filter-aaaa/conf/good3.conf15
-rw-r--r--bin/tests/system/filter-aaaa/conf/good4.conf15
-rw-r--r--bin/tests/system/filter-aaaa/conf/good5.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/good6.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/good7.conf18
-rw-r--r--bin/tests/system/filter-aaaa/conf/good8.conf19
-rw-r--r--bin/tests/system/filter-aaaa/ns1/named1.conf.in38
-rw-r--r--bin/tests/system/filter-aaaa/ns1/named2.conf.in37
-rw-r--r--bin/tests/system/filter-aaaa/ns1/root.db23
-rwxr-xr-xbin/tests/system/filter-aaaa/ns1/sign.sh30
-rw-r--r--bin/tests/system/filter-aaaa/ns1/signed.db.in23
-rw-r--r--bin/tests/system/filter-aaaa/ns1/signed.db.presigned125
-rw-r--r--bin/tests/system/filter-aaaa/ns1/unsigned.db23
-rw-r--r--bin/tests/system/filter-aaaa/ns2/hints11
-rw-r--r--bin/tests/system/filter-aaaa/ns2/named1.conf.in35
-rw-r--r--bin/tests/system/filter-aaaa/ns2/named2.conf.in35
-rw-r--r--bin/tests/system/filter-aaaa/ns3/hints11
-rw-r--r--bin/tests/system/filter-aaaa/ns3/named1.conf.in35
-rw-r--r--bin/tests/system/filter-aaaa/ns3/named2.conf.in35
-rw-r--r--bin/tests/system/filter-aaaa/ns4/named1.conf.in37
-rw-r--r--bin/tests/system/filter-aaaa/ns4/named2.conf.in37
-rw-r--r--bin/tests/system/filter-aaaa/ns4/root.db22
-rwxr-xr-xbin/tests/system/filter-aaaa/ns4/sign.sh30
-rw-r--r--bin/tests/system/filter-aaaa/ns4/signed.db.in23
-rw-r--r--bin/tests/system/filter-aaaa/ns4/signed.db.presigned110
-rw-r--r--bin/tests/system/filter-aaaa/ns4/unsigned.db23
-rw-r--r--bin/tests/system/filter-aaaa/ns5/hints11
-rw-r--r--bin/tests/system/filter-aaaa/ns5/named.conf.in42
-rw-r--r--bin/tests/system/filter-aaaa/prereq.sh19
-rw-r--r--bin/tests/system/filter-aaaa/setup.sh33
-rw-r--r--bin/tests/system/filter-aaaa/tests.sh1390
-rw-r--r--bin/tests/system/formerr/clean.sh16
-rw-r--r--bin/tests/system/formerr/formerr.pl95
-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.in26
-rw-r--r--bin/tests/system/formerr/ns1/root.db19
-rw-r--r--bin/tests/system/formerr/setup.sh16
-rw-r--r--bin/tests/system/formerr/tests.sh45
-rw-r--r--bin/tests/system/formerr/twoquestions7
-rw-r--r--bin/tests/system/forward/clean.sh17
-rw-r--r--bin/tests/system/forward/ns1/example.db12
-rw-r--r--bin/tests/system/forward/ns1/named.conf.in56
-rw-r--r--bin/tests/system/forward/ns1/root.db28
-rw-r--r--bin/tests/system/forward/ns2/example.db12
-rw-r--r--bin/tests/system/forward/ns2/named.conf.in56
-rw-r--r--bin/tests/system/forward/ns2/root.db28
-rw-r--r--bin/tests/system/forward/ns3/named.conf.in45
-rw-r--r--bin/tests/system/forward/ns3/root.db28
-rw-r--r--bin/tests/system/forward/ns4/named.conf.in54
-rw-r--r--bin/tests/system/forward/ns4/root.db28
-rw-r--r--bin/tests/system/forward/ns5/named.conf.in27
-rw-r--r--bin/tests/system/forward/ns5/root.db28
-rw-r--r--bin/tests/system/forward/rfc1918-inherited.conf15
-rw-r--r--bin/tests/system/forward/rfc1918-notinherited.conf16
-rw-r--r--bin/tests/system/forward/setup.sh20
-rw-r--r--bin/tests/system/forward/tests.sh135
-rw-r--r--bin/tests/system/forward/ula-inherited.conf15
-rw-r--r--bin/tests/system/forward/ula-notinherited.conf16
-rw-r--r--bin/tests/system/genzone.sh468
-rw-r--r--bin/tests/system/geoip/clean.sh19
-rw-r--r--bin/tests/system/geoip/data/GeoIP.csv8
-rw-r--r--bin/tests/system/geoip/data/GeoIP.datbin0 -> 385 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPASNum.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPASNum.datbin0 -> 433 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPASNumv6.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPASNumv6.datbin0 -> 1003 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPCity.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPCity.datbin0 -> 457 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPCityv6.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPCityv6.datbin0 -> 1023 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPDomain.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPDomain.datbin0 -> 382 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPISP.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPISP.datbin0 -> 442 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPNetSpeed.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPNetSpeed.datbin0 -> 241 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPOrg.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPOrg.datbin0 -> 442 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPRegion.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPRegion.datbin0 -> 250 bytes
-rw-r--r--bin/tests/system/geoip/data/GeoIPv6.csv7
-rw-r--r--bin/tests/system/geoip/data/GeoIPv6.datbin0 -> 826 bytes
-rw-r--r--bin/tests/system/geoip/data/README34
-rw-r--r--bin/tests/system/geoip/ns2/example.db.in19
-rw-r--r--bin/tests/system/geoip/ns2/named1.conf.in105
-rw-r--r--bin/tests/system/geoip/ns2/named10.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named11.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named12.conf.in73
-rw-r--r--bin/tests/system/geoip/ns2/named13.conf.in38
-rw-r--r--bin/tests/system/geoip/ns2/named14.conf.in106
-rw-r--r--bin/tests/system/geoip/ns2/named15.conf.in48
-rw-r--r--bin/tests/system/geoip/ns2/named2.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named3.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named4.conf.in89
-rw-r--r--bin/tests/system/geoip/ns2/named5.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named6.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named7.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named8.conf.in97
-rw-r--r--bin/tests/system/geoip/ns2/named9.conf.in97
-rw-r--r--bin/tests/system/geoip/options.conf37
-rw-r--r--bin/tests/system/geoip/prereq.sh19
-rw-r--r--bin/tests/system/geoip/setup.sh25
-rw-r--r--bin/tests/system/geoip/tests.sh484
-rw-r--r--bin/tests/system/glue/clean.sh20
-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/cache.in15
-rw-r--r--bin/tests/system/glue/ns1/mil.db23
-rw-r--r--bin/tests/system/glue/ns1/named.conf.in43
-rw-r--r--bin/tests/system/glue/ns1/net.db32
-rw-r--r--bin/tests/system/glue/ns1/root-servers.nil.db23
-rw-r--r--bin/tests/system/glue/ns1/root.db68
-rw-r--r--bin/tests/system/glue/setup.sh18
-rw-r--r--bin/tests/system/glue/tests.sh40
-rw-r--r--bin/tests/system/glue/xx.good16
-rw-r--r--bin/tests/system/glue/yy.good17
-rw-r--r--bin/tests/system/gost/clean.sh18
-rw-r--r--bin/tests/system/gost/ns1/named.conf35
-rw-r--r--bin/tests/system/gost/ns1/root.db.in19
-rw-r--r--bin/tests/system/gost/ns1/sign.sh38
-rw-r--r--bin/tests/system/gost/ns2/named.conf35
-rw-r--r--bin/tests/system/gost/prereq.sh15
-rw-r--r--bin/tests/system/gost/setup.sh17
-rw-r--r--bin/tests/system/gost/tests.sh35
-rw-r--r--bin/tests/system/idna/clean.sh16
-rw-r--r--bin/tests/system/idna/ns1/named.conf.in29
-rw-r--r--bin/tests/system/idna/ns1/root.db24
-rw-r--r--bin/tests/system/idna/setup.sh16
-rw-r--r--bin/tests/system/idna/tests.sh347
-rw-r--r--bin/tests/system/ifconfig.bat34
-rwxr-xr-xbin/tests/system/ifconfig.sh263
-rw-r--r--bin/tests/system/inline/checkdsa.sh.in17
-rw-r--r--bin/tests/system/inline/clean.sh127
-rw-r--r--bin/tests/system/inline/ns1/named.conf.in35
-rw-r--r--bin/tests/system/inline/ns1/root.db.in57
-rw-r--r--bin/tests/system/inline/ns1/sign.sh24
-rw-r--r--bin/tests/system/inline/ns2/bits.db.in20
-rw-r--r--bin/tests/system/inline/ns2/named.conf.in83
-rw-r--r--bin/tests/system/inline/ns2/nsec3-loop.db23
-rw-r--r--bin/tests/system/inline/ns3/master.db.in19
-rw-r--r--bin/tests/system/inline/ns3/master2.db.in21
-rw-r--r--bin/tests/system/inline/ns3/master3.db.in22
-rw-r--r--bin/tests/system/inline/ns3/master4.db.in22
-rw-r--r--bin/tests/system/inline/ns3/master5.db.in22
-rw-r--r--bin/tests/system/inline/ns3/named.conf.in170
-rwxr-xr-xbin/tests/system/inline/ns3/sign.sh176
-rw-r--r--bin/tests/system/inline/ns4/named.conf.in31
-rw-r--r--bin/tests/system/inline/ns4/noixfr.db.in20
-rw-r--r--bin/tests/system/inline/ns5/named.conf.post40
-rw-r--r--bin/tests/system/inline/ns5/named.conf.pre37
-rw-r--r--bin/tests/system/inline/ns6/named.conf.in38
-rw-r--r--bin/tests/system/inline/ns7/named.conf.in48
-rwxr-xr-xbin/tests/system/inline/ns7/sign.sh23
-rw-r--r--bin/tests/system/inline/prereq.sh15
-rw-r--r--bin/tests/system/inline/setup.sh55
-rwxr-xr-xbin/tests/system/inline/tests.sh1369
-rw-r--r--bin/tests/system/integrity/clean.sh15
-rw-r--r--bin/tests/system/integrity/ns1/mx-cname.db15
-rw-r--r--bin/tests/system/integrity/ns1/named.conf.in112
-rw-r--r--bin/tests/system/integrity/ns1/srv-cname.db15
-rw-r--r--bin/tests/system/integrity/setup.sh16
-rw-r--r--bin/tests/system/integrity/tests.sh129
-rw-r--r--bin/tests/system/ixfr/ans2/startme0
-rw-r--r--bin/tests/system/ixfr/clean.sh21
-rw-r--r--bin/tests/system/ixfr/ns1/startme0
-rw-r--r--bin/tests/system/ixfr/ns3/mytest0.db24
-rw-r--r--bin/tests/system/ixfr/ns3/mytest1.db24
-rw-r--r--bin/tests/system/ixfr/ns3/mytest2.db24
-rw-r--r--bin/tests/system/ixfr/ns3/named.conf.in49
-rw-r--r--bin/tests/system/ixfr/ns3/subtest0.db22
-rw-r--r--bin/tests/system/ixfr/ns3/subtest1.db22
-rw-r--r--bin/tests/system/ixfr/ns4/named.conf.in47
-rw-r--r--bin/tests/system/ixfr/prereq.sh21
-rw-r--r--bin/tests/system/ixfr/setup.sh47
-rw-r--r--bin/tests/system/ixfr/tests.sh311
-rw-r--r--bin/tests/system/keymgr/01-ksk-inactive/README6
-rw-r--r--bin/tests/system/keymgr/01-ksk-inactive/expect9
-rw-r--r--bin/tests/system/keymgr/02-zsk-inactive/README6
-rw-r--r--bin/tests/system/keymgr/02-zsk-inactive/expect9
-rw-r--r--bin/tests/system/keymgr/03-ksk-unpublished/README6
-rw-r--r--bin/tests/system/keymgr/03-ksk-unpublished/expect9
-rw-r--r--bin/tests/system/keymgr/04-zsk-unpublished/README6
-rw-r--r--bin/tests/system/keymgr/04-zsk-unpublished/expect9
-rw-r--r--bin/tests/system/keymgr/05-ksk-unpub-active/README7
-rw-r--r--bin/tests/system/keymgr/05-ksk-unpub-active/expect9
-rw-r--r--bin/tests/system/keymgr/06-zsk-unpub-active/README7
-rw-r--r--bin/tests/system/keymgr/06-zsk-unpub-active/expect9
-rw-r--r--bin/tests/system/keymgr/07-ksk-ttl/README6
-rw-r--r--bin/tests/system/keymgr/07-ksk-ttl/expect9
-rw-r--r--bin/tests/system/keymgr/08-zsk-ttl/README6
-rw-r--r--bin/tests/system/keymgr/08-zsk-ttl/expect9
-rw-r--r--bin/tests/system/keymgr/09-no-keys/README5
-rw-r--r--bin/tests/system/keymgr/09-no-keys/expect9
-rw-r--r--bin/tests/system/keymgr/10-change-roll/README7
-rw-r--r--bin/tests/system/keymgr/10-change-roll/expect9
-rw-r--r--bin/tests/system/keymgr/11-many-simul/README6
-rw-r--r--bin/tests/system/keymgr/11-many-simul/expect9
-rw-r--r--bin/tests/system/keymgr/12-many-active/README6
-rw-r--r--bin/tests/system/keymgr/12-many-active/expect9
-rw-r--r--bin/tests/system/keymgr/13-noroll/README6
-rw-r--r--bin/tests/system/keymgr/13-noroll/expect9
-rw-r--r--bin/tests/system/keymgr/14-wrongalg/README6
-rw-r--r--bin/tests/system/keymgr/14-wrongalg/expect9
-rw-r--r--bin/tests/system/keymgr/15-unspec/README6
-rw-r--r--bin/tests/system/keymgr/15-unspec/expect9
-rw-r--r--bin/tests/system/keymgr/16-wrongalg-unspec/README6
-rw-r--r--bin/tests/system/keymgr/16-wrongalg-unspec/expect9
-rw-r--r--bin/tests/system/keymgr/17-noforce/README6
-rw-r--r--bin/tests/system/keymgr/17-noforce/expect9
-rw-r--r--bin/tests/system/keymgr/18-nonstd-prepub/README7
-rw-r--r--bin/tests/system/keymgr/18-nonstd-prepub/expect9
-rw-r--r--bin/tests/system/keymgr/18-nonstd-prepub/policy.conf18
-rw-r--r--bin/tests/system/keymgr/clean.sh15
-rw-r--r--bin/tests/system/keymgr/policy.conf21
-rw-r--r--bin/tests/system/keymgr/policy.good170
-rw-r--r--bin/tests/system/keymgr/policy.sample58
-rw-r--r--bin/tests/system/keymgr/prereq.sh15
-rw-r--r--bin/tests/system/keymgr/setup.sh216
-rw-r--r--bin/tests/system/keymgr/testpolicy.py39
-rw-r--r--bin/tests/system/keymgr/tests.sh111
-rw-r--r--bin/tests/system/legacy/build.sh22
-rw-r--r--bin/tests/system/legacy/clean.sh25
-rw-r--r--bin/tests/system/legacy/ns1/named1.conf.in26
-rw-r--r--bin/tests/system/legacy/ns1/named2.conf.in28
-rw-r--r--bin/tests/system/legacy/ns1/root.db25
-rw-r--r--bin/tests/system/legacy/ns1/trusted.conf3
-rw-r--r--bin/tests/system/legacy/ns2/dropedns.db12
-rw-r--r--bin/tests/system/legacy/ns2/named.conf.in26
-rw-r--r--bin/tests/system/legacy/ns2/named.dropedns1
-rw-r--r--bin/tests/system/legacy/ns3/dropedns-notcp.db12
-rw-r--r--bin/tests/system/legacy/ns3/named.conf.in26
-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.in26
-rw-r--r--bin/tests/system/legacy/ns4/plain.db12
-rw-r--r--bin/tests/system/legacy/ns5/named.args1
-rw-r--r--bin/tests/system/legacy/ns5/named.conf.in26
-rw-r--r--bin/tests/system/legacy/ns5/named.notcp1
-rw-r--r--bin/tests/system/legacy/ns5/plain-notcp.db12
-rw-r--r--bin/tests/system/legacy/ns6/edns512.db.in24
-rw-r--r--bin/tests/system/legacy/ns6/edns512.db.signed248
-rw-r--r--bin/tests/system/legacy/ns6/named.args1
-rw-r--r--bin/tests/system/legacy/ns6/named.conf.in26
-rwxr-xr-xbin/tests/system/legacy/ns6/sign.sh29
-rw-r--r--bin/tests/system/legacy/ns7/edns512-notcp.db.in24
-rw-r--r--bin/tests/system/legacy/ns7/edns512-notcp.db.signed248
-rw-r--r--bin/tests/system/legacy/ns7/named.args1
-rw-r--r--bin/tests/system/legacy/ns7/named.conf.in26
-rw-r--r--bin/tests/system/legacy/ns7/named.notcp1
-rwxr-xr-xbin/tests/system/legacy/ns7/sign.sh32
-rw-r--r--bin/tests/system/legacy/setup.sh24
-rwxr-xr-xbin/tests/system/legacy/tests.sh166
-rw-r--r--bin/tests/system/limits/clean.sh19
-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.db19110
-rw-r--r--bin/tests/system/limits/ns1/named.conf.in32
-rw-r--r--bin/tests/system/limits/ns1/root.db22
-rw-r--r--bin/tests/system/limits/setup.sh16
-rw-r--r--bin/tests/system/limits/tests.sh54
-rw-r--r--bin/tests/system/logfileconfig/clean.sh30
-rw-r--r--bin/tests/system/logfileconfig/ns1/controls.conf.in16
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.dirconf43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.pipeconf43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.plain51
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.plainconf34
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.symconf43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.unlimited53
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.versconf53
-rw-r--r--bin/tests/system/logfileconfig/ns1/rndc.conf.in24
-rw-r--r--bin/tests/system/logfileconfig/ns1/root.db25
-rw-r--r--bin/tests/system/logfileconfig/setup.sh19
-rw-r--r--bin/tests/system/logfileconfig/tests.sh364
-rw-r--r--bin/tests/system/lwresd/Makefile.in50
-rw-r--r--bin/tests/system/lwresd/clean.sh22
-rw-r--r--bin/tests/system/lwresd/lwresd1/lwresd.conf28
-rw-r--r--bin/tests/system/lwresd/lwresd1/nosearch.conf27
-rw-r--r--bin/tests/system/lwresd/lwresd1/resolv.conf15
-rw-r--r--bin/tests/system/lwresd/lwtest.c797
-rw-r--r--bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db23
-rw-r--r--bin/tests/system/lwresd/ns1/e.example1.db54
-rw-r--r--bin/tests/system/lwresd/ns1/example1.db29
-rw-r--r--bin/tests/system/lwresd/ns1/example2.db24
-rw-r--r--bin/tests/system/lwresd/ns1/ip6.arpa.db24
-rw-r--r--bin/tests/system/lwresd/ns1/ip6.int.db21
-rw-r--r--bin/tests/system/lwresd/ns1/named.conf63
-rw-r--r--bin/tests/system/lwresd/ns1/root.db27
-rw-r--r--bin/tests/system/lwresd/resolv.conf15
-rw-r--r--bin/tests/system/lwresd/tests.sh87
-rw-r--r--bin/tests/system/masterfile/clean.sh17
-rw-r--r--bin/tests/system/masterfile/knowngood.dig.out32
-rw-r--r--bin/tests/system/masterfile/ns1/include.db33
-rw-r--r--bin/tests/system/masterfile/ns1/named.conf.in37
-rw-r--r--bin/tests/system/masterfile/ns1/sub.db13
-rw-r--r--bin/tests/system/masterfile/ns1/ttl1.db25
-rw-r--r--bin/tests/system/masterfile/ns1/ttl2.db28
-rw-r--r--bin/tests/system/masterfile/ns2/example.db19
-rw-r--r--bin/tests/system/masterfile/ns2/named.conf.in41
-rw-r--r--bin/tests/system/masterfile/setup.sh17
-rw-r--r--bin/tests/system/masterfile/tests.sh60
-rw-r--r--bin/tests/system/masterfile/zone/inheritownerafterinclude.db12
-rw-r--r--bin/tests/system/masterfile/zone/inheritownerafterinclude.good3
-rw-r--r--bin/tests/system/masterfile/zone/nameservers.db10
-rwxr-xr-xbin/tests/system/masterformat/clean.sh33
-rwxr-xr-xbin/tests/system/masterformat/ns1/compile.sh32
-rw-r--r--bin/tests/system/masterformat/ns1/example.db56
-rw-r--r--bin/tests/system/masterformat/ns1/large.db.in20
-rw-r--r--bin/tests/system/masterformat/ns1/named.conf.in86
-rw-r--r--bin/tests/system/masterformat/ns1/signed.db27
-rw-r--r--bin/tests/system/masterformat/ns2/formerly-text.db.in46
-rw-r--r--bin/tests/system/masterformat/ns2/named.conf.in62
-rw-r--r--bin/tests/system/masterformat/ns3/named.conf.in44
-rwxr-xr-xbin/tests/system/masterformat/prereq.sh15
-rwxr-xr-xbin/tests/system/masterformat/setup.sh31
-rwxr-xr-xbin/tests/system/masterformat/tests.sh298
-rw-r--r--bin/tests/system/metadata/child.db22
-rw-r--r--bin/tests/system/metadata/clean.sh19
-rw-r--r--bin/tests/system/metadata/parent.db29
-rw-r--r--bin/tests/system/metadata/prereq.sh15
-rw-r--r--bin/tests/system/metadata/setup.sh63
-rw-r--r--bin/tests/system/metadata/tests.sh211
-rw-r--r--bin/tests/system/mkeys/README18
-rw-r--r--bin/tests/system/mkeys/clean.sh21
-rw-r--r--bin/tests/system/mkeys/ns1/named1.conf.in48
-rw-r--r--bin/tests/system/mkeys/ns1/named2.conf.in46
-rw-r--r--bin/tests/system/mkeys/ns1/named3.conf.in40
-rw-r--r--bin/tests/system/mkeys/ns1/root.db23
-rw-r--r--bin/tests/system/mkeys/ns1/sign.sh37
-rw-r--r--bin/tests/system/mkeys/ns2/named.args1
-rw-r--r--bin/tests/system/mkeys/ns2/named.conf.in42
-rw-r--r--bin/tests/system/mkeys/ns3/named.args1
-rw-r--r--bin/tests/system/mkeys/ns3/named.conf.in47
-rw-r--r--bin/tests/system/mkeys/ns5/named.conf.in41
-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/prereq.sh15
-rw-r--r--bin/tests/system/mkeys/setup.sh27
-rw-r--r--bin/tests/system/mkeys/tests.sh714
-rw-r--r--bin/tests/system/names/clean.sh17
-rw-r--r--bin/tests/system/names/ns1/example.db49
-rw-r--r--bin/tests/system/names/ns1/named.conf.in42
-rw-r--r--bin/tests/system/names/setup.sh15
-rw-r--r--bin/tests/system/names/tests.sh46
-rw-r--r--bin/tests/system/notify/clean.sh35
-rw-r--r--bin/tests/system/notify/ns1/named.conf.in27
-rw-r--r--bin/tests/system/notify/ns1/root.db22
-rw-r--r--bin/tests/system/notify/ns2/example1.db142
-rw-r--r--bin/tests/system/notify/ns2/example2.db142
-rw-r--r--bin/tests/system/notify/ns2/example3.db142
-rw-r--r--bin/tests/system/notify/ns2/example4.db142
-rw-r--r--bin/tests/system/notify/ns2/generic.db23
-rw-r--r--bin/tests/system/notify/ns2/named.conf.in70
-rw-r--r--bin/tests/system/notify/ns3/named.conf.in34
-rw-r--r--bin/tests/system/notify/ns4/named.conf.in34
-rw-r--r--bin/tests/system/notify/ns4/named.port.in1
-rw-r--r--bin/tests/system/notify/ns5/named.conf.in68
-rw-r--r--bin/tests/system/notify/ns5/x21.db20
-rw-r--r--bin/tests/system/notify/setup.sh26
-rw-r--r--bin/tests/system/notify/tests.sh212
-rw-r--r--bin/tests/system/nslookup/clean.sh15
-rw-r--r--bin/tests/system/nslookup/ns1/example.net.db29
-rw-r--r--bin/tests/system/nslookup/ns1/named.conf.in31
-rw-r--r--bin/tests/system/nslookup/setup.sh19
-rw-r--r--bin/tests/system/nslookup/tests.sh110
-rw-r--r--bin/tests/system/nsupdate/ans4/ans.pl58
-rw-r--r--bin/tests/system/nsupdate/clean.sh60
-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.sh113
-rw-r--r--bin/tests/system/nsupdate/ns1/example1.db144
-rw-r--r--bin/tests/system/nsupdate/ns1/many.test.db.in20
-rw-r--r--bin/tests/system/nsupdate/ns1/max-ttl.db27
-rw-r--r--bin/tests/system/nsupdate/ns1/named.conf.in134
-rw-r--r--bin/tests/system/nsupdate/ns1/sample.db.in17
-rw-r--r--bin/tests/system/nsupdate/ns10/dns.keytabbin0 -> 168 bytes
-rw-r--r--bin/tests/system/nsupdate/ns10/example.com.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns10/in-addr.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns10/machine.ccachebin0 -> 1217 bytes
-rw-r--r--bin/tests/system/nsupdate/ns10/named.conf.in48
-rw-r--r--bin/tests/system/nsupdate/ns2/named.conf.in64
-rw-r--r--bin/tests/system/nsupdate/ns2/sample.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns3/delegation.test.db.in13
-rw-r--r--bin/tests/system/nsupdate/ns3/dnskey.test.db.in13
-rw-r--r--bin/tests/system/nsupdate/ns3/example.db.in13
-rw-r--r--bin/tests/system/nsupdate/ns3/named.conf.in64
-rw-r--r--bin/tests/system/nsupdate/ns3/nsec3param.test.db.in13
-rw-r--r--bin/tests/system/nsupdate/ns3/sign.sh46
-rw-r--r--bin/tests/system/nsupdate/ns3/too-big.test.db.in13
-rw-r--r--bin/tests/system/nsupdate/ns5/local.db.in23
-rw-r--r--bin/tests/system/nsupdate/ns5/named.args1
-rw-r--r--bin/tests/system/nsupdate/ns5/named.conf.in38
-rw-r--r--bin/tests/system/nsupdate/ns6/in-addr.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns6/named.args1
-rw-r--r--bin/tests/system/nsupdate/ns6/named.conf.in38
-rw-r--r--bin/tests/system/nsupdate/ns7/dns.keytabbin0 -> 166 bytes
-rw-r--r--bin/tests/system/nsupdate/ns7/example.com.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns7/in-addr.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns7/machine.ccachebin0 -> 1327 bytes
-rw-r--r--bin/tests/system/nsupdate/ns7/named.conf.in48
-rw-r--r--bin/tests/system/nsupdate/ns8/dns.keytabbin0 -> 166 bytes
-rw-r--r--bin/tests/system/nsupdate/ns8/example.com.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns8/in-addr.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns8/machine.ccachebin0 -> 1327 bytes
-rw-r--r--bin/tests/system/nsupdate/ns8/named.conf.in48
-rw-r--r--bin/tests/system/nsupdate/ns9/dns.keytabbin0 -> 166 bytes
-rw-r--r--bin/tests/system/nsupdate/ns9/example.com.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns9/in-addr.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns9/machine.ccachebin0 -> 1215 bytes
-rw-r--r--bin/tests/system/nsupdate/ns9/named.conf.in48
-rw-r--r--bin/tests/system/nsupdate/prereq.sh26
-rw-r--r--bin/tests/system/nsupdate/setup.sh90
-rwxr-xr-xbin/tests/system/nsupdate/tests.sh1253
-rw-r--r--bin/tests/system/nsupdate/update_test.pl418
-rw-r--r--bin/tests/system/nsupdate/verylarge.in3
-rw-r--r--bin/tests/system/nzd2nzf/clean.sh18
-rw-r--r--bin/tests/system/nzd2nzf/ns1/added.db24
-rw-r--r--bin/tests/system/nzd2nzf/ns1/named.conf.in29
-rw-r--r--bin/tests/system/nzd2nzf/prereq.sh18
-rw-r--r--bin/tests/system/nzd2nzf/setup.sh17
-rw-r--r--bin/tests/system/nzd2nzf/tests.sh72
-rw-r--r--bin/tests/system/org.isc.bind.system16
-rw-r--r--bin/tests/system/org.isc.bind.system.plist17
-rw-r--r--bin/tests/system/packet.pl100
-rw-r--r--bin/tests/system/pending/clean.sh24
-rw-r--r--bin/tests/system/pending/ns1/named.conf.in28
-rw-r--r--bin/tests/system/pending/ns1/root.db.in27
-rw-r--r--bin/tests/system/pending/ns1/sign.sh34
-rw-r--r--bin/tests/system/pending/ns2/example.com.db.in25
-rw-r--r--bin/tests/system/pending/ns2/example.db.in24
-rw-r--r--bin/tests/system/pending/ns2/forgery.db22
-rw-r--r--bin/tests/system/pending/ns2/named.conf.in50
-rw-r--r--bin/tests/system/pending/ns2/sign.sh32
-rw-r--r--bin/tests/system/pending/ns3/hostile.db20
-rw-r--r--bin/tests/system/pending/ns3/mail.example.db21
-rw-r--r--bin/tests/system/pending/ns3/named.conf.in43
-rw-r--r--bin/tests/system/pending/ns4/named.conf.in28
-rw-r--r--bin/tests/system/pending/prereq.sh15
-rw-r--r--bin/tests/system/pending/setup.sh22
-rw-r--r--bin/tests/system/pending/tests.sh197
-rw-r--r--bin/tests/system/pipelined/Makefile.in46
-rw-r--r--bin/tests/system/pipelined/clean.sh16
-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.in36
-rw-r--r--bin/tests/system/pipelined/ns1/root.db25
-rw-r--r--bin/tests/system/pipelined/ns2/examplea.db30
-rw-r--r--bin/tests/system/pipelined/ns2/named.conf.in42
-rw-r--r--bin/tests/system/pipelined/ns3/exampleb.db30
-rw-r--r--bin/tests/system/pipelined/ns3/named.args1
-rw-r--r--bin/tests/system/pipelined/ns3/named.conf.in42
-rw-r--r--bin/tests/system/pipelined/ns4/named.conf.in38
-rw-r--r--bin/tests/system/pipelined/pipequeries.c346
-rw-r--r--bin/tests/system/pipelined/ref8
-rw-r--r--bin/tests/system/pipelined/refb8
-rw-r--r--bin/tests/system/pipelined/setup.sh22
-rw-r--r--bin/tests/system/pipelined/tests.sh75
-rw-r--r--bin/tests/system/pkcs11/clean.sh16
-rw-r--r--bin/tests/system/pkcs11/ns1/example.db.in22
-rw-r--r--bin/tests/system/pkcs11/ns1/named.conf51
-rw-r--r--bin/tests/system/pkcs11/prereq.sh36
-rw-r--r--bin/tests/system/pkcs11/setup.sh98
-rw-r--r--bin/tests/system/pkcs11/tests.sh87
-rw-r--r--bin/tests/system/pkcs11/usepkcs111
-rw-r--r--bin/tests/system/pkcs11ssl/clean.sh16
-rw-r--r--bin/tests/system/pkcs11ssl/ns1/example.db.in22
-rw-r--r--bin/tests/system/pkcs11ssl/ns1/named.conf45
-rw-r--r--bin/tests/system/pkcs11ssl/prereq.sh16
-rw-r--r--bin/tests/system/pkcs11ssl/setup.sh40
-rw-r--r--bin/tests/system/pkcs11ssl/tests.sh62
-rw-r--r--bin/tests/system/pkcs11ssl/usepkcs111
-rw-r--r--bin/tests/system/reclimit/README13
-rw-r--r--bin/tests/system/reclimit/ans2/ans.pl233
-rw-r--r--bin/tests/system/reclimit/ans7/ans.pl74
-rw-r--r--bin/tests/system/reclimit/clean.sh18
-rw-r--r--bin/tests/system/reclimit/ns1/named.conf.in24
-rw-r--r--bin/tests/system/reclimit/ns1/root.db17
-rw-r--r--bin/tests/system/reclimit/ns3/hints.db11
-rw-r--r--bin/tests/system/reclimit/ns3/named1.conf.in34
-rw-r--r--bin/tests/system/reclimit/ns3/named2.conf.in34
-rw-r--r--bin/tests/system/reclimit/ns3/named3.conf.in35
-rw-r--r--bin/tests/system/reclimit/ns3/named4.conf.in35
-rw-r--r--bin/tests/system/reclimit/prereq.sh35
-rw-r--r--bin/tests/system/reclimit/setup.sh17
-rw-r--r--bin/tests/system/reclimit/tests.sh191
-rw-r--r--bin/tests/system/redirect/clean.sh30
-rw-r--r--bin/tests/system/redirect/conf/bad1.conf23
-rw-r--r--bin/tests/system/redirect/conf/bad2.conf23
-rw-r--r--bin/tests/system/redirect/conf/bad3.conf22
-rw-r--r--bin/tests/system/redirect/conf/good1.conf20
-rw-r--r--bin/tests/system/redirect/conf/good2.conf20
-rw-r--r--bin/tests/system/redirect/conf/good3.conf21
-rw-r--r--bin/tests/system/redirect/conf/good4.conf21
-rw-r--r--bin/tests/system/redirect/ns1/example.db48
-rw-r--r--bin/tests/system/redirect/ns1/named.conf.in56
-rw-r--r--bin/tests/system/redirect/ns1/redirect.db18
-rw-r--r--bin/tests/system/redirect/ns1/root.db17
-rw-r--r--bin/tests/system/redirect/ns1/sign.sh35
-rw-r--r--bin/tests/system/redirect/ns2/example.db.in14
-rw-r--r--bin/tests/system/redirect/ns2/named.conf.in56
-rw-r--r--bin/tests/system/redirect/ns2/redirect.db.in18
-rw-r--r--bin/tests/system/redirect/ns3/example.db48
-rw-r--r--bin/tests/system/redirect/ns3/named.conf.in53
-rw-r--r--bin/tests/system/redirect/ns3/redirect.db14
-rw-r--r--bin/tests/system/redirect/ns3/root.db18
-rw-r--r--bin/tests/system/redirect/ns3/sign.sh35
-rw-r--r--bin/tests/system/redirect/ns4/example.db.in14
-rw-r--r--bin/tests/system/redirect/ns4/named.conf.in51
-rw-r--r--bin/tests/system/redirect/ns4/root.hint12
-rw-r--r--bin/tests/system/redirect/prereq.sh15
-rw-r--r--bin/tests/system/redirect/setup.sh29
-rw-r--r--bin/tests/system/redirect/tests.sh522
-rw-r--r--bin/tests/system/resolver/ans2/ans.pl115
-rw-r--r--bin/tests/system/resolver/ans3/ans.pl99
-rw-r--r--bin/tests/system/resolver/ans8/ans.pl145
-rw-r--r--bin/tests/system/resolver/clean.sh36
-rw-r--r--bin/tests/system/resolver/ns1/named.conf.in61
-rw-r--r--bin/tests/system/resolver/ns1/root.hint12
-rw-r--r--bin/tests/system/resolver/ns4/broken.db22
-rw-r--r--bin/tests/system/resolver/ns4/child.server.db21
-rw-r--r--bin/tests/system/resolver/ns4/moves.db20
-rw-r--r--bin/tests/system/resolver/ns4/named.conf.in60
-rw-r--r--bin/tests/system/resolver/ns4/named.noaa5
-rw-r--r--bin/tests/system/resolver/ns4/root.db26
-rw-r--r--bin/tests/system/resolver/ns4/tld1.db29
-rw-r--r--bin/tests/system/resolver/ns4/tld2.db29
-rw-r--r--bin/tests/system/resolver/ns5/child.server.db21
-rw-r--r--bin/tests/system/resolver/ns5/moves.db20
-rw-r--r--bin/tests/system/resolver/ns5/named.conf.in49
-rw-r--r--bin/tests/system/resolver/ns5/root.hint12
-rw-r--r--bin/tests/system/resolver/ns6/broken.db26
-rw-r--r--bin/tests/system/resolver/ns6/delegation-only.db31
-rw-r--r--bin/tests/system/resolver/ns6/ds.example.net.db.in13
-rw-r--r--bin/tests/system/resolver/ns6/example.net.db.in21
-rw-r--r--bin/tests/system/resolver/ns6/keygen.sh34
-rw-r--r--bin/tests/system/resolver/ns6/moves.db20
-rw-r--r--bin/tests/system/resolver/ns6/named.conf.in69
-rw-r--r--bin/tests/system/resolver/ns6/no-edns-version.tld.db12
-rw-r--r--bin/tests/system/resolver/ns6/root.db31
-rw-r--r--bin/tests/system/resolver/ns6/to-be-removed.tld.db.in26
-rw-r--r--bin/tests/system/resolver/ns7/all-cnames.db18
-rw-r--r--bin/tests/system/resolver/ns7/edns-version.tld.db12
-rw-r--r--bin/tests/system/resolver/ns7/named.args2
-rw-r--r--bin/tests/system/resolver/ns7/named1.conf.in61
-rw-r--r--bin/tests/system/resolver/ns7/named2.conf.in61
-rw-r--r--bin/tests/system/resolver/ns7/root.hint12
-rw-r--r--bin/tests/system/resolver/ns7/server.db.in22
-rw-r--r--bin/tests/system/resolver/prereq.sh29
-rw-r--r--bin/tests/system/resolver/setup.sh27
-rwxr-xr-xbin/tests/system/resolver/tests.sh783
-rw-r--r--bin/tests/system/rndc/Makefile.in50
-rw-r--r--bin/tests/system/rndc/clean.sh27
-rw-r--r--bin/tests/system/rndc/gencheck.c88
-rw-r--r--bin/tests/system/rndc/ns2/incl.db11
-rw-r--r--bin/tests/system/rndc/ns2/named.conf.in62
-rw-r--r--bin/tests/system/rndc/ns2/secondkey.conf19
-rw-r--r--bin/tests/system/rndc/ns3/named.conf.in46
-rw-r--r--bin/tests/system/rndc/ns4/named.conf.in26
-rw-r--r--bin/tests/system/rndc/ns5/named.conf.in32
-rw-r--r--bin/tests/system/rndc/ns6/named.args3
-rw-r--r--bin/tests/system/rndc/ns6/named.conf.in27
-rw-r--r--bin/tests/system/rndc/setup.sh45
-rw-r--r--bin/tests/system/rndc/tests.sh660
-rw-r--r--bin/tests/system/rootkeysentinel/clean.sh23
-rw-r--r--bin/tests/system/rootkeysentinel/ns1/named.conf.in31
-rw-r--r--bin/tests/system/rootkeysentinel/ns1/root.db.in22
-rw-r--r--bin/tests/system/rootkeysentinel/ns1/sign.sh34
-rw-r--r--bin/tests/system/rootkeysentinel/ns2/example.db.in19
-rw-r--r--bin/tests/system/rootkeysentinel/ns2/named.conf.in31
-rw-r--r--bin/tests/system/rootkeysentinel/ns2/sign.sh40
-rw-r--r--bin/tests/system/rootkeysentinel/ns3/hint.db11
-rw-r--r--bin/tests/system/rootkeysentinel/ns3/named.conf.in32
-rw-r--r--bin/tests/system/rootkeysentinel/ns4/hint.db11
-rw-r--r--bin/tests/system/rootkeysentinel/ns4/named.conf.in32
-rw-r--r--bin/tests/system/rootkeysentinel/prereq.sh15
-rw-r--r--bin/tests/system/rootkeysentinel/setup.sh25
-rw-r--r--bin/tests/system/rootkeysentinel/tests.sh286
-rw-r--r--bin/tests/system/rpz/clean.sh21
-rw-r--r--bin/tests/system/rpz/ns1/named.conf.in24
-rw-r--r--bin/tests/system/rpz/ns1/root.db35
-rw-r--r--bin/tests/system/rpz/ns2/base-tld2s.db23
-rw-r--r--bin/tests/system/rpz/ns2/bl.tld2.db.in19
-rw-r--r--bin/tests/system/rpz/ns2/blv2.tld2.db.in17
-rw-r--r--bin/tests/system/rpz/ns2/blv3.tld2.db.in19
-rw-r--r--bin/tests/system/rpz/ns2/hints11
-rw-r--r--bin/tests/system/rpz/ns2/named.conf.in45
-rw-r--r--bin/tests/system/rpz/ns2/tld2.db120
-rw-r--r--bin/tests/system/rpz/ns3/base.db20
-rw-r--r--bin/tests/system/rpz/ns3/crash121
-rw-r--r--bin/tests/system/rpz/ns3/crash227
-rw-r--r--bin/tests/system/rpz/ns3/hints11
-rw-r--r--bin/tests/system/rpz/ns3/named.conf.in91
-rw-r--r--bin/tests/system/rpz/ns4/hints11
-rw-r--r--bin/tests/system/rpz/ns4/named.conf.in31
-rw-r--r--bin/tests/system/rpz/ns4/tld4.db64
-rw-r--r--bin/tests/system/rpz/ns5/empty.db.in12
-rw-r--r--bin/tests/system/rpz/ns5/hints11
-rw-r--r--bin/tests/system/rpz/ns5/named.args3
-rw-r--r--bin/tests/system/rpz/ns5/named.conf.in82
-rw-r--r--bin/tests/system/rpz/ns5/tld5.db30
-rw-r--r--bin/tests/system/rpz/ns6/hints11
-rw-r--r--bin/tests/system/rpz/ns6/named.conf.in44
-rw-r--r--bin/tests/system/rpz/ns7/hints11
-rw-r--r--bin/tests/system/rpz/ns7/named.conf.in43
-rw-r--r--bin/tests/system/rpz/prereq.sh15
-rw-r--r--bin/tests/system/rpz/qperf.sh20
-rw-r--r--bin/tests/system/rpz/setup.sh123
-rw-r--r--bin/tests/system/rpz/test196
-rw-r--r--bin/tests/system/rpz/test274
-rw-r--r--bin/tests/system/rpz/test342
-rw-r--r--bin/tests/system/rpz/test431
-rw-r--r--bin/tests/system/rpz/test4a25
-rw-r--r--bin/tests/system/rpz/test558
-rw-r--r--bin/tests/system/rpz/test635
-rw-r--r--bin/tests/system/rpz/tests.sh646
-rw-r--r--bin/tests/system/rpzrecurse/README117
-rw-r--r--bin/tests/system/rpzrecurse/ans5/ans.pl79
-rw-r--r--bin/tests/system/rpzrecurse/clean.sh29
-rw-r--r--bin/tests/system/rpzrecurse/ns1/db.l015
-rw-r--r--bin/tests/system/rpzrecurse/ns1/db.l1.l015
-rw-r--r--bin/tests/system/rpzrecurse/ns1/example.db14
-rw-r--r--bin/tests/system/rpzrecurse/ns1/named.conf.in67
-rw-r--r--bin/tests/system/rpzrecurse/ns1/root.db22
-rw-r--r--bin/tests/system/rpzrecurse/ns1/test1.example.net.db15
-rw-r--r--bin/tests/system/rpzrecurse/ns1/test2.example.net.db15
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.clientip115
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.clientip214
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.clientip2115
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.log114
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.log215
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.log316
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard115
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard2a15
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard2b15
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard314
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.clientip.conf30
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.clientip2.conf30
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.conf.header.in35
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.default.conf20
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.log.conf32
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf28
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf30
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf28
-rw-r--r--bin/tests/system/rpzrecurse/ns2/root.hint12
-rw-r--r--bin/tests/system/rpzrecurse/ns3/example.db15
-rw-r--r--bin/tests/system/rpzrecurse/ns3/named1.conf.in35
-rw-r--r--bin/tests/system/rpzrecurse/ns3/named2.conf.in34
-rw-r--r--bin/tests/system/rpzrecurse/ns3/policy.db13
-rw-r--r--bin/tests/system/rpzrecurse/ns3/root.db15
-rw-r--r--bin/tests/system/rpzrecurse/ns4/child.example.db16
-rw-r--r--bin/tests/system/rpzrecurse/ns4/named.conf.in26
-rw-r--r--bin/tests/system/rpzrecurse/prereq.sh32
-rw-r--r--bin/tests/system/rpzrecurse/setup.sh43
-rwxr-xr-xbin/tests/system/rpzrecurse/testgen.pl341
-rw-r--r--bin/tests/system/rpzrecurse/tests.sh389
-rw-r--r--bin/tests/system/rrchecker/classlist.good3
-rw-r--r--bin/tests/system/rrchecker/clean.sh11
-rw-r--r--bin/tests/system/rrchecker/privatelist.good0
-rw-r--r--bin/tests/system/rrchecker/tests.sh82
-rw-r--r--bin/tests/system/rrchecker/typelist.good77
-rw-r--r--bin/tests/system/rrl/broken.conf47
-rw-r--r--bin/tests/system/rrl/clean.sh17
-rw-r--r--bin/tests/system/rrl/ns1/named.conf.in24
-rw-r--r--bin/tests/system/rrl/ns1/root.db26
-rw-r--r--bin/tests/system/rrl/ns2/hints13
-rw-r--r--bin/tests/system/rrl/ns2/named.conf.in63
-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.in44
-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.in64
-rw-r--r--bin/tests/system/rrl/ns4/tld4.db42
-rw-r--r--bin/tests/system/rrl/setup.sh20
-rw-r--r--bin/tests/system/rrl/tests.sh282
-rw-r--r--bin/tests/system/rrsetorder/clean.sh20
-rw-r--r--bin/tests/system/rrsetorder/dig.out.fixed.good4
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good14
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good104
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good114
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good124
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good134
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good144
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good154
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good164
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good174
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good184
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good194
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good24
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good204
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good214
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good224
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good234
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good244
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good34
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good44
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good54
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good64
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good74
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good84
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good94
-rw-r--r--bin/tests/system/rrsetorder/ns1/named.conf.in36
-rw-r--r--bin/tests/system/rrsetorder/ns1/root.db39
-rw-r--r--bin/tests/system/rrsetorder/ns2/named.conf.in36
-rw-r--r--bin/tests/system/rrsetorder/ns3/named.conf.in35
-rw-r--r--bin/tests/system/rrsetorder/ns4/named.conf.in32
-rw-r--r--bin/tests/system/rrsetorder/setup.sh19
-rw-r--r--bin/tests/system/rrsetorder/tests.sh472
-rw-r--r--bin/tests/system/rsabigexponent/Makefile.in50
-rw-r--r--bin/tests/system/rsabigexponent/bigkey.c258
-rw-r--r--bin/tests/system/rsabigexponent/clean.sh20
-rw-r--r--bin/tests/system/rsabigexponent/conf/bad01.conf14
-rw-r--r--bin/tests/system/rsabigexponent/conf/bad02.conf14
-rw-r--r--bin/tests/system/rsabigexponent/conf/bad03.conf14
-rw-r--r--bin/tests/system/rsabigexponent/conf/good01.conf14
-rw-r--r--bin/tests/system/rsabigexponent/conf/good02.conf14
-rw-r--r--bin/tests/system/rsabigexponent/conf/good03.conf14
-rw-r--r--bin/tests/system/rsabigexponent/ns1/named.conf.in33
-rw-r--r--bin/tests/system/rsabigexponent/ns1/root.db.in22
-rwxr-xr-xbin/tests/system/rsabigexponent/ns1/sign.sh32
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.key2
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.private10
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.key2
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.private10
-rw-r--r--bin/tests/system/rsabigexponent/ns2/dsset-example.in2
-rw-r--r--bin/tests/system/rsabigexponent/ns2/example.db.bad110
-rw-r--r--bin/tests/system/rsabigexponent/ns2/example.db.in21
-rw-r--r--bin/tests/system/rsabigexponent/ns2/named.conf.in37
-rwxr-xr-xbin/tests/system/rsabigexponent/ns2/sign.sh27
-rw-r--r--bin/tests/system/rsabigexponent/ns3/named.conf.in34
-rw-r--r--bin/tests/system/rsabigexponent/prereq.sh24
-rw-r--r--bin/tests/system/rsabigexponent/setup.sh23
-rw-r--r--bin/tests/system/rsabigexponent/tests.sh55
-rw-r--r--bin/tests/system/run.sh207
-rw-r--r--bin/tests/system/runall.sh96
-rw-r--r--bin/tests/system/runsequential.sh25
-rw-r--r--bin/tests/system/runtime/README6
-rw-r--r--bin/tests/system/runtime/clean.sh20
-rw-r--r--bin/tests/system/runtime/ns2/named-alt1.conf.in33
-rw-r--r--bin/tests/system/runtime/ns2/named-alt2.conf.in33
-rw-r--r--bin/tests/system/runtime/ns2/named-alt3.conf.in34
-rw-r--r--bin/tests/system/runtime/ns2/named-alt4.conf.in30
-rw-r--r--bin/tests/system/runtime/ns2/named-alt5.conf.in29
-rw-r--r--bin/tests/system/runtime/ns2/named-alt6.conf.in30
-rw-r--r--bin/tests/system/runtime/ns2/named1.conf.in33
-rw-r--r--bin/tests/system/runtime/setup.sh35
-rw-r--r--bin/tests/system/runtime/tests.sh153
-rw-r--r--bin/tests/system/send.pl31
-rw-r--r--bin/tests/system/setup.sh32
-rw-r--r--bin/tests/system/sfcache/README12
-rw-r--r--bin/tests/system/sfcache/clean.sh19
-rw-r--r--bin/tests/system/sfcache/ns1/named.conf.in33
-rw-r--r--bin/tests/system/sfcache/ns1/root.db.in22
-rw-r--r--bin/tests/system/sfcache/ns1/sign.sh34
-rw-r--r--bin/tests/system/sfcache/ns2/example.db.in101
-rw-r--r--bin/tests/system/sfcache/ns2/named.conf.in48
-rw-r--r--bin/tests/system/sfcache/ns2/sign.sh24
-rw-r--r--bin/tests/system/sfcache/ns5/named.conf.in43
-rw-r--r--bin/tests/system/sfcache/ns5/trusted.conf.bad14
-rw-r--r--bin/tests/system/sfcache/prereq.sh23
-rw-r--r--bin/tests/system/sfcache/setup.sh26
-rw-r--r--bin/tests/system/sfcache/tests.sh96
-rw-r--r--bin/tests/system/smartsign/child.db22
-rw-r--r--bin/tests/system/smartsign/clean.sh13
-rw-r--r--bin/tests/system/smartsign/parent.db29
-rw-r--r--bin/tests/system/smartsign/prereq.sh15
-rw-r--r--bin/tests/system/smartsign/setup.sh17
-rw-r--r--bin/tests/system/smartsign/tests.sh342
-rw-r--r--bin/tests/system/sortlist/clean.sh16
-rw-r--r--bin/tests/system/sortlist/ns1/example.db35
-rw-r--r--bin/tests/system/sortlist/ns1/named.conf.in43
-rw-r--r--bin/tests/system/sortlist/ns1/root.db22
-rw-r--r--bin/tests/system/sortlist/setup.sh16
-rw-r--r--bin/tests/system/sortlist/tests.sh49
-rw-r--r--bin/tests/system/spf/clean.sh13
-rw-r--r--bin/tests/system/spf/ns1/named.conf.in40
-rw-r--r--bin/tests/system/spf/ns1/spf.db16
-rw-r--r--bin/tests/system/spf/setup.sh16
-rw-r--r--bin/tests/system/spf/tests.sh37
-rwxr-xr-xbin/tests/system/start.pl345
-rw-r--r--bin/tests/system/start.sh13
-rwxr-xr-xbin/tests/system/staticstub/clean.sh25
-rw-r--r--bin/tests/system/staticstub/conf/bad01.conf30
-rw-r--r--bin/tests/system/staticstub/conf/bad02.conf30
-rw-r--r--bin/tests/system/staticstub/conf/bad03.conf30
-rw-r--r--bin/tests/system/staticstub/conf/bad04.conf30
-rw-r--r--bin/tests/system/staticstub/conf/bad05.conf31
-rw-r--r--bin/tests/system/staticstub/conf/bad06.conf31
-rw-r--r--bin/tests/system/staticstub/conf/bad07.conf31
-rw-r--r--bin/tests/system/staticstub/conf/bad08.conf31
-rw-r--r--bin/tests/system/staticstub/conf/bad09.conf30
-rw-r--r--bin/tests/system/staticstub/conf/bad10.conf32
-rw-r--r--bin/tests/system/staticstub/conf/bad11.conf32
-rw-r--r--bin/tests/system/staticstub/conf/good01.conf31
-rw-r--r--bin/tests/system/staticstub/conf/good02.conf30
-rw-r--r--bin/tests/system/staticstub/conf/good03.conf30
-rw-r--r--bin/tests/system/staticstub/conf/good04.conf30
-rw-r--r--bin/tests/system/staticstub/conf/good05.conf31
-rw-r--r--bin/tests/system/staticstub/knowngood.dig.out.rec18
-rw-r--r--bin/tests/system/staticstub/ns1/named.conf.in22
-rw-r--r--bin/tests/system/staticstub/ns1/root.db17
-rw-r--r--bin/tests/system/staticstub/ns2/named.conf.in59
-rw-r--r--bin/tests/system/staticstub/ns3/example.db.in30
-rw-r--r--bin/tests/system/staticstub/ns3/example.org.db22
-rw-r--r--bin/tests/system/staticstub/ns3/named.conf.in43
-rwxr-xr-xbin/tests/system/staticstub/ns3/sign.sh42
-rw-r--r--bin/tests/system/staticstub/ns3/undelegated.db.in21
-rw-r--r--bin/tests/system/staticstub/ns4/example.com.db21
-rw-r--r--bin/tests/system/staticstub/ns4/example.info.db22
-rw-r--r--bin/tests/system/staticstub/ns4/example.org.db23
-rw-r--r--bin/tests/system/staticstub/ns4/named.conf.in42
-rwxr-xr-xbin/tests/system/staticstub/ns4/sign.sh24
-rw-r--r--bin/tests/system/staticstub/ns4/sub.example.db.in24
-rwxr-xr-xbin/tests/system/staticstub/prereq.sh15
-rwxr-xr-xbin/tests/system/staticstub/setup.sh28
-rwxr-xr-xbin/tests/system/staticstub/tests.sh216
-rw-r--r--bin/tests/system/statistics/ans4/ans.pl116
-rw-r--r--bin/tests/system/statistics/clean.sh26
-rw-r--r--bin/tests/system/statistics/ns1/named.conf.in41
-rw-r--r--bin/tests/system/statistics/ns1/root.db22
-rw-r--r--bin/tests/system/statistics/ns1/zone.db12
-rw-r--r--bin/tests/system/statistics/ns2/example.db26
-rw-r--r--bin/tests/system/statistics/ns2/internal.db28
-rw-r--r--bin/tests/system/statistics/ns2/named.conf.in47
-rw-r--r--bin/tests/system/statistics/ns3/internal.db26
-rw-r--r--bin/tests/system/statistics/ns3/named.conf.in47
-rw-r--r--bin/tests/system/statistics/ns3/root.hint12
-rw-r--r--bin/tests/system/statistics/prereq.sh27
-rw-r--r--bin/tests/system/statistics/setup.sh18
-rw-r--r--bin/tests/system/statistics/tests.sh164
-rw-r--r--bin/tests/system/statschannel/clean.sh20
-rw-r--r--bin/tests/system/statschannel/fetch.pl41
-rw-r--r--bin/tests/system/statschannel/ns2/example.db47
-rw-r--r--bin/tests/system/statschannel/ns2/named.conf.in40
-rw-r--r--bin/tests/system/statschannel/prereq.sh25
-rw-r--r--bin/tests/system/statschannel/server-json.pl33
-rw-r--r--bin/tests/system/statschannel/server-xml.pl23
-rw-r--r--bin/tests/system/statschannel/setup.sh17
-rw-r--r--bin/tests/system/statschannel/tests.sh215
-rw-r--r--bin/tests/system/statschannel/traffic-json.pl47
-rw-r--r--bin/tests/system/statschannel/traffic-xml.pl44
-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/stop.pl193
-rw-r--r--bin/tests/system/stop.sh14
-rw-r--r--bin/tests/system/stopall.sh22
-rw-r--r--bin/tests/system/stress/clean.sh22
-rw-r--r--bin/tests/system/stress/ns1/named.conf29
-rw-r--r--bin/tests/system/stress/ns2/named.conf31
-rw-r--r--bin/tests/system/stress/ns3/named.conf48
-rw-r--r--bin/tests/system/stress/ns4/named.conf33
-rw-r--r--bin/tests/system/stress/prereq.sh21
-rw-r--r--bin/tests/system/stress/setup.pl83
-rw-r--r--bin/tests/system/stress/setup.sh16
-rw-r--r--bin/tests/system/stress/tests.sh37
-rw-r--r--bin/tests/system/stress/update.pl99
-rw-r--r--bin/tests/system/stub/clean.sh19
-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.in27
-rw-r--r--bin/tests/system/stub/ns1/root.db22
-rw-r--r--bin/tests/system/stub/ns2/child.example.db20
-rw-r--r--bin/tests/system/stub/ns2/named.conf.in32
-rw-r--r--bin/tests/system/stub/ns3/example.db20
-rw-r--r--bin/tests/system/stub/ns3/named.conf.in39
-rw-r--r--bin/tests/system/stub/setup.sh19
-rw-r--r--bin/tests/system/stub/tests.sh64
-rw-r--r--bin/tests/system/tcp/clean.sh17
-rw-r--r--bin/tests/system/tcp/ns1/named.conf.in37
-rw-r--r--bin/tests/system/tcp/ns1/root.db22
-rw-r--r--bin/tests/system/tcp/ns2/example.db26
-rw-r--r--bin/tests/system/tcp/ns2/named.conf.in44
-rw-r--r--bin/tests/system/tcp/ns3/named.conf.in39
-rw-r--r--bin/tests/system/tcp/ns4/named.conf.in41
-rw-r--r--bin/tests/system/tcp/setup.sh20
-rw-r--r--bin/tests/system/tcp/tests.sh57
-rw-r--r--bin/tests/system/testcrypto.sh68
-rw-r--r--bin/tests/system/testsock.pl42
-rw-r--r--bin/tests/system/testsock6.pl23
-rw-r--r--bin/tests/system/testsummary.sh59
-rw-r--r--bin/tests/system/tkey/Makefile.in54
-rw-r--r--bin/tests/system/tkey/clean.sh17
-rw-r--r--bin/tests/system/tkey/keycreate.c337
-rw-r--r--bin/tests/system/tkey/keydelete.c271
-rw-r--r--bin/tests/system/tkey/ns1/example.db25
-rw-r--r--bin/tests/system/tkey/ns1/named.conf.in50
-rw-r--r--bin/tests/system/tkey/ns1/setup.sh18
-rw-r--r--bin/tests/system/tkey/prereq.sh15
-rw-r--r--bin/tests/system/tkey/setup.sh19
-rw-r--r--bin/tests/system/tkey/tests.sh147
-rw-r--r--bin/tests/system/tsig/clean.sh22
-rw-r--r--bin/tests/system/tsig/ns1/example.db161
-rw-r--r--bin/tests/system/tsig/ns1/named.conf.in87
-rw-r--r--bin/tests/system/tsig/setup.sh19
-rw-r--r--bin/tests/system/tsig/tests.sh222
-rw-r--r--bin/tests/system/tsiggss/authsock.pl89
-rw-r--r--bin/tests/system/tsiggss/clean.sh25
-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.in51
-rw-r--r--bin/tests/system/tsiggss/ns1/named.conf.in47
-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.sh22
-rw-r--r--bin/tests/system/tsiggss/tests.sh105
-rw-r--r--bin/tests/system/unknown/clean.sh19
-rw-r--r--bin/tests/system/unknown/large.out1
-rw-r--r--bin/tests/system/unknown/ns1/broken1.db21
-rw-r--r--bin/tests/system/unknown/ns1/broken2.db21
-rw-r--r--bin/tests/system/unknown/ns1/broken3.db21
-rw-r--r--bin/tests/system/unknown/ns1/broken4.db21
-rw-r--r--bin/tests/system/unknown/ns1/broken5.db21
-rw-r--r--bin/tests/system/unknown/ns1/class10.hints11
-rw-r--r--bin/tests/system/unknown/ns1/example-class10.db29
-rw-r--r--bin/tests/system/unknown/ns1/example-in.db54
-rw-r--r--bin/tests/system/unknown/ns1/large.db3009
-rw-r--r--bin/tests/system/unknown/ns1/named.conf.in66
-rw-r--r--bin/tests/system/unknown/ns2/named.conf.in30
-rw-r--r--bin/tests/system/unknown/ns3/named.conf.in32
-rw-r--r--bin/tests/system/unknown/ns3/sign.sh19
-rw-r--r--bin/tests/system/unknown/prereq.sh15
-rw-r--r--bin/tests/system/unknown/setup.sh21
-rw-r--r--bin/tests/system/unknown/tests.sh189
-rw-r--r--bin/tests/system/unknown/zones/nan.bad10
-rw-r--r--bin/tests/system/upforwd/ans4/ans.pl361
-rw-r--r--bin/tests/system/upforwd/clean.sh26
-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.db16
-rw-r--r--bin/tests/system/upforwd/ns1/named.conf.in40
-rw-r--r--bin/tests/system/upforwd/ns2/named.conf.in35
-rw-r--r--bin/tests/system/upforwd/ns3/named.conf.in45
-rw-r--r--bin/tests/system/upforwd/ns3/nomaster.db12
-rw-r--r--bin/tests/system/upforwd/prereq.sh21
-rw-r--r--bin/tests/system/upforwd/setup.sh36
-rw-r--r--bin/tests/system/upforwd/tests.sh198
-rw-r--r--bin/tests/system/verify/clean.sh17
-rw-r--r--bin/tests/system/verify/prereq.sh15
-rw-r--r--bin/tests/system/verify/setup.sh19
-rw-r--r--bin/tests/system/verify/tests.sh108
-rw-r--r--bin/tests/system/verify/zones/genzones.sh241
-rw-r--r--bin/tests/system/verify/zones/unsigned.db27
-rw-r--r--bin/tests/system/views/clean.sh31
-rw-r--r--bin/tests/system/views/ns1/named.conf.in27
-rw-r--r--bin/tests/system/views/ns1/root.db22
-rw-r--r--bin/tests/system/views/ns2/1.10.in-addr.arpa.db11
-rw-r--r--bin/tests/system/views/ns2/clone.db23
-rw-r--r--bin/tests/system/views/ns2/example1.db26
-rw-r--r--bin/tests/system/views/ns2/example2.db26
-rw-r--r--bin/tests/system/views/ns2/external/inline.db27
-rw-r--r--bin/tests/system/views/ns2/internal.db28
-rw-r--r--bin/tests/system/views/ns2/internal/inline.db27
-rw-r--r--bin/tests/system/views/ns2/named1.conf.in43
-rw-r--r--bin/tests/system/views/ns2/named2.conf.in98
-rw-r--r--bin/tests/system/views/ns3/child.clone.db21
-rw-r--r--bin/tests/system/views/ns3/internal.db26
-rw-r--r--bin/tests/system/views/ns3/named1.conf.in48
-rw-r--r--bin/tests/system/views/ns3/named2.conf.in48
-rw-r--r--bin/tests/system/views/ns5/child.clone.db21
-rw-r--r--bin/tests/system/views/ns5/named.conf.in42
-rw-r--r--bin/tests/system/views/setup.sh44
-rw-r--r--bin/tests/system/views/tests.sh134
-rw-r--r--bin/tests/system/wildcard/clean.sh25
-rw-r--r--bin/tests/system/wildcard/ns1/dlv.db.in12
-rw-r--r--bin/tests/system/wildcard/ns1/named.conf.in38
-rw-r--r--bin/tests/system/wildcard/ns1/nsec.db.in15
-rw-r--r--bin/tests/system/wildcard/ns1/nsec3.db.in15
-rw-r--r--bin/tests/system/wildcard/ns1/private.nsec.db.in14
-rw-r--r--bin/tests/system/wildcard/ns1/private.nsec3.db.in15
-rw-r--r--bin/tests/system/wildcard/ns1/root.db.in16
-rwxr-xr-xbin/tests/system/wildcard/ns1/sign.sh104
-rw-r--r--bin/tests/system/wildcard/ns2/hints11
-rw-r--r--bin/tests/system/wildcard/ns2/named.conf.in24
-rw-r--r--bin/tests/system/wildcard/ns3/hints11
-rw-r--r--bin/tests/system/wildcard/ns3/named.conf.in26
-rw-r--r--bin/tests/system/wildcard/ns4/named.conf.in28
-rw-r--r--bin/tests/system/wildcard/ns5/hints11
-rw-r--r--bin/tests/system/wildcard/ns5/named.conf.in27
-rw-r--r--bin/tests/system/wildcard/prereq.sh15
-rw-r--r--bin/tests/system/wildcard/setup.sh25
-rw-r--r--bin/tests/system/wildcard/tests.sh147
-rw-r--r--bin/tests/system/win32/bigkey.dsp.in95
-rw-r--r--bin/tests/system/win32/bigkey.dsw29
-rw-r--r--bin/tests/system/win32/bigkey.mak.in346
-rw-r--r--bin/tests/system/win32/bigkey.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/bigkey.vcxproj.in110
-rw-r--r--bin/tests/system/win32/bigkey.vcxproj.user3
-rw-r--r--bin/tests/system/win32/feature-test.dsp.in95
-rw-r--r--bin/tests/system/win32/feature-test.dsw29
-rw-r--r--bin/tests/system/win32/feature-test.mak.in318
-rw-r--r--bin/tests/system/win32/feature-test.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/feature-test.vcxproj.in110
-rw-r--r--bin/tests/system/win32/feature-test.vcxproj.user3
-rw-r--r--bin/tests/system/win32/gencheck.dsp.in95
-rw-r--r--bin/tests/system/win32/gencheck.dsw29
-rw-r--r--bin/tests/system/win32/gencheck.mak.in318
-rw-r--r--bin/tests/system/win32/gencheck.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/gencheck.vcxproj.in110
-rw-r--r--bin/tests/system/win32/gencheck.vcxproj.user3
-rw-r--r--bin/tests/system/win32/keycreate.dsp.in95
-rw-r--r--bin/tests/system/win32/keycreate.dsw29
-rw-r--r--bin/tests/system/win32/keycreate.mak.in346
-rw-r--r--bin/tests/system/win32/keycreate.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/keycreate.vcxproj.in110
-rw-r--r--bin/tests/system/win32/keycreate.vcxproj.user3
-rw-r--r--bin/tests/system/win32/keydelete.dsp.in95
-rw-r--r--bin/tests/system/win32/keydelete.dsw29
-rw-r--r--bin/tests/system/win32/keydelete.mak.in346
-rw-r--r--bin/tests/system/win32/keydelete.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/keydelete.vcxproj.in110
-rw-r--r--bin/tests/system/win32/keydelete.vcxproj.user3
-rw-r--r--bin/tests/system/win32/lwtest.dsp.in95
-rw-r--r--bin/tests/system/win32/lwtest.dsw29
-rw-r--r--bin/tests/system/win32/lwtest.mak.in346
-rw-r--r--bin/tests/system/win32/lwtest.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/lwtest.vcxproj.in110
-rw-r--r--bin/tests/system/win32/lwtest.vcxproj.user3
-rw-r--r--bin/tests/system/win32/pipequeries.dsp.in95
-rw-r--r--bin/tests/system/win32/pipequeries.dsw29
-rw-r--r--bin/tests/system/win32/pipequeries.mak.in346
-rw-r--r--bin/tests/system/win32/pipequeries.vcxproj.filters.in22
-rw-r--r--bin/tests/system/win32/pipequeries.vcxproj.in110
-rw-r--r--bin/tests/system/win32/pipequeries.vcxproj.user3
-rw-r--r--bin/tests/system/xfer/ans5/badkeydata10
-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/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/clean.sh35
-rw-r--r--bin/tests/system/xfer/dig1.good155
-rw-r--r--bin/tests/system/xfer/dig2.good155
-rw-r--r--bin/tests/system/xfer/knowngood.mapped26
-rw-r--r--bin/tests/system/xfer/ns1/axfr-too-big.db13
-rw-r--r--bin/tests/system/xfer/ns1/ixfr-too-big.db.in16
-rw-r--r--bin/tests/system/xfer/ns1/named.conf.in54
-rw-r--r--bin/tests/system/xfer/ns1/root.db25
-rw-r--r--bin/tests/system/xfer/ns2/mapped.db.in26
-rw-r--r--bin/tests/system/xfer/ns2/named.conf.in72
-rw-r--r--bin/tests/system/xfer/ns2/slave.db.in17
-rw-r--r--bin/tests/system/xfer/ns3/named.conf.in72
-rw-r--r--bin/tests/system/xfer/ns4/named.conf.base46
-rw-r--r--bin/tests/system/xfer/ns4/root.db.in12
-rw-r--r--bin/tests/system/xfer/ns6/named.conf.in67
-rw-r--r--bin/tests/system/xfer/ns7/named.conf.in52
-rw-r--r--bin/tests/system/xfer/ns8/example.db22
-rw-r--r--bin/tests/system/xfer/ns8/named.conf.in44
-rw-r--r--bin/tests/system/xfer/prereq.sh27
-rw-r--r--bin/tests/system/xfer/setup.sh45
-rwxr-xr-xbin/tests/system/xfer/tests.sh468
-rw-r--r--bin/tests/system/xferquota/clean.sh23
-rw-r--r--bin/tests/system/xferquota/ns1/changing1.db25
-rw-r--r--bin/tests/system/xferquota/ns1/changing2.db25
-rw-r--r--bin/tests/system/xferquota/ns1/named.conf.in43
-rw-r--r--bin/tests/system/xferquota/ns1/root.db27
-rw-r--r--bin/tests/system/xferquota/ns2/example.db144
-rw-r--r--bin/tests/system/xferquota/ns2/named.conf.in38
-rw-r--r--bin/tests/system/xferquota/setup.pl38
-rw-r--r--bin/tests/system/xferquota/setup.sh26
-rwxr-xr-xbin/tests/system/xferquota/tests.sh62
-rw-r--r--bin/tests/system/zero/ans5/ans.pl79
-rw-r--r--bin/tests/system/zero/clean.sh17
-rw-r--r--bin/tests/system/zero/ns1/named.conf.in27
-rw-r--r--bin/tests/system/zero/ns1/root.db24
-rw-r--r--bin/tests/system/zero/ns2/named.conf.in32
-rw-r--r--bin/tests/system/zero/ns2/tld.db18
-rw-r--r--bin/tests/system/zero/ns3/named.conf.in27
-rw-r--r--bin/tests/system/zero/ns3/root.hint11
-rw-r--r--bin/tests/system/zero/ns4/named.conf.in33
-rw-r--r--bin/tests/system/zero/ns4/one.tld.db15
-rw-r--r--bin/tests/system/zero/prereq.sh21
-rw-r--r--bin/tests/system/zero/setup.sh20
-rw-r--r--bin/tests/system/zero/tests.sh89
-rw-r--r--bin/tests/system/zonechecks/a.db12
-rw-r--r--bin/tests/system/zonechecks/aaaa.db12
-rw-r--r--bin/tests/system/zonechecks/bigserial.db12
-rw-r--r--bin/tests/system/zonechecks/clean.sh19
-rw-r--r--bin/tests/system/zonechecks/cname.db12
-rw-r--r--bin/tests/system/zonechecks/dname.db12
-rw-r--r--bin/tests/system/zonechecks/noaddress.db12
-rw-r--r--bin/tests/system/zonechecks/ns1/named.conf.in71
-rw-r--r--bin/tests/system/zonechecks/ns2/named.conf.in41
-rw-r--r--bin/tests/system/zonechecks/nxdomain.db12
-rw-r--r--bin/tests/system/zonechecks/prereq.sh15
-rw-r--r--bin/tests/system/zonechecks/setup.sh34
-rw-r--r--bin/tests/system/zonechecks/tests.sh255
-rw-r--r--bin/tests/testdata/wire/wire_test.data9
-rw-r--r--bin/tests/testdata/wire/wire_test.data214
-rw-r--r--bin/tests/testdata/wire/wire_test.data314
-rw-r--r--bin/tests/testdata/wire/wire_test.data431
-rw-r--r--bin/tests/virtual-time/Makefile.in38
-rw-r--r--bin/tests/virtual-time/README18
-rw-r--r--bin/tests/virtual-time/autosign-ksk/clean.sh20
-rw-r--r--bin/tests/virtual-time/autosign-ksk/ns1/example.db.in21
-rw-r--r--bin/tests/virtual-time/autosign-ksk/ns1/named.conf50
-rw-r--r--bin/tests/virtual-time/autosign-ksk/ns1/root.db23
-rw-r--r--bin/tests/virtual-time/autosign-ksk/ns1/sign.sh33
-rw-r--r--bin/tests/virtual-time/autosign-ksk/ns1/wrap.sh17
-rw-r--r--bin/tests/virtual-time/autosign-ksk/setup.sh21
-rw-r--r--bin/tests/virtual-time/autosign-ksk/tests.sh102
-rw-r--r--bin/tests/virtual-time/autosign-zsk/clean.sh20
-rw-r--r--bin/tests/virtual-time/autosign-zsk/ns1/example.db.in21
-rw-r--r--bin/tests/virtual-time/autosign-zsk/ns1/named.conf50
-rw-r--r--bin/tests/virtual-time/autosign-zsk/ns1/root.db23
-rw-r--r--bin/tests/virtual-time/autosign-zsk/ns1/sign.sh33
-rw-r--r--bin/tests/virtual-time/autosign-zsk/ns1/wrap.sh17
-rw-r--r--bin/tests/virtual-time/autosign-zsk/setup.sh21
-rw-r--r--bin/tests/virtual-time/autosign-zsk/tests.sh93
-rw-r--r--bin/tests/virtual-time/cleanall.sh30
-rw-r--r--bin/tests/virtual-time/common/controls.conf20
-rw-r--r--bin/tests/virtual-time/common/rndc.conf19
-rw-r--r--bin/tests/virtual-time/common/root.hint12
-rw-r--r--bin/tests/virtual-time/conf.sh.in45
-rw-r--r--bin/tests/virtual-time/run.sh102
-rw-r--r--bin/tests/virtual-time/runall.sh33
-rw-r--r--bin/tests/virtual-time/setup.sh30
-rw-r--r--bin/tests/virtual-time/slave/clean.sh17
-rw-r--r--bin/tests/virtual-time/slave/ns1/example.db.in21
-rw-r--r--bin/tests/virtual-time/slave/ns1/named.conf45
-rw-r--r--bin/tests/virtual-time/slave/ns1/root.db23
-rw-r--r--bin/tests/virtual-time/slave/ns1/wrap.sh17
-rw-r--r--bin/tests/virtual-time/slave/setup.sh11
-rw-r--r--bin/tests/virtual-time/slave/tests.sh42
-rw-r--r--bin/tests/virtual-time/start.pl177
-rw-r--r--bin/tests/virtual-time/start.sh13
-rw-r--r--bin/tests/virtual-time/stop.pl174
-rw-r--r--bin/tests/virtual-time/stop.sh14
-rw-r--r--bin/tests/virtual-time/testsock.pl43
-rw-r--r--bin/tests/virtual-time/vtwrapper.c301
-rw-r--r--bin/tests/win32/backtrace_test.dsp.in103
-rw-r--r--bin/tests/win32/backtrace_test.dsw29
-rw-r--r--bin/tests/win32/backtrace_test.mak.in299
-rw-r--r--bin/tests/win32/backtrace_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/backtrace_test.vcxproj.in110
-rw-r--r--bin/tests/win32/backtrace_test.vcxproj.user3
-rw-r--r--bin/tests/win32/inter_test.dsp.in103
-rw-r--r--bin/tests/win32/inter_test.dsw29
-rw-r--r--bin/tests/win32/inter_test.mak.in299
-rw-r--r--bin/tests/win32/inter_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/inter_test.vcxproj.in110
-rw-r--r--bin/tests/win32/inter_test.vcxproj.user3
-rw-r--r--bin/tests/win32/makejournal.dsp.in103
-rw-r--r--bin/tests/win32/makejournal.dsw29
-rw-r--r--bin/tests/win32/makejournal.mak.in299
-rw-r--r--bin/tests/win32/makejournal.vcxproj.filters.in18
-rw-r--r--bin/tests/win32/makejournal.vcxproj.in110
-rw-r--r--bin/tests/win32/makejournal.vcxproj.user3
-rw-r--r--bin/tests/win32/rwlock_test.dsp.in103
-rw-r--r--bin/tests/win32/rwlock_test.dsw29
-rw-r--r--bin/tests/win32/rwlock_test.mak.in299
-rw-r--r--bin/tests/win32/rwlock_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/rwlock_test.vcxproj.in110
-rw-r--r--bin/tests/win32/rwlock_test.vcxproj.user3
-rw-r--r--bin/tests/win32/shutdown_test.dsp.in103
-rw-r--r--bin/tests/win32/shutdown_test.dsw29
-rw-r--r--bin/tests/win32/shutdown_test.mak.in299
-rw-r--r--bin/tests/win32/shutdown_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/shutdown_test.vcxproj.in110
-rw-r--r--bin/tests/win32/shutdown_test.vcxproj.user3
-rw-r--r--bin/tests/win32/sock_test.dsp.in103
-rw-r--r--bin/tests/win32/sock_test.dsw29
-rw-r--r--bin/tests/win32/sock_test.mak.in299
-rw-r--r--bin/tests/win32/sock_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/sock_test.vcxproj.in110
-rw-r--r--bin/tests/win32/sock_test.vcxproj.user3
-rw-r--r--bin/tests/win32/task_test.dsp.in103
-rw-r--r--bin/tests/win32/task_test.dsw29
-rw-r--r--bin/tests/win32/task_test.mak.in299
-rw-r--r--bin/tests/win32/task_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/task_test.vcxproj.in110
-rw-r--r--bin/tests/win32/task_test.vcxproj.user3
-rw-r--r--bin/tests/win32/timer_test.dsp.in103
-rw-r--r--bin/tests/win32/timer_test.dsw29
-rw-r--r--bin/tests/win32/timer_test.mak.in299
-rw-r--r--bin/tests/win32/timer_test.vcxproj.filters.in22
-rw-r--r--bin/tests/win32/timer_test.vcxproj.in110
-rw-r--r--bin/tests/win32/timer_test.vcxproj.user3
-rw-r--r--bin/tests/wire_test.c348
-rw-r--r--bin/tools/Makefile.in185
-rw-r--r--bin/tools/arpaname.156
-rw-r--r--bin/tools/arpaname.c48
-rw-r--r--bin/tools/arpaname.docbook66
-rw-r--r--bin/tools/arpaname.html57
-rw-r--r--bin/tools/dnstap-read.186
-rw-r--r--bin/tools/dnstap-read.c367
-rw-r--r--bin/tools/dnstap-read.docbook115
-rw-r--r--bin/tools/dnstap-read.html100
-rw-r--r--bin/tools/genrandom.877
-rw-r--r--bin/tools/genrandom.c132
-rw-r--r--bin/tools/genrandom.docbook111
-rw-r--r--bin/tools/genrandom.html93
-rw-r--r--bin/tools/isc-hmac-fixup.869
-rw-r--r--bin/tools/isc-hmac-fixup.c142
-rw-r--r--bin/tools/isc-hmac-fixup.docbook102
-rw-r--r--bin/tools/isc-hmac-fixup.html92
-rw-r--r--bin/tools/mdig.1408
-rw-r--r--bin/tools/mdig.c2081
-rw-r--r--bin/tools/mdig.docbook698
-rw-r--r--bin/tools/mdig.html577
-rw-r--r--bin/tools/named-journalprint.868
-rw-r--r--bin/tools/named-journalprint.c80
-rw-r--r--bin/tools/named-journalprint.docbook93
-rw-r--r--bin/tools/named-journalprint.html83
-rw-r--r--bin/tools/named-nzd2nzf.867
-rw-r--r--bin/tools/named-nzd2nzf.c101
-rw-r--r--bin/tools/named-nzd2nzf.docbook94
-rw-r--r--bin/tools/named-nzd2nzf.html85
-rw-r--r--bin/tools/named-rrchecker.181
-rw-r--r--bin/tools/named-rrchecker.c322
-rw-r--r--bin/tools/named-rrchecker.docbook96
-rw-r--r--bin/tools/named-rrchecker.html87
-rw-r--r--bin/tools/nsec3hash.878
-rw-r--r--bin/tools/nsec3hash.c116
-rw-r--r--bin/tools/nsec3hash.docbook116
-rw-r--r--bin/tools/nsec3hash.html97
-rw-r--r--bin/tools/win32/arpaname.dsp.in103
-rw-r--r--bin/tools/win32/arpaname.dsw29
-rw-r--r--bin/tools/win32/arpaname.mak.in299
-rw-r--r--bin/tools/win32/arpaname.vcxproj.filters.in22
-rw-r--r--bin/tools/win32/arpaname.vcxproj.in110
-rw-r--r--bin/tools/win32/arpaname.vcxproj.user3
-rw-r--r--bin/tools/win32/genrandom.dsp.in103
-rw-r--r--bin/tools/win32/genrandom.dsw29
-rw-r--r--bin/tools/win32/genrandom.mak.in299
-rw-r--r--bin/tools/win32/genrandom.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/genrandom.vcxproj.in110
-rw-r--r--bin/tools/win32/genrandom.vcxproj.user3
-rwxr-xr-xbin/tools/win32/ischmacfixup.dsp.in103
-rw-r--r--bin/tools/win32/ischmacfixup.dsw29
-rwxr-xr-xbin/tools/win32/ischmacfixup.mak.in299
-rw-r--r--bin/tools/win32/ischmacfixup.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/ischmacfixup.vcxproj.in112
-rw-r--r--bin/tools/win32/ischmacfixup.vcxproj.user3
-rw-r--r--bin/tools/win32/journalprint.dsp.in103
-rw-r--r--bin/tools/win32/journalprint.dsw29
-rw-r--r--bin/tools/win32/journalprint.mak.in299
-rw-r--r--bin/tools/win32/journalprint.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/journalprint.vcxproj.in112
-rw-r--r--bin/tools/win32/journalprint.vcxproj.user3
-rw-r--r--bin/tools/win32/mdig.dsp.in103
-rw-r--r--bin/tools/win32/mdig.dsw29
-rw-r--r--bin/tools/win32/mdig.mak.in299
-rw-r--r--bin/tools/win32/mdig.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/mdig.vcxproj.in110
-rw-r--r--bin/tools/win32/mdig.vcxproj.user3
-rw-r--r--bin/tools/win32/nsec3hash.dsp.in103
-rw-r--r--bin/tools/win32/nsec3hash.dsw29
-rw-r--r--bin/tools/win32/nsec3hash.mak.in299
-rw-r--r--bin/tools/win32/nsec3hash.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/nsec3hash.vcxproj.in110
-rw-r--r--bin/tools/win32/nsec3hash.vcxproj.user3
-rw-r--r--bin/tools/win32/rrchecker.dsp.in103
-rw-r--r--bin/tools/win32/rrchecker.dsw29
-rw-r--r--bin/tools/win32/rrchecker.mak.in299
-rw-r--r--bin/tools/win32/rrchecker.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/rrchecker.vcxproj.in112
-rw-r--r--bin/tools/win32/rrchecker.vcxproj.user3
-rw-r--r--bin/win32/BINDInstall/AccountInfo.cpp456
-rw-r--r--bin/win32/BINDInstall/AccountInfo.h41
-rw-r--r--bin/win32/BINDInstall/BINDInstall.cpp98
-rw-r--r--bin/win32/BINDInstall/BINDInstall.dsp.in177
-rw-r--r--bin/win32/BINDInstall/BINDInstall.dsw29
-rw-r--r--bin/win32/BINDInstall/BINDInstall.h57
-rw-r--r--bin/win32/BINDInstall/BINDInstall.mak.in428
-rw-r--r--bin/win32/BINDInstall/BINDInstall.rc324
-rw-r--r--bin/win32/BINDInstall/BINDInstall.vcxproj.filters.in79
-rw-r--r--bin/win32/BINDInstall/BINDInstall.vcxproj.in148
-rw-r--r--bin/win32/BINDInstall/BINDInstall.vcxproj.user3
-rw-r--r--bin/win32/BINDInstall/BINDInstallDlg.cpp1590
-rw-r--r--bin/win32/BINDInstall/BINDInstallDlg.h126
-rw-r--r--bin/win32/BINDInstall/DirBrowse.cpp95
-rw-r--r--bin/win32/BINDInstall/DirBrowse.h64
-rw-r--r--bin/win32/BINDInstall/StdAfx.cpp8
-rw-r--r--bin/win32/BINDInstall/StdAfx.h36
-rw-r--r--bin/win32/BINDInstall/VersionInfo.cpp293
-rw-r--r--bin/win32/BINDInstall/VersionInfo.h62
-rw-r--r--bin/win32/BINDInstall/res/BINDInstall.icobin0 -> 1078 bytes
-rw-r--r--bin/win32/BINDInstall/res/BINDInstall.rc213
-rw-r--r--bin/win32/BINDInstall/resource.h104
-rw-r--r--bind.keys50
-rw-r--r--bind.keys.h108
2599 files changed, 382929 insertions, 0 deletions
diff --git a/bin/Makefile.in b/bin/Makefile.in
new file mode 100644
index 0000000..f0c504a
--- /dev/null
+++ b/bin/Makefile.in
@@ -0,0 +1,18 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = named rndc dig delv dnssec tools nsupdate check confgen \
+ @NZD_TOOLS@ @PYTHON_TOOLS@ @PKCS11_TOOLS@ tests
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in
new file mode 100644
index 0000000..c124e80
--- /dev/null
+++ b/bin/check/Makefile.in
@@ -0,0 +1,101 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.36 2009/12/05 23:31:40 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISCCFG_INCLUDES} \
+ ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@ -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+LIBS = ${ISCLIBS} @LIBS@
+NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@
+
+SUBDIRS =
+
+# Alphabetically
+TARGETS = named-checkconf@EXEEXT@ named-checkzone@EXEEXT@
+
+# Alphabetically
+SRCS = named-checkconf.c named-checkzone.c check-tool.c
+
+MANPAGES = named-checkconf.8 named-checkzone.8
+
+HTMLPAGES = named-checkconf.html named-checkzone.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+named-checkconf.@O@: named-checkconf.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/named-checkconf.c
+
+named-checkzone.@O@: named-checkzone.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/named-checkzone.c
+
+named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \
+ ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${BIND9DEPLIBS}
+ export BASEOBJS="named-checkconf.@O@ check-tool.@O@"; \
+ export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="named-checkzone.@O@ check-tool.@O@"; \
+ export LIBS0="${ISCCFGLIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: named-checkconf@EXEEXT@ named-checkzone@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkconf@EXEEXT@ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkzone@EXEEXT@ ${DESTDIR}${sbindir}
+ (cd ${DESTDIR}${sbindir}; rm -f named-compilezone@EXEEXT@; ${LINK_PROGRAM} named-checkzone@EXEEXT@ named-compilezone@EXEEXT@)
+ for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8 || exit 1; done
+ (cd ${DESTDIR}${mandir}/man8; rm -f named-compilezone.8; ${LINK_PROGRAM} named-checkzone.8 named-compilezone.8)
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man8/named-compilezone.8
+ for m in ${MANPAGES}; do rm -f ${DESTDIR}${mandir}/man8/$$m || exit 1; done
+ rm -f ${DESTDIR}${sbindir}/named-compilezone@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named-checkconf@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named-checkzone@EXEEXT@
+
+clean distclean::
+ rm -f ${TARGETS} r1.htm
diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c
new file mode 100644
index 0000000..dab9e8d
--- /dev/null
+++ b/bin/check/check-tool.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#ifdef _WIN32
+#include <Winsock2.h>
+#endif
+
+#include "check-tool.h"
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netdb.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/region.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/result.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include <isccfg/log.h>
+
+#ifndef CHECK_SIBLING
+#define CHECK_SIBLING 1
+#endif
+
+#ifndef CHECK_LOCAL
+#define CHECK_LOCAL 1
+#endif
+
+#ifdef HAVE_ADDRINFO
+#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GAISTRERROR
+#define USE_GETADDRINFO
+#endif
+#endif
+#endif
+
+#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
+bool docheckmx = false;
+bool dochecksrv = false;
+bool docheckns = false;
+#endif
+unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
+ DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_MANYERRORS |
+ DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKINTEGRITY |
+#if CHECK_SIBLING
+ DNS_ZONEOPT_CHECKSIBLING |
+#endif
+ DNS_ZONEOPT_CHECKWILDCARD |
+ DNS_ZONEOPT_WARNMXCNAME |
+ DNS_ZONEOPT_WARNSRVCNAME;
+unsigned int zone_options2 = 0;
+
+/*
+ * 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 },
+ { "trust-anchor-telemetry", 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) {
+ result = isc_mem_create(0, 0, &sym_mctx);
+ if (result != ISC_R_SUCCESS)
+ return;
+ }
+
+ 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);
+ if (key == NULL)
+ return;
+
+ 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, dns_name_t *name, dns_name_t *owner,
+ dns_rdataset_t *a, dns_rdataset_t *aaaa)
+{
+#ifdef USE_GETADDRINFO
+ 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 (!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);
+#else
+ return (true);
+#endif
+}
+
+static bool
+checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
+#ifdef USE_GETADDRINFO
+ 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 (!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);
+ }
+#else
+ return (true);
+#endif
+}
+
+static bool
+checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
+#ifdef USE_GETADDRINFO
+ 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 (!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);
+ }
+#else
+ return (true);
+#endif
+}
+
+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;
+
+ RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
+ isc_log_registercategories(log, categories);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+ cfg_log_init(log);
+
+ destination.file.stream = errout;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, 0) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
+ NULL, NULL) == ISC_R_SUCCESS);
+
+ *logp = log;
+ return (ISC_R_SUCCESS);
+}
+
+/*% scan the zone for oversize TTLs */
+static isc_result_t
+check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbiterator_t *dbiter = NULL;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdataset_t rdataset;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ name = dns_fixedname_initname(&fname);
+ dns_rdataset_init(&rdataset);
+
+ CHECK(dns_zone_getdb(zone, &db));
+ INSIST(db != NULL);
+
+ CHECK(dns_db_newversion(db, &version));
+ CHECK(dns_db_createiterator(db, 0, &dbiter));
+
+ for (result = dns_dbiterator_first(dbiter);
+ result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiter)) {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ if (result == DNS_R_NEWORIGIN)
+ result = ISC_R_SUCCESS;
+ CHECK(result);
+
+ CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter));
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.ttl > maxttl) {
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char tbuf[255];
+ isc_buffer_t b;
+ isc_region_t r;
+
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1);
+ CHECK(dns_rdatatype_totext(rdataset.type, &b));
+ isc_buffer_usedregion(&b, &r);
+ r.base[r.length] = 0;
+
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/%s TTL %d exceeds "
+ "maximum TTL %d",
+ nbuf, tbuf, rdataset.ttl, maxttl);
+ dns_rdataset_disassociate(&rdataset);
+ CHECK(ISC_R_RANGE);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ CHECK(result);
+
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(db, &node);
+ }
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (rdsiter != NULL)
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (dbiter != NULL)
+ dns_dbiterator_destroy(&dbiter);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, false);
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ return (result);
+}
+
+/*% 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_master);
+
+ 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));
+ CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
+ CHECK(dns_zone_setfile2(zone, filename, fileformat));
+ 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_setoption2(zone, zone_options2, 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));
+
+ /*
+ * When loading map files we can't catch oversize TTLs during
+ * load, so we check for them here.
+ */
+ if (fileformat == dns_masterformat_map && maxttl != 0) {
+ CHECK(check_ttls(zone, maxttl));
+ }
+
+ 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_dumptostream3(zone, output, fileformat, style,
+ rawversion);
+ if (output != stdout)
+ (void)isc_stdio_close(output);
+
+ return (result);
+}
+
+#ifdef _WIN32
+void
+InitSockets(void) {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if (err != 0) {
+ fprintf(stderr, "WSAStartup() failed: %d\n", err);
+ exit(1);
+ }
+}
+
+void
+DestroySockets(void) {
+ WSACleanup();
+}
+#endif
diff --git a/bin/check/check-tool.h b/bin/check/check-tool.h
new file mode 100644
index 0000000..a1acbe2
--- /dev/null
+++ b/bin/check/check-tool.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef CHECK_TOOL_H
+#define CHECK_TOOL_H
+
+/*! \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>
+
+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);
+
+#ifdef _WIN32
+void InitSockets(void);
+void DestroySockets(void);
+#endif
+
+extern int debug;
+extern const char *journal;
+extern bool nomerge;
+extern bool docheckmx;
+extern bool docheckns;
+extern bool dochecksrv;
+extern unsigned int zone_options;
+extern unsigned int zone_options2;
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/check/named-checkconf.8 b/bin/check/named-checkconf.8
new file mode 100644
index 0000000..16271cf
--- /dev/null
+++ b/bin/check/named-checkconf.8
@@ -0,0 +1,135 @@
+.\" Copyright (C) 2000-2002, 2004, 2005, 2007, 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named-checkconf
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-10
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NAMED\-CHECKCONF" "8" "2014\-01\-10" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named-checkconf \- named configuration file syntax checking tool
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\-checkconf\fR\ 'u
+\fBnamed\-checkconf\fR [\fB\-hjvz\fR] [\fB\-p\fR\ [\fB\-x\fR\ ]] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] {filename}
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-checkconf\fR
+checks the syntax, but not the semantics, of a
+\fBnamed\fR
+configuration file\&. The file is parsed and checked for syntax errors, along with all files included by it\&. If no file is specified,
+/etc/named\&.conf
+is read by default\&.
+.PP
+Note: files that
+\fBnamed\fR
+reads in separate parser contexts, such as
+rndc\&.key
+and
+bind\&.keys, are not automatically read by
+\fBnamed\-checkconf\fR\&. Configuration errors in these files may cause
+\fBnamed\fR
+to fail to run, even if
+\fBnamed\-checkconf\fR
+was successful\&.
+\fBnamed\-checkconf\fR
+can be run on these files explicitly, however\&.
+.SH "OPTIONS"
+.PP
+\-h
+.RS 4
+Print the usage summary and exit\&.
+.RE
+.PP
+\-j
+.RS 4
+When loading a zonefile read the journal if it exists\&.
+.RE
+.PP
+\-p
+.RS 4
+Print out the
+named\&.conf
+and included files in canonical form if no errors were detected\&. See also the
+\fB\-x\fR
+option\&.
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+directory
+so that include directives in the configuration file are processed as if run by a similarly chrooted
+\fBnamed\fR\&.
+.RE
+.PP
+\-v
+.RS 4
+Print the version of the
+\fBnamed\-checkconf\fR
+program and exit\&.
+.RE
+.PP
+\-x
+.RS 4
+When printing the configuration files in canonical form, obscure shared secrets by replacing them with strings of question marks (\*(Aq?\*(Aq)\&. This allows the contents of
+named\&.conf
+and related files to be shared \(em for example, when submitting bug reports \(em without compromising private data\&. This option cannot be used without
+\fB\-p\fR\&.
+.RE
+.PP
+\-z
+.RS 4
+Perform a test load of all master zones found in
+named\&.conf\&.
+.RE
+.PP
+filename
+.RS 4
+The name of the configuration file to be checked\&. If not specified, it defaults to
+/etc/named\&.conf\&.
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBnamed\-checkconf\fR
+returns an exit status of 1 if errors were detected and 0 otherwise\&.
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBnamed-checkzone\fR(8),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2002, 2004, 2005, 2007, 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c
new file mode 100644
index 0000000..29ff821
--- /dev/null
+++ b/bin/check/named-checkconf.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.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 <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/rootns.h>
+#include <dns/zone.h>
+
+#include "check-tool.h"
+
+static const char *program = "named-checkconf";
+
+isc_log_t *logc = NULL;
+
+#define CHECK(r)\
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+/*% usage */
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: %s [-hjvz] [-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), "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)
+{
+ 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 *mastersobj = 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)
+ return (ISC_R_SUCCESS);
+
+ cfg_map_get(zoptions, "type", &typeobj);
+ if (typeobj == NULL)
+ return (ISC_R_FAILURE);
+
+ /*
+ * 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), "master") != 0) &&
+ (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0))
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Is the redirect zone configured as a slave?
+ */
+ if (strcasecmp(cfg_obj_asstring(typeobj), "redirect") == 0) {
+ cfg_map_get(zoptions, "masters", &mastersobj);
+ if (mastersobj != 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
+ INSIST(0);
+ } 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
+ INSIST(0);
+ } 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
+ INSIST(0);
+ } 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
+ INSIST(0);
+ } 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
+ INSIST(0);
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ }
+
+ 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
+ INSIST(0);
+ } 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 if (strcasecmp(masterformatstr, "map") == 0)
+ masterformat = dns_masterformat_map;
+ else
+ INSIST(0);
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "max-zone-ttl", &obj)) {
+ maxttl = cfg_obj_asuint32(obj);
+ zone_options2 |= DNS_ZONEOPT2_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,
+ dns_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)
+{
+ 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);
+ 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) {
+ 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");
+ CHECK(config_getclass(classobj, dns_rdataclass_in,
+ &viewclass));
+ 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);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ if (views == NULL) {
+ tresult = configure_view("IN", "_default", config, NULL, mctx);
+ 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;
+ isc_entropy_t *ectx = NULL;
+ bool load_zones = false;
+ bool print = false;
+ unsigned int flags = 0;
+
+ isc_commandline_errprint = false;
+
+ /*
+ * Process memory debugging argument first.
+ */
+#define CMDLINE_FLAGS "dhjm: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;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) {
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+
+ case 'j':
+ nomerge = false;
+ 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(VERSION "\n");
+ 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 (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;
+
+#ifdef _WIN32
+ InitSockets();
+#endif
+
+ RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
+ == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS);
+
+ 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, logc, mctx);
+ if (result != ISC_R_SUCCESS)
+ exit_status = 1;
+
+ if (result == ISC_R_SUCCESS && load_zones) {
+ result = load_zones_fromconfig(config, mctx);
+ 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);
+
+ dns_name_destroy();
+
+ isc_log_destroy(&logc);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_destroy(&mctx);
+
+#ifdef _WIN32
+ DestroySockets();
+#endif
+
+ return (exit_status);
+}
diff --git a/bin/check/named-checkconf.docbook b/bin/check/named-checkconf.docbook
new file mode 100644
index 0000000..efdd0a0
--- /dev/null
+++ b/bin/check/named-checkconf.docbook
@@ -0,0 +1,197 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named-checkconf">
+ <info>
+ <date>2014-01-10</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named-checkconf</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname><application>named-checkconf</application></refname>
+ <refpurpose>named configuration file syntax checking tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>named-checkconf</command>
+ <arg choice="opt" rep="norepeat"><option>-hjvz</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p</option>
+ <arg choice="opt" rep="norepeat"><option>-x</option>
+ </arg></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">filename</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>named-checkconf</command>
+ checks the syntax, but not the semantics, of a
+ <command>named</command> configuration file. The file is parsed
+ and checked for syntax errors, along with all files included by it.
+ If no file is specified, <filename>/etc/named.conf</filename> is read
+ by default.
+ </para>
+ <para>
+ Note: files that <command>named</command> reads in separate
+ parser contexts, such as <filename>rndc.key</filename> and
+ <filename>bind.keys</filename>, are not automatically read
+ by <command>named-checkconf</command>. Configuration
+ errors in these files may cause <command>named</command> to
+ fail to run, even if <command>named-checkconf</command> was
+ successful. <command>named-checkconf</command> can be run
+ on these files explicitly, however.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Print the usage summary and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j</term>
+ <listitem>
+ <para>
+ When loading a zonefile read the journal if it exists.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p</term>
+ <listitem>
+ <para>
+ Print out the <filename>named.conf</filename> and included files
+ in canonical form if no errors were detected.
+ See also the <option>-x</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Chroot to <filename>directory</filename> so that include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted <command>named</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the version of the <command>named-checkconf</command>
+ program and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x</term>
+ <listitem>
+ <para>
+ When printing the configuration files in canonical
+ form, obscure shared secrets by replacing them with
+ strings of question marks ('?'). This allows the
+ contents of <filename>named.conf</filename> and related
+ files to be shared &mdash; for example, when submitting
+ bug reports &mdash; without compromising private data.
+ This option cannot be used without <option>-p</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Perform a test load of all master zones found in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>filename</term>
+ <listitem>
+ <para>
+ The name of the configuration file to be checked. If not
+ specified, it defaults to <filename>/etc/named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>RETURN VALUES</title></info>
+
+ <para><command>named-checkconf</command>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+</refentry>
diff --git a/bin/check/named-checkconf.html b/bin/check/named-checkconf.html
new file mode 100644
index 0000000..1f7cc8d
--- /dev/null
+++ b/bin/check/named-checkconf.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2002, 2004, 2005, 2007, 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-checkconf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named-checkconf"></a><div class="titlepage"></div>
+
+
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">named-checkconf</span>
+ &#8212; named configuration file syntax checking tool
+ </p>
+</div>
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named-checkconf</code>
+ [<code class="option">-hjvz</code>]
+ [<code class="option">-p</code>
+ [<code class="option">-x</code>
+ ]]
+ [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>]
+ {filename}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>named-checkconf</strong></span>
+ checks the syntax, but not the semantics, of a
+ <span class="command"><strong>named</strong></span> configuration file. The file is parsed
+ and checked for syntax errors, along with all files included by it.
+ If no file is specified, <code class="filename">/etc/named.conf</code> is read
+ by default.
+ </p>
+ <p>
+ Note: files that <span class="command"><strong>named</strong></span> reads in separate
+ parser contexts, such as <code class="filename">rndc.key</code> and
+ <code class="filename">bind.keys</code>, are not automatically read
+ by <span class="command"><strong>named-checkconf</strong></span>. Configuration
+ errors in these files may cause <span class="command"><strong>named</strong></span> to
+ fail to run, even if <span class="command"><strong>named-checkconf</strong></span> was
+ successful. <span class="command"><strong>named-checkconf</strong></span> can be run
+ on these files explicitly, however.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Print the usage summary and exit.
+ </p>
+ </dd>
+<dt><span class="term">-j</span></dt>
+<dd>
+ <p>
+ When loading a zonefile read the journal if it exists.
+ </p>
+ </dd>
+<dt><span class="term">-p</span></dt>
+<dd>
+ <p>
+ Print out the <code class="filename">named.conf</code> and included files
+ in canonical form if no errors were detected.
+ See also the <code class="option">-x</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Chroot to <code class="filename">directory</code> so that include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted <span class="command"><strong>named</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Print the version of the <span class="command"><strong>named-checkconf</strong></span>
+ program and exit.
+ </p>
+ </dd>
+<dt><span class="term">-x</span></dt>
+<dd>
+ <p>
+ When printing the configuration files in canonical
+ form, obscure shared secrets by replacing them with
+ strings of question marks ('?'). This allows the
+ contents of <code class="filename">named.conf</code> and related
+ files to be shared &#8212; for example, when submitting
+ bug reports &#8212; without compromising private data.
+ This option cannot be used without <code class="option">-p</code>.
+ </p>
+ </dd>
+<dt><span class="term">-z</span></dt>
+<dd>
+ <p>
+ Perform a test load of all master zones found in
+ <code class="filename">named.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">filename</span></dt>
+<dd>
+ <p>
+ The name of the configuration file to be checked. If not
+ specified, it defaults to <code class="filename">/etc/named.conf</code>.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>RETURN VALUES</h2>
+
+ <p><span class="command"><strong>named-checkconf</strong></span>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named-checkzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+</div></body>
+</html>
diff --git a/bin/check/named-checkzone.8 b/bin/check/named-checkzone.8
new file mode 100644
index 0000000..9293dd9
--- /dev/null
+++ b/bin/check/named-checkzone.8
@@ -0,0 +1,329 @@
+.\" Copyright (C) 2000-2002, 2004-2007, 2009-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named-checkzone
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-02-19
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NAMED\-CHECKZONE" "8" "2014\-02\-19" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named-checkzone, named-compilezone \- zone file validity checking or converting tool
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\-checkzone\fR\ 'u
+\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-J\ \fR\fB\fIfilename\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-l\ \fR\fB\fIttl\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename}
+.HP \w'\fBnamed\-compilezone\fR\ 'u
+\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-J\ \fR\fB\fIfilename\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-l\ \fR\fB\fIttl\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename}
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-checkzone\fR
+checks the syntax and integrity of a zone file\&. It performs the same checks as
+\fBnamed\fR
+does when loading a zone\&. This makes
+\fBnamed\-checkzone\fR
+useful for checking zone files before configuring them into a name server\&.
+.PP
+\fBnamed\-compilezone\fR
+is similar to
+\fBnamed\-checkzone\fR, but it always dumps the zone contents to a specified file in a specified format\&. Additionally, it applies stricter check levels by default, since the dump output will be used as an actual zone file loaded by
+\fBnamed\fR\&. When manually specified otherwise, the check levels must at least be as strict as those specified in the
+\fBnamed\fR
+configuration file\&.
+.SH "OPTIONS"
+.PP
+\-d
+.RS 4
+Enable debugging\&.
+.RE
+.PP
+\-h
+.RS 4
+Print the usage summary and exit\&.
+.RE
+.PP
+\-q
+.RS 4
+Quiet mode \- exit code only\&.
+.RE
+.PP
+\-v
+.RS 4
+Print the version of the
+\fBnamed\-checkzone\fR
+program and exit\&.
+.RE
+.PP
+\-j
+.RS 4
+When loading a zone file, read the journal if it exists\&. The journal file name is assumed to be the zone file name appended with the string
+\&.jnl\&.
+.RE
+.PP
+\-J \fIfilename\fR
+.RS 4
+When loading the zone file read the journal from the given file, if it exists\&. (Implies \-j\&.)
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specify the class of the zone\&. If not specified, "IN" is assumed\&.
+.RE
+.PP
+\-i \fImode\fR
+.RS 4
+Perform post\-load zone integrity checks\&. Possible modes are
+\fB"full"\fR
+(default),
+\fB"full\-sibling"\fR,
+\fB"local"\fR,
+\fB"local\-sibling"\fR
+and
+\fB"none"\fR\&.
+.sp
+Mode
+\fB"full"\fR
+checks that MX records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames)\&. Mode
+\fB"local"\fR
+only checks MX records which refer to in\-zone hostnames\&.
+.sp
+Mode
+\fB"full"\fR
+checks that SRV records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames)\&. Mode
+\fB"local"\fR
+only checks SRV records which refer to in\-zone hostnames\&.
+.sp
+Mode
+\fB"full"\fR
+checks that delegation NS records refer to A or AAAA record (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
+\fB"local"\fR
+only checks NS records which refer to in\-zone hostnames or that some required glue exists, that is when the nameserver is in a child zone\&.
+.sp
+Mode
+\fB"full\-sibling"\fR
+and
+\fB"local\-sibling"\fR
+disable sibling glue checks but are otherwise the same as
+\fB"full"\fR
+and
+\fB"local"\fR
+respectively\&.
+.sp
+Mode
+\fB"none"\fR
+disables the checks\&.
+.RE
+.PP
+\-f \fIformat\fR
+.RS 4
+Specify the format of the zone file\&. Possible formats are
+\fB"text"\fR
+(default),
+\fB"raw"\fR, and
+\fB"map"\fR\&.
+.RE
+.PP
+\-F \fIformat\fR
+.RS 4
+Specify the format of the output file specified\&. For
+\fBnamed\-checkzone\fR, this does not cause any effects unless it dumps the zone contents\&.
+.sp
+Possible formats are
+\fB"text"\fR
+(default), which is the standard textual representation of the zone, and
+\fB"map"\fR,
+\fB"raw"\fR, and
+\fB"raw=N"\fR, which store the zone in a binary format for rapid loading by
+\fBnamed\fR\&.
+\fB"raw=N"\fR
+specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of
+\fBnamed\fR; if N is 1, the file can be read by release 9\&.9\&.0 or higher; the default is 1\&.
+.RE
+.PP
+\-k \fImode\fR
+.RS 4
+Perform
+\fB"check\-names"\fR
+checks with the specified failure mode\&. Possible modes are
+\fB"fail"\fR
+(default for
+\fBnamed\-compilezone\fR),
+\fB"warn"\fR
+(default for
+\fBnamed\-checkzone\fR) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-l \fIttl\fR
+.RS 4
+Sets a maximum permissible TTL for the input file\&. Any record with a TTL higher than this value will cause the zone to be rejected\&. This is similar to using the
+\fBmax\-zone\-ttl\fR
+option in
+named\&.conf\&.
+.RE
+.PP
+\-L \fIserial\fR
+.RS 4
+When compiling a zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number\&. (This is expected to be used primarily for testing purposes\&.)
+.RE
+.PP
+\-m \fImode\fR
+.RS 4
+Specify whether MX records should be checked to see if they are addresses\&. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-M \fImode\fR
+.RS 4
+Check if a MX record refers to a CNAME\&. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-n \fImode\fR
+.RS 4
+Specify whether NS records should be checked to see if they are addresses\&. Possible modes are
+\fB"fail"\fR
+(default for
+\fBnamed\-compilezone\fR),
+\fB"warn"\fR
+(default for
+\fBnamed\-checkzone\fR) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-o \fIfilename\fR
+.RS 4
+Write zone output to
+filename\&. If
+filename
+is
+\-
+then write to standard out\&. This is mandatory for
+\fBnamed\-compilezone\fR\&.
+.RE
+.PP
+\-r \fImode\fR
+.RS 4
+Check for records that are treated as different by DNSSEC but are semantically equal in plain DNS\&. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-s \fIstyle\fR
+.RS 4
+Specify the style of the dumped zone file\&. Possible styles are
+\fB"full"\fR
+(default) and
+\fB"relative"\fR\&. The full format is most suitable for processing automatically by a separate script\&. On the other hand, the relative format is more human\-readable and is thus suitable for editing by hand\&. For
+\fBnamed\-checkzone\fR
+this does not cause any effects unless it dumps the zone contents\&. It also does not have any meaning if the output format is not text\&.
+.RE
+.PP
+\-S \fImode\fR
+.RS 4
+Check if a SRV record refers to a CNAME\&. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+directory
+so that include directives in the configuration file are processed as if run by a similarly chrooted
+\fBnamed\fR\&.
+.RE
+.PP
+\-T \fImode\fR
+.RS 4
+Check if Sender Policy Framework (SPF) records exist and issues a warning if an SPF\-formatted TXT record is not also present\&. Possible modes are
+\fB"warn"\fR
+(default),
+\fB"ignore"\fR\&.
+.RE
+.PP
+\-w \fIdirectory\fR
+.RS 4
+chdir to
+directory
+so that relative filenames in master file $INCLUDE directives work\&. This is similar to the directory clause in
+named\&.conf\&.
+.RE
+.PP
+\-D
+.RS 4
+Dump zone file in canonical format\&. This is always enabled for
+\fBnamed\-compilezone\fR\&.
+.RE
+.PP
+\-W \fImode\fR
+.RS 4
+Specify 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 1034)\&. Possible modes are
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR\&.
+.RE
+.PP
+zonename
+.RS 4
+The domain name of the zone being checked\&.
+.RE
+.PP
+filename
+.RS 4
+The name of the zone file\&.
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBnamed\-checkzone\fR
+returns an exit status of 1 if errors were detected and 0 otherwise\&.
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBnamed-checkconf\fR(8),
+RFC 1035,
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2002, 2004-2007, 2009-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c
new file mode 100644
index 0000000..0f491fa
--- /dev/null
+++ b/bin/check/named-checkzone.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/socket.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/result.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include "check-tool.h"
+
+static int quiet = 0;
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+dns_zone_t *zone = NULL;
+dns_zonetype_t zonetype = dns_zone_master;
+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, dns_result_totext(result)); \
+ return (result); \
+ } \
+ } while (0)
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "usage: %s [-djqvD] [-c class] "
+ "[-f inputformat] [-F outputformat] [-J filename] "
+ "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
+ "[-n (ignore|warn|fail)] [-m (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);
+ dns_name_destroy();
+}
+
+/*% main processing routine */
+int
+main(int argc, char **argv) {
+ int c;
+ char *origin = NULL;
+ 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
+ INSIST(0);
+
+ /* 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_options2 |= DNS_ZONEOPT2_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(VERSION "\n");
+ 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 if (strcasecmp(inputformatstr, "map") == 0) {
+ inputformat = dns_masterformat_map;
+ } 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 if (strcasecmp(outputformatstr, "map") == 0) {
+ outputformat = dns_masterformat_map;
+ } 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 outputing 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 (isc_commandline_index + 2 != argc)
+ usage();
+
+#ifdef _WIN32
+ InitSockets();
+#endif
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ if (!quiet)
+ RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
+ == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
+ == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ origin = argv[isc_commandline_index++];
+ filename = argv[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_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+#ifdef _WIN32
+ DestroySockets();
+#endif
+ return ((result == ISC_R_SUCCESS) ? 0 : 1);
+}
diff --git a/bin/check/named-checkzone.docbook b/bin/check/named-checkzone.docbook
new file mode 100644
index 0000000..6f4d9b5
--- /dev/null
+++ b/bin/check/named-checkzone.docbook
@@ -0,0 +1,528 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named-checkzone">
+ <info>
+ <date>2014-02-19</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named-checkzone</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname><application>named-checkzone</application></refname>
+ <refname><application>named-compilezone</application></refname>
+ <refpurpose>zone file validity checking or converting tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>named-checkzone</command>
+ <arg choice="opt" rep="norepeat"><option>-d</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-j</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-F <replaceable class="parameter">format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-J <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-M <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">serial</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-o <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">style</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-w <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-W <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">zonename</arg>
+ <arg choice="req" rep="norepeat">filename</arg>
+ </cmdsynopsis>
+ <cmdsynopsis sepchar=" ">
+ <command>named-compilezone</command>
+ <arg choice="opt" rep="norepeat"><option>-d</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-j</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-C <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-F <replaceable class="parameter">format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-J <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">serial</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">style</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-w <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-W <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="req" rep="norepeat"><option>-o <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">zonename</arg>
+ <arg choice="req" rep="norepeat">filename</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>named-checkzone</command>
+ checks the syntax and integrity of a zone file. It performs the
+ same checks as <command>named</command> does when loading a
+ zone. This makes <command>named-checkzone</command> useful for
+ checking zone files before configuring them into a name server.
+ </para>
+ <para>
+ <command>named-compilezone</command> is similar to
+ <command>named-checkzone</command>, but it always dumps the
+ zone contents to a specified file in a specified format.
+ Additionally, it applies stricter check levels by default,
+ since the dump output will be used as an actual zone file
+ loaded by <command>named</command>.
+ When manually specified otherwise, the check levels must at
+ least be as strict as those specified in the
+ <command>named</command> configuration file.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-d</term>
+ <listitem>
+ <para>
+ Enable debugging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Print the usage summary and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ Quiet mode - exit code only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the version of the <command>named-checkzone</command>
+ program and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j</term>
+ <listitem>
+ <para>
+ When loading a zone file, read the journal if it exists.
+ The journal file name is assumed to be the zone file name
+ appended with the string <filename>.jnl</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-J <replaceable class="parameter">filename</replaceable></term>
+ <listitem>
+ <para>
+ When loading the zone file read the journal from the given
+ file, if it exists. (Implies -j.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specify the class of the zone. If not specified, "IN" is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Perform post-load zone integrity checks. Possible modes are
+ <command>"full"</command> (default),
+ <command>"full-sibling"</command>,
+ <command>"local"</command>,
+ <command>"local-sibling"</command> and
+ <command>"none"</command>.
+ </para>
+ <para>
+ Mode <command>"full"</command> checks that MX records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <command>"local"</command> only
+ checks MX records which refer to in-zone hostnames.
+ </para>
+ <para>
+ Mode <command>"full"</command> checks that SRV records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <command>"local"</command> only
+ checks SRV records which refer to in-zone hostnames.
+ </para>
+ <para>
+ Mode <command>"full"</command> checks that delegation NS
+ records refer to A or AAAA record (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 <command>"local"</command> only checks NS records which
+ refer to in-zone hostnames or that some required glue exists,
+ that is when the nameserver is in a child zone.
+ </para>
+ <para>
+ Mode <command>"full-sibling"</command> and
+ <command>"local-sibling"</command> disable sibling glue
+ checks but are otherwise the same as <command>"full"</command>
+ and <command>"local"</command> respectively.
+ </para>
+ <para>
+ Mode <command>"none"</command> disables the checks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">format</replaceable></term>
+ <listitem>
+ <para>
+ Specify the format of the zone file.
+ Possible formats are <command>"text"</command> (default),
+ <command>"raw"</command>, and <command>"map"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-F <replaceable class="parameter">format</replaceable></term>
+ <listitem>
+ <para>
+ Specify the format of the output file specified.
+ For <command>named-checkzone</command>,
+ this does not cause any effects unless it dumps the zone
+ contents.
+ </para>
+ <para>
+ Possible formats are <command>"text"</command> (default),
+ which is the standard textual representation of the zone,
+ and <command>"map"</command>, <command>"raw"</command>,
+ and <command>"raw=N"</command>, which store the zone in a
+ binary format for rapid loading by <command>named</command>.
+ <command>"raw=N"</command> specifies the format version of
+ the raw zone file: if N is 0, the raw file can be read by
+ any version of <command>named</command>; if N is 1, the file
+ can be read by release 9.9.0 or higher; the default is 1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Perform <command>"check-names"</command> checks with the
+ specified failure mode.
+ Possible modes are <command>"fail"</command>
+ (default for <command>named-compilezone</command>),
+ <command>"warn"</command>
+ (default for <command>named-checkzone</command>) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Sets a maximum permissible TTL for the input file.
+ Any record with a TTL higher than this value will cause
+ the zone to be rejected. This is similar to using the
+ <command>max-zone-ttl</command> option in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">serial</replaceable></term>
+ <listitem>
+ <para>
+ When compiling a zone to "raw" or "map" format, set the
+ "source serial" value in the header to the specified serial
+ number. (This is expected to be used primarily for testing
+ purposes.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Specify whether MX records should be checked to see if they
+ are addresses. Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-M <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Check if a MX record refers to a CNAME.
+ Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Specify whether NS records should be checked to see if they
+ are addresses.
+ Possible modes are <command>"fail"</command>
+ (default for <command>named-compilezone</command>),
+ <command>"warn"</command>
+ (default for <command>named-checkzone</command>) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-o <replaceable class="parameter">filename</replaceable></term>
+ <listitem>
+ <para>
+ Write zone output to <filename>filename</filename>.
+ If <filename>filename</filename> is <filename>-</filename> then
+ write to standard out.
+ This is mandatory for <command>named-compilezone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Check for records that are treated as different by DNSSEC but
+ are semantically equal in plain DNS.
+ Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">style</replaceable></term>
+ <listitem>
+ <para>
+ Specify the style of the dumped zone file.
+ Possible styles are <command>"full"</command> (default)
+ and <command>"relative"</command>.
+ The full format is most suitable for processing
+ automatically by a separate script.
+ On the other hand, the relative format is more
+ human-readable and is thus suitable for editing by hand.
+ For <command>named-checkzone</command>
+ this does not cause any effects unless it dumps the zone
+ contents.
+ It also does not have any meaning if the output format
+ is not text.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Check if a SRV record refers to a CNAME.
+ Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Chroot to <filename>directory</filename> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted <command>named</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Check if Sender Policy Framework (SPF) records exist
+ and issues a warning if an SPF-formatted TXT record is
+ not also present. Possible modes are <command>"warn"</command>
+ (default), <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-w <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ chdir to <filename>directory</filename> so that
+ relative
+ filenames in master file $INCLUDE directives work. This
+ is similar to the directory clause in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D</term>
+ <listitem>
+ <para>
+ Dump zone file in canonical format.
+ This is always enabled for <command>named-compilezone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-W <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Specify 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 1034).
+ Possible modes are <command>"warn"</command> (default)
+ and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zonename</term>
+ <listitem>
+ <para>
+ The domain name of the zone being checked.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>filename</term>
+ <listitem>
+ <para>
+ The name of the zone file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>RETURN VALUES</title></info>
+
+ <para><command>named-checkzone</command>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkconf</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC 1035</citetitle>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/check/named-checkzone.html b/bin/check/named-checkzone.html
new file mode 100644
index 0000000..414b3ab
--- /dev/null
+++ b/bin/check/named-checkzone.html
@@ -0,0 +1,429 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2002, 2004-2007, 2009-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-checkzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named-checkzone"></a><div class="titlepage"></div>
+
+
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">named-checkzone</span>,
+ <span class="application">named-compilezone</span>
+ &#8212; zone file validity checking or converting tool
+ </p>
+</div>
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named-checkzone</code>
+ [<code class="option">-d</code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-j</code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>format</code></em></code>]
+ [<code class="option">-F <em class="replaceable"><code>format</code></em></code>]
+ [<code class="option">-J <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-M <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-l <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>serial</code></em></code>]
+ [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>style</code></em></code>]
+ [<code class="option">-S <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-T <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-D</code>]
+ [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>]
+ {zonename}
+ {filename}
+ </p></div>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named-compilezone</code>
+ [<code class="option">-d</code>]
+ [<code class="option">-j</code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-C <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>format</code></em></code>]
+ [<code class="option">-F <em class="replaceable"><code>format</code></em></code>]
+ [<code class="option">-J <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-l <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>serial</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>style</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-T <em class="replaceable"><code>mode</code></em></code>]
+ [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-D</code>]
+ [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>]
+ {<code class="option">-o <em class="replaceable"><code>filename</code></em></code>}
+ {zonename}
+ {filename}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>named-checkzone</strong></span>
+ checks the syntax and integrity of a zone file. It performs the
+ same checks as <span class="command"><strong>named</strong></span> does when loading a
+ zone. This makes <span class="command"><strong>named-checkzone</strong></span> useful for
+ checking zone files before configuring them into a name server.
+ </p>
+ <p>
+ <span class="command"><strong>named-compilezone</strong></span> is similar to
+ <span class="command"><strong>named-checkzone</strong></span>, but it always dumps the
+ zone contents to a specified file in a specified format.
+ Additionally, it applies stricter check levels by default,
+ since the dump output will be used as an actual zone file
+ loaded by <span class="command"><strong>named</strong></span>.
+ When manually specified otherwise, the check levels must at
+ least be as strict as those specified in the
+ <span class="command"><strong>named</strong></span> configuration file.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-d</span></dt>
+<dd>
+ <p>
+ Enable debugging.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Print the usage summary and exit.
+ </p>
+ </dd>
+<dt><span class="term">-q</span></dt>
+<dd>
+ <p>
+ Quiet mode - exit code only.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Print the version of the <span class="command"><strong>named-checkzone</strong></span>
+ program and exit.
+ </p>
+ </dd>
+<dt><span class="term">-j</span></dt>
+<dd>
+ <p>
+ When loading a zone file, read the journal if it exists.
+ The journal file name is assumed to be the zone file name
+ appended with the string <code class="filename">.jnl</code>.
+ </p>
+ </dd>
+<dt><span class="term">-J <em class="replaceable"><code>filename</code></em></span></dt>
+<dd>
+ <p>
+ When loading the zone file read the journal from the given
+ file, if it exists. (Implies -j.)
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Specify the class of the zone. If not specified, "IN" is assumed.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Perform post-load zone integrity checks. Possible modes are
+ <span class="command"><strong>"full"</strong></span> (default),
+ <span class="command"><strong>"full-sibling"</strong></span>,
+ <span class="command"><strong>"local"</strong></span>,
+ <span class="command"><strong>"local-sibling"</strong></span> and
+ <span class="command"><strong>"none"</strong></span>.
+ </p>
+ <p>
+ Mode <span class="command"><strong>"full"</strong></span> checks that MX records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <span class="command"><strong>"local"</strong></span> only
+ checks MX records which refer to in-zone hostnames.
+ </p>
+ <p>
+ Mode <span class="command"><strong>"full"</strong></span> checks that SRV records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <span class="command"><strong>"local"</strong></span> only
+ checks SRV records which refer to in-zone hostnames.
+ </p>
+ <p>
+ Mode <span class="command"><strong>"full"</strong></span> checks that delegation NS
+ records refer to A or AAAA record (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 <span class="command"><strong>"local"</strong></span> only checks NS records which
+ refer to in-zone hostnames or that some required glue exists,
+ that is when the nameserver is in a child zone.
+ </p>
+ <p>
+ Mode <span class="command"><strong>"full-sibling"</strong></span> and
+ <span class="command"><strong>"local-sibling"</strong></span> disable sibling glue
+ checks but are otherwise the same as <span class="command"><strong>"full"</strong></span>
+ and <span class="command"><strong>"local"</strong></span> respectively.
+ </p>
+ <p>
+ Mode <span class="command"><strong>"none"</strong></span> disables the checks.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>format</code></em></span></dt>
+<dd>
+ <p>
+ Specify the format of the zone file.
+ Possible formats are <span class="command"><strong>"text"</strong></span> (default),
+ <span class="command"><strong>"raw"</strong></span>, and <span class="command"><strong>"map"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-F <em class="replaceable"><code>format</code></em></span></dt>
+<dd>
+ <p>
+ Specify the format of the output file specified.
+ For <span class="command"><strong>named-checkzone</strong></span>,
+ this does not cause any effects unless it dumps the zone
+ contents.
+ </p>
+ <p>
+ Possible formats are <span class="command"><strong>"text"</strong></span> (default),
+ which is the standard textual representation of the zone,
+ and <span class="command"><strong>"map"</strong></span>, <span class="command"><strong>"raw"</strong></span>,
+ and <span class="command"><strong>"raw=N"</strong></span>, which store the zone in a
+ binary format for rapid loading by <span class="command"><strong>named</strong></span>.
+ <span class="command"><strong>"raw=N"</strong></span> specifies the format version of
+ the raw zone file: if N is 0, the raw file can be read by
+ any version of <span class="command"><strong>named</strong></span>; if N is 1, the file
+ can be read by release 9.9.0 or higher; the default is 1.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Perform <span class="command"><strong>"check-names"</strong></span> checks with the
+ specified failure mode.
+ Possible modes are <span class="command"><strong>"fail"</strong></span>
+ (default for <span class="command"><strong>named-compilezone</strong></span>),
+ <span class="command"><strong>"warn"</strong></span>
+ (default for <span class="command"><strong>named-checkzone</strong></span>) and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>ttl</code></em></span></dt>
+<dd>
+ <p>
+ Sets a maximum permissible TTL for the input file.
+ Any record with a TTL higher than this value will cause
+ the zone to be rejected. This is similar to using the
+ <span class="command"><strong>max-zone-ttl</strong></span> option in
+ <code class="filename">named.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>serial</code></em></span></dt>
+<dd>
+ <p>
+ When compiling a zone to "raw" or "map" format, set the
+ "source serial" value in the header to the specified serial
+ number. (This is expected to be used primarily for testing
+ purposes.)
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Specify whether MX records should be checked to see if they
+ are addresses. Possible modes are <span class="command"><strong>"fail"</strong></span>,
+ <span class="command"><strong>"warn"</strong></span> (default) and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-M <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Check if a MX record refers to a CNAME.
+ Possible modes are <span class="command"><strong>"fail"</strong></span>,
+ <span class="command"><strong>"warn"</strong></span> (default) and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-n <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Specify whether NS records should be checked to see if they
+ are addresses.
+ Possible modes are <span class="command"><strong>"fail"</strong></span>
+ (default for <span class="command"><strong>named-compilezone</strong></span>),
+ <span class="command"><strong>"warn"</strong></span>
+ (default for <span class="command"><strong>named-checkzone</strong></span>) and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-o <em class="replaceable"><code>filename</code></em></span></dt>
+<dd>
+ <p>
+ Write zone output to <code class="filename">filename</code>.
+ If <code class="filename">filename</code> is <code class="filename">-</code> then
+ write to standard out.
+ This is mandatory for <span class="command"><strong>named-compilezone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Check for records that are treated as different by DNSSEC but
+ are semantically equal in plain DNS.
+ Possible modes are <span class="command"><strong>"fail"</strong></span>,
+ <span class="command"><strong>"warn"</strong></span> (default) and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>style</code></em></span></dt>
+<dd>
+ <p>
+ Specify the style of the dumped zone file.
+ Possible styles are <span class="command"><strong>"full"</strong></span> (default)
+ and <span class="command"><strong>"relative"</strong></span>.
+ The full format is most suitable for processing
+ automatically by a separate script.
+ On the other hand, the relative format is more
+ human-readable and is thus suitable for editing by hand.
+ For <span class="command"><strong>named-checkzone</strong></span>
+ this does not cause any effects unless it dumps the zone
+ contents.
+ It also does not have any meaning if the output format
+ is not text.
+ </p>
+ </dd>
+<dt><span class="term">-S <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Check if a SRV record refers to a CNAME.
+ Possible modes are <span class="command"><strong>"fail"</strong></span>,
+ <span class="command"><strong>"warn"</strong></span> (default) and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Chroot to <code class="filename">directory</code> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted <span class="command"><strong>named</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-T <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Check if Sender Policy Framework (SPF) records exist
+ and issues a warning if an SPF-formatted TXT record is
+ not also present. Possible modes are <span class="command"><strong>"warn"</strong></span>
+ (default), <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-w <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ chdir to <code class="filename">directory</code> so that
+ relative
+ filenames in master file $INCLUDE directives work. This
+ is similar to the directory clause in
+ <code class="filename">named.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-D</span></dt>
+<dd>
+ <p>
+ Dump zone file in canonical format.
+ This is always enabled for <span class="command"><strong>named-compilezone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-W <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+ <p>
+ Specify 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 1034).
+ Possible modes are <span class="command"><strong>"warn"</strong></span> (default)
+ and
+ <span class="command"><strong>"ignore"</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">zonename</span></dt>
+<dd>
+ <p>
+ The domain name of the zone being checked.
+ </p>
+ </dd>
+<dt><span class="term">filename</span></dt>
+<dd>
+ <p>
+ The name of the zone file.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>RETURN VALUES</h2>
+
+ <p><span class="command"><strong>named-checkzone</strong></span>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named-checkconf</span>(8)
+ </span>,
+ <em class="citetitle">RFC 1035</em>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/check/win32/checkconf.dsp.in b/bin/check/win32/checkconf.dsp.in
new file mode 100644
index 0000000..6f8dafc
--- /dev/null
+++ b/bin/check/win32/checkconf.dsp.in
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="checkconf" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=checkconf - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "checkconf.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "checkconf.mak" CFG="checkconf - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "checkconf - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "checkconf - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/checktool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named-checkconf.exe"
+
+!ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/checktool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/named-checkconf.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "checkconf - @PLATFORM@ Release"
+# Name "checkconf - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\named-checkconf.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\check-tool.h"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/check/win32/checkconf.dsw b/bin/check/win32/checkconf.dsw
new file mode 100644
index 0000000..bb5bba7
--- /dev/null
+++ b/bin/check/win32/checkconf.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "checkconf"=".\checkconf.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/check/win32/checkconf.mak.in b/bin/check/win32/checkconf.mak.in
new file mode 100644
index 0000000..cb27892
--- /dev/null
+++ b/bin/check/win32/checkconf.mak.in
@@ -0,0 +1,404 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on checkconf.dsp
+!IF "$(CFG)" == ""
+CFG=checkconf - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to checkconf - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "checkconf - @PLATFORM@ Release" && "$(CFG)" != "checkconf - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "checkconf.mak" CFG="checkconf - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "checkconf - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "checkconf - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc"
+
+!ELSE
+
+ALL : "libdns - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "..\..\..\Build\Release\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" "libdns - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\check-tool.sbr"
+ -@erase "$(INTDIR)\named-checkconf.obj"
+ -@erase "$(INTDIR)\named-checkconf.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(OUTDIR)\checkconf.bsc"
+ -@erase "..\..\..\Build\Release\named-checkconf.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\checkconf.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkconf.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check-tool.sbr" \
+ "$(INTDIR)\named-checkconf.sbr"
+
+"$(OUTDIR)\checkconf.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-checkconf.pdb" @MACHINE@ /out:"../../../Build/Release/named-checkconf.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkconf.obj" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib"
+
+"..\..\..\Build\Release\named-checkconf.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc"
+
+!ELSE
+
+ALL : "libdns - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "..\..\..\Build\Debug\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" "libdns - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\check-tool.sbr"
+ -@erase "$(INTDIR)\named-checkconf.obj"
+ -@erase "$(INTDIR)\named-checkconf.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\named-checkconf.pdb"
+ -@erase "$(OUTDIR)\checkconf.bsc"
+ -@erase "..\..\..\Build\Debug\named-checkconf.exe"
+ -@erase "..\..\..\Build\Debug\named-checkconf.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkconf.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check-tool.sbr" \
+ "$(INTDIR)\named-checkconf.sbr"
+
+"$(OUTDIR)\checkconf.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-checkconf.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/named-checkconf.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkconf.obj" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib"
+
+"..\..\..\Build\Debug\named-checkconf.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("checkconf.dep")
+!INCLUDE "checkconf.dep"
+!ELSE
+!MESSAGE Warning: cannot find "checkconf.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release" || "$(CFG)" == "checkconf - @PLATFORM@ Debug"
+SOURCE="..\check-tool.c"
+
+"$(INTDIR)\check-tool.obj" "$(INTDIR)\check-tool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE="..\named-checkconf.c"
+
+"$(INTDIR)\named-checkconf.obj" "$(INTDIR)\named-checkconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release"
+
+"libisccfg - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release"
+ cd "..\..\..\bin\check\win32"
+
+"libisccfg - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug"
+
+"libisccfg - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libisccfg - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "checkconf - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/check/win32/checkconf.vcxproj.filters.in b/bin/check/win32/checkconf.vcxproj.filters.in
new file mode 100644
index 0000000..7d0bc52
--- /dev/null
+++ b/bin/check/win32/checkconf.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\check-tool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-checkconf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/check/win32/checkconf.vcxproj.in b/bin/check/win32/checkconf.vcxproj.in
new file mode 100644
index 0000000..284e457
--- /dev/null
+++ b/bin/check/win32/checkconf.vcxproj.in
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{03A96113-CB14-43AA-AEB2-48950E3915C5}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>checkconf</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\check-tool.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-checkconf.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/check/win32/checkconf.vcxproj.user b/bin/check/win32/checkconf.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/check/win32/checkconf.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/check/win32/checktool.dsp.in b/bin/check/win32/checktool.dsp.in
new file mode 100644
index 0000000..2ecaabe
--- /dev/null
+++ b/bin/check/win32/checktool.dsp.in
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="checktool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104
+
+CFG=checktool - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "checktool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "checktool.mak" CFG="checktool - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "checktool - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE "checktool - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "checktool - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fdchecktool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/checktool.lib"
+
+!ELSEIF "$(CFG)" == "checktool - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fdchecktool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/checktool.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "checktool - @PLATFORM@ Release"
+# Name "checktool - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\check-tool.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/check/win32/checktool.dsw b/bin/check/win32/checktool.dsw
new file mode 100644
index 0000000..bb139e7
--- /dev/null
+++ b/bin/check/win32/checktool.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "checktool"=".\checktool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/check/win32/checktool.vcxproj.filters.in b/bin/check/win32/checktool.vcxproj.filters.in
new file mode 100644
index 0000000..34fc8c6
--- /dev/null
+++ b/bin/check/win32/checktool.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\check-tool.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/check/win32/checktool.vcxproj.in b/bin/check/win32/checktool.vcxproj.in
new file mode 100644
index 0000000..aa735c5
--- /dev/null
+++ b/bin/check/win32/checktool.vcxproj.in
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\check-tool.c" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2C1F7096-C5B5-48D4-846F-A7ACA454335D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>checktool</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <OutDir>.\$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <OutDir>.\$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Lib>
+ <OutputFile>.\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Lib>
+ <OutputFile>.\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/check/win32/checktool.vcxproj.user b/bin/check/win32/checktool.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/check/win32/checktool.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/check/win32/checkzone.dsp.in b/bin/check/win32/checkzone.dsp.in
new file mode 100644
index 0000000..8a7b176
--- /dev/null
+++ b/bin/check/win32/checkzone.dsp.in
@@ -0,0 +1,108 @@
+# Microsoft Developer Studio Project File - Name="checkzone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=checkzone - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "checkzone.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "checkzone.mak" CFG="checkzone - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "checkzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "checkzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" @COPTY@ /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/checktool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named-checkzone.exe"
+
+!ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/checktool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/named-checkzone.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "checkzone - @PLATFORM@ Release"
+# Name "checkzone - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\named-checkzone.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\check-tool.h"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/check/win32/checkzone.dsw b/bin/check/win32/checkzone.dsw
new file mode 100644
index 0000000..533f206
--- /dev/null
+++ b/bin/check/win32/checkzone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "checkzone"=".\checkzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/check/win32/checkzone.mak.in b/bin/check/win32/checkzone.mak.in
new file mode 100644
index 0000000..31c9378
--- /dev/null
+++ b/bin/check/win32/checkzone.mak.in
@@ -0,0 +1,404 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on checkzone.dsp
+!IF "$(CFG)" == ""
+CFG=checkzone - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to checkzone - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "checkzone - @PLATFORM@ Release" && "$(CFG)" != "checkzone - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "checkzone.mak" CFG="checkzone - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "checkzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "checkzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\named-checkzone.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\named-checkzone.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\named-checkzone.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\named-checkzone.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /Fp"$(INTDIR)\checkzone.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkzone.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-checkzone.pdb" @MACHINE@ /out:"../../../Build/Release/named-checkzone.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkzone.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib"
+
+"..\..\..\Build\Release\named-checkzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\named-checkzone.exe" "$(OUTDIR)\checkzone.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\named-checkzone.exe" "$(OUTDIR)\checkzone.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\check-tool.sbr"
+ -@erase "$(INTDIR)\named-checkzone.obj"
+ -@erase "$(INTDIR)\named-checkzone.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\named-checkzone.pdb"
+ -@erase "$(OUTDIR)\checkzone.bsc"
+ -@erase "..\..\..\Build\Debug\named-checkzone.exe"
+ -@erase "..\..\..\Build\Debug\named-checkzone.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkzone.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check-tool.sbr" \
+ "$(INTDIR)\named-checkzone.sbr"
+
+"$(OUTDIR)\checkzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-checkzone.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/named-checkzone.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkzone.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib"
+
+"..\..\..\Build\Debug\named-checkzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("checkzone.dep")
+!INCLUDE "checkzone.dep"
+!ELSE
+!MESSAGE Warning: cannot find "checkzone.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release" || "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+SOURCE="..\check-tool.c"
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+
+
+"$(INTDIR)\check-tool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\check-tool.obj" "$(INTDIR)\check-tool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE="..\named-checkzone.c"
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+
+
+"$(INTDIR)\named-checkzone.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\named-checkzone.obj" "$(INTDIR)\named-checkzone.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "checkzone - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/check/win32/checkzone.vcxproj.filters.in b/bin/check/win32/checkzone.vcxproj.filters.in
new file mode 100644
index 0000000..4f3396c
--- /dev/null
+++ b/bin/check/win32/checkzone.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\check-tool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-checkzone.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/check/win32/checkzone.vcxproj.in b/bin/check/win32/checkzone.vcxproj.in
new file mode 100644
index 0000000..92704f8
--- /dev/null
+++ b/bin/check/win32/checkzone.vcxproj.in
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{66028555-7DD5-4016-B601-9EF9A1EE8BFA}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>checkzone</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>cd ..\..\..\Build\$(Configuration)
+copy /Y named-checkzone.exe named-compilezone.exe
+copy /Y named-checkzone.ilk named-compilezone.ilk
+</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ </Link>
+ <PostBuildEvent>
+ <Command>cd ..\..\..\Build\$(Configuration)
+copy /Y named-checkzone.exe named-compilezone.exe
+</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\check-tool.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-checkzone.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/check/win32/checkzone.vcxproj.user b/bin/check/win32/checkzone.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/check/win32/checkzone.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/confgen/Makefile.in b/bin/confgen/Makefile.in
new file mode 100644
index 0000000..87f13dd
--- /dev/null
+++ b/bin/confgen/Makefile.in
@@ -0,0 +1,115 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.8 2009/12/05 23:31:40 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+# Attempt to disable parallel processing.
+.NOTPARALLEL:
+.NO_PARALLEL:
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+RNDCLIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@
+RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@
+
+CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+SRCS= rndc-confgen.c ddns-confgen.c
+
+SUBDIRS = unix
+
+TARGETS = rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@
+
+MANPAGES = rndc-confgen.8 ddns-confgen.8
+
+HTMLPAGES = rndc-confgen.html ddns-confgen.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+UOBJS = unix/os.@O@
+
+@BIND9_MAKE_RULES@
+
+rndc-confgen.@O@: rndc-confgen.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \
+ -c ${srcdir}/rndc-confgen.c
+
+ddns-confgen.@O@: ddns-confgen.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${srcdir}/ddns-confgen.c
+
+rndc-confgen@EXEEXT@: rndc-confgen.@O@ util.@O@ keygen.@O@ ${CONFDEPLIBS}
+ export BASEOBJS="rndc-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \
+ ${FINALBUILDCMD}
+
+ddns-confgen@EXEEXT@: ddns-confgen.@O@ util.@O@ keygen.@O@ ${CONFDEPLIBS}
+ export BASEOBJS="ddns-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \
+ ${FINALBUILDCMD}
+
+# make a link in the build directory to assist with testing
+tsig-keygen@EXEEXT@: ddns-confgen@EXEEXT@
+ rm -f tsig-keygen@EXEEXT@
+ ${LINK_PROGRAM} ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} ddns-confgen@EXEEXT@ ${DESTDIR}${sbindir}
+ ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/ddns-confgen.8 ${DESTDIR}${mandir}/man8
+ (cd ${DESTDIR}${sbindir}; rm -f tsig-keygen@EXEEXT@; ${LINK_PROGRAM} ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@)
+ (cd ${DESTDIR}${mandir}/man8; rm -f tsig-keygen.8; ${LINK_PROGRAM} ddns-confgen.8 tsig-keygen.8)
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man8/tsig-keygen.8
+ rm -f ${DESTDIR}${sbindir}/tsig-keygen@EXEEXT@
+ rm -f ${DESTDIR}${mandir}/man8/ddns-confgen.8
+ rm -f ${DESTDIR}${mandir}/man8/rndc-confgen.8
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/ddns-confgen@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/rndc-confgen@EXEEXT@
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
diff --git a/bin/confgen/ddns-confgen.8 b/bin/confgen/ddns-confgen.8
new file mode 100644
index 0000000..8746497
--- /dev/null
+++ b/bin/confgen/ddns-confgen.8
@@ -0,0 +1,159 @@
+.\" Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: ddns-confgen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-03-06
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DDNS\-CONFGEN" "8" "2014\-03\-06" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+ddns-confgen \- ddns key generation tool
+.SH "SYNOPSIS"
+.HP \w'\fBtsig\-keygen\fR\ 'u
+\fBtsig\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-h\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [name]
+.HP \w'\fBddns\-confgen\fR\ 'u
+\fBddns\-confgen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-q\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\-s\ \fIname\fR | \-z\ \fIzone\fR]
+.SH "DESCRIPTION"
+.PP
+\fBtsig\-keygen\fR
+and
+\fBddns\-confgen\fR
+are invocation methods for a 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
+\fBrndc\fR
+command channel\&.
+.PP
+When run as
+\fBtsig\-keygen\fR, a domain name can be specified on the command line which will be used as the name of the generated key\&. If no name is specified, the default is
+\fBtsig\-key\fR\&.
+.PP
+When run as
+\fBddns\-confgen\fR, the generated key is accompanied by configuration text and instructions that can be used with
+\fBnsupdate\fR
+and
+\fBnamed\fR
+when setting up dynamic DNS, including an example
+\fBupdate\-policy\fR
+statement\&. (This usage similar to the
+\fBrndc\-confgen\fR
+command for setting up command channel security\&.)
+.PP
+Note that
+\fBnamed\fR
+itself can configure a local DDNS key for use with
+\fBnsupdate \-l\fR: it does this when a zone is configured with
+\fBupdate\-policy local;\fR\&.
+\fBddns\-confgen\fR
+is only needed when a more elaborate configuration is required: for instance, if
+\fBnsupdate\fR
+is to be used from a remote system\&.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+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\&.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of options and arguments\&.
+.RE
+.PP
+\-k \fIkeyname\fR
+.RS 4
+Specifies the key name of the DDNS authentication key\&. The default is
+\fBddns\-key\fR
+when neither the
+\fB\-s\fR
+nor
+\fB\-z\fR
+option is specified; otherwise, the default is
+\fBddns\-key\fR
+as a separate label followed by the argument of the option, e\&.g\&.,
+\fBddns\-key\&.example\&.com\&.\fR
+The key name must have the format of a valid domain name, consisting of letters, digits, hyphens and periods\&.
+.RE
+.PP
+\-q
+.RS 4
+(\fBddns\-confgen\fR
+only\&.) Quiet mode: Print only the key, with no explanatory text or usage examples; This is essentially identical to
+\fBtsig\-keygen\fR\&.
+.RE
+.PP
+\-r \fIrandomfile\fR
+.RS 4
+Specifies a source of random data for generating the authorization\&. If the operating system does not provide a
+/dev/random
+or equivalent device, the default source of randomness is keyboard input\&.
+randomdev
+specifies the name of a character device or file containing random data to be used instead of the default\&. The special value
+keyboard
+indicates that keyboard input should be used\&.
+.RE
+.PP
+\-s \fIname\fR
+.RS 4
+(\fBddns\-confgen\fR
+only\&.) Generate configuration example to allow dynamic updates of a single hostname\&. The example
+\fBnamed\&.conf\fR
+text shows how to set an update policy for the specified
+\fIname\fR
+using the "name" nametype\&. The default key name is ddns\-key\&.\fIname\fR\&. 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
+\fB\-z\fR
+option\&.
+.RE
+.PP
+\-z \fIzone\fR
+.RS 4
+(\fBddns\-confgen\fR
+only\&.) Generate configuration example to allow dynamic updates of a zone: The example
+\fBnamed\&.conf\fR
+text shows how to set an update policy for the specified
+\fIzone\fR
+using the "zonesub" nametype, allowing updates to all subdomain names within that
+\fIzone\fR\&. This option cannot be used with the
+\fB\-s\fR
+option\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBnsupdate\fR(1),
+\fBnamed.conf\fR(5),
+\fBnamed\fR(8),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/confgen/ddns-confgen.c b/bin/confgen/ddns-confgen.c
new file mode 100644
index 0000000..5220ed6
--- /dev/null
+++ b/bin/confgen/ddns-confgen.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/**
+ * ddns-confgen generates configuration files for dynamic DNS. It can
+ * be used as a convenient alternative to writing the ddns.key file
+ * and the corresponding key and update-policy statements in named.conf.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/assertions.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/keyboard.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>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+#include <confgen/os.h>
+
+#include "util.h"
+#include "keygen.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 */
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(int status) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(int status) {
+ if (progmode == progmode_confgen) {
+ fprintf(stderr, "\
+Usage:\n\
+ %s [-a alg] [-k keyname] [-r randomfile] [-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\
+ -r randomfile: source of random data (use \"keyboard\" for key timing)\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] [-r randomfile] [keyname]\n\
+ -a alg: algorithm (default hmac-sha256)\n\
+ -r randomfile: source of random data (use \"keyboard\" for key timing)\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 *randomfile = 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;
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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
+ INSIST(0);
+
+ 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':
+ randomfile = isc_commandline_argument;
+ 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 = alg_totext(alg);
+
+ DO("create memory context", isc_mem_create(0, 0, &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);
+ if (keybuf == NULL)
+ fatal("failed to allocate memory for keyname");
+ snprintf(keybuf, len, "%s.%s", keyname, suffix);
+ keyname = (const char *) keybuf;
+ }
+ }
+
+ isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
+
+ generate_key(mctx, randomfile, 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/ddns-confgen.docbook b/bin/confgen/ddns-confgen.docbook
new file mode 100644
index 0000000..47b7b21
--- /dev/null
+++ b/bin/confgen/ddns-confgen.docbook
@@ -0,0 +1,230 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.ddns-confgen">
+ <info>
+ <date>2014-03-06</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>ddns-confgen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>ddns-confgen</application></refname>
+ <refpurpose>ddns key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>tsig-keygen</command>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">randomfile</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat">name</arg>
+ </cmdsynopsis>
+ <cmdsynopsis sepchar=" ">
+ <command>ddns-confgen</command>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">keyname</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">randomfile</replaceable></option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="plain" rep="norepeat">-s <replaceable class="parameter">name</replaceable></arg>
+ <arg choice="plain" rep="norepeat">-z <replaceable class="parameter">zone</replaceable></arg>
+ </group>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>tsig-keygen</command> and <command>ddns-confgen</command>
+ are invocation methods for a 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
+ <command>rndc</command> command channel.
+ </para>
+
+ <para>
+ When run as <command>tsig-keygen</command>, a domain name
+ can be specified on the command line which will be used as
+ the name of the generated key. If no name is specified,
+ the default is <constant>tsig-key</constant>.
+ </para>
+
+ <para>
+ When run as <command>ddns-confgen</command>, the generated
+ key is accompanied by configuration text and instructions
+ that can be used with <command>nsupdate</command> and
+ <command>named</command> when setting up dynamic DNS,
+ including an example <command>update-policy</command>
+ statement. (This usage similar to the
+ <command>rndc-confgen</command> command for setting
+ up command channel security.)
+ </para>
+
+ <para>
+ Note that <command>named</command> itself can configure a
+ local DDNS key for use with <command>nsupdate -l</command>:
+ it does this when a zone is configured with
+ <command>update-policy local;</command>.
+ <command>ddns-confgen</command> is only needed when a
+ more elaborate configuration is required: for instance,
+ if <command>nsupdate</command> is to be used from a remote
+ system.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of options and arguments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">keyname</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the key name of the DDNS authentication key.
+ The default is <constant>ddns-key</constant> when neither
+ the <option>-s</option> nor <option>-z</option> option is
+ specified; otherwise, the default
+ is <constant>ddns-key</constant> as a separate label
+ followed by the argument of the option, e.g.,
+ <constant>ddns-key.example.com.</constant>
+ The key name must have the format of a valid domain name,
+ consisting of letters, digits, hyphens and periods.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ (<command>ddns-confgen</command> only.) Quiet mode: Print
+ only the key, with no explanatory text or usage examples;
+ This is essentially identical to <command>tsig-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomfile</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a source of random data for generating the
+ authorization. If the operating system does not provide a
+ <filename>/dev/random</filename> or equivalent device, the
+ default source of randomness is keyboard input.
+ <filename>randomdev</filename> specifies the name of a
+ character device or file containing random data to be used
+ instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard input
+ should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ (<command>ddns-confgen</command> only.)
+ Generate configuration example to allow dynamic updates
+ of a single hostname. The example <command>named.conf</command>
+ text shows how to set an update policy for the specified
+ <replaceable class="parameter">name</replaceable>
+ using the "name" nametype. The default key name is
+ ddns-key.<replaceable class="parameter">name</replaceable>.
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z <replaceable class="parameter">zone</replaceable></term>
+ <listitem>
+ <para>
+ (<command>ddns-confgen</command> only.)
+ Generate configuration example to allow dynamic updates
+ of a zone: The example <command>named.conf</command> text
+ shows how to set an update policy for the specified
+ <replaceable class="parameter">zone</replaceable>
+ using the "zonesub" nametype, allowing updates to
+ all subdomain names within that
+ <replaceable class="parameter">zone</replaceable>.
+ This option cannot be used with the <option>-s</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>nsupdate</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/confgen/ddns-confgen.html b/bin/confgen/ddns-confgen.html
new file mode 100644
index 0000000..f31fad5
--- /dev/null
+++ b/bin/confgen/ddns-confgen.html
@@ -0,0 +1,202 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>ddns-confgen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.ddns-confgen"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">ddns-confgen</span>
+ &#8212; ddns key generation tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">tsig-keygen</code>
+ [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>]
+ [name]
+ </p></div>
+ <div class="cmdsynopsis"><p>
+ <code class="command">ddns-confgen</code>
+ [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-k <em class="replaceable"><code>keyname</code></em></code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>]
+ [
+ -s <em class="replaceable"><code>name</code></em>
+ | -z <em class="replaceable"><code>zone</code></em>
+ ]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>tsig-keygen</strong></span> and <span class="command"><strong>ddns-confgen</strong></span>
+ are invocation methods for a 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
+ <span class="command"><strong>rndc</strong></span> command channel.
+ </p>
+
+ <p>
+ When run as <span class="command"><strong>tsig-keygen</strong></span>, a domain name
+ can be specified on the command line which will be used as
+ the name of the generated key. If no name is specified,
+ the default is <code class="constant">tsig-key</code>.
+ </p>
+
+ <p>
+ When run as <span class="command"><strong>ddns-confgen</strong></span>, the generated
+ key is accompanied by configuration text and instructions
+ that can be used with <span class="command"><strong>nsupdate</strong></span> and
+ <span class="command"><strong>named</strong></span> when setting up dynamic DNS,
+ including an example <span class="command"><strong>update-policy</strong></span>
+ statement. (This usage similar to the
+ <span class="command"><strong>rndc-confgen</strong></span> command for setting
+ up command channel security.)
+ </p>
+
+ <p>
+ Note that <span class="command"><strong>named</strong></span> itself can configure a
+ local DDNS key for use with <span class="command"><strong>nsupdate -l</strong></span>:
+ it does this when a zone is configured with
+ <span class="command"><strong>update-policy local;</strong></span>.
+ <span class="command"><strong>ddns-confgen</strong></span> is only needed when a
+ more elaborate configuration is required: for instance,
+ if <span class="command"><strong>nsupdate</strong></span> is to be used from a remote
+ system.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+ <p>
+ 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.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Prints a short summary of options and arguments.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyname</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the key name of the DDNS authentication key.
+ The default is <code class="constant">ddns-key</code> when neither
+ the <code class="option">-s</code> nor <code class="option">-z</code> option is
+ specified; otherwise, the default
+ is <code class="constant">ddns-key</code> as a separate label
+ followed by the argument of the option, e.g.,
+ <code class="constant">ddns-key.example.com.</code>
+ The key name must have the format of a valid domain name,
+ consisting of letters, digits, hyphens and periods.
+ </p>
+ </dd>
+<dt><span class="term">-q</span></dt>
+<dd>
+ <p>
+ (<span class="command"><strong>ddns-confgen</strong></span> only.) Quiet mode: Print
+ only the key, with no explanatory text or usage examples;
+ This is essentially identical to <span class="command"><strong>tsig-keygen</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomfile</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a source of random data for generating the
+ authorization. If the operating system does not provide a
+ <code class="filename">/dev/random</code> or equivalent device, the
+ default source of randomness is keyboard input.
+ <code class="filename">randomdev</code> specifies the name of a
+ character device or file containing random data to be used
+ instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard input
+ should be used.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>name</code></em></span></dt>
+<dd>
+ <p>
+ (<span class="command"><strong>ddns-confgen</strong></span> only.)
+ Generate configuration example to allow dynamic updates
+ of a single hostname. The example <span class="command"><strong>named.conf</strong></span>
+ text shows how to set an update policy for the specified
+ <em class="replaceable"><code>name</code></em>
+ using the "name" nametype. The default key name is
+ ddns-key.<em class="replaceable"><code>name</code></em>.
+ 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 <code class="option">-z</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-z <em class="replaceable"><code>zone</code></em></span></dt>
+<dd>
+ <p>
+ (<span class="command"><strong>ddns-confgen</strong></span> only.)
+ Generate configuration example to allow dynamic updates
+ of a zone: The example <span class="command"><strong>named.conf</strong></span> text
+ shows how to set an update policy for the specified
+ <em class="replaceable"><code>zone</code></em>
+ using the "zonesub" nametype, allowing updates to
+ all subdomain names within that
+ <em class="replaceable"><code>zone</code></em>.
+ This option cannot be used with the <code class="option">-s</code> option.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">nsupdate</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named.conf</span>(5)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/confgen/include/confgen/os.h b/bin/confgen/include/confgen/os.h
new file mode 100644
index 0000000..6346b2b
--- /dev/null
+++ b/bin/confgen/include/confgen/os.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#ifndef RNDC_OS_H
+#define RNDC_OS_H 1
+
+#include <isc/lang.h>
+#include <stdio.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
+
+#endif
diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c
new file mode 100644
index 0000000..8931ad5
--- /dev/null
+++ b/bin/confgen/keygen.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/keyboard.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+
+#include <pk11/site.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+#include <confgen/os.h>
+
+#include "util.h"
+#include "keygen.h"
+
+/*%
+ * Convert algorithm type to string.
+ */
+const char *
+alg_totext(dns_secalg_t alg) {
+ switch (alg) {
+#ifndef PK11_MD5_DISABLE
+ case DST_ALG_HMACMD5:
+ return "hmac-md5";
+#endif
+ case DST_ALG_HMACSHA1:
+ return "hmac-sha1";
+ case DST_ALG_HMACSHA224:
+ return "hmac-sha224";
+ case DST_ALG_HMACSHA256:
+ return "hmac-sha256";
+ case DST_ALG_HMACSHA384:
+ return "hmac-sha384";
+ case DST_ALG_HMACSHA512:
+ return "hmac-sha512";
+ default:
+ return "(unknown)";
+ }
+}
+
+/*%
+ * 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];
+
+#ifndef PK11_MD5_DISABLE
+ if (strcasecmp(p, "md5") == 0)
+ return DST_ALG_HMACMD5;
+#endif
+ 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' using entropy source 'randomfile',
+ * and place it in 'key_txtbuffer'
+ */
+void
+generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg,
+ int keysize, isc_buffer_t *key_txtbuffer) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_entropysource_t *entropy_source = NULL;
+ int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE;
+ int entropy_flags = 0;
+ isc_entropy_t *ectx = NULL;
+ isc_buffer_t key_rawbuffer;
+ isc_region_t key_rawregion;
+ char key_rawsecret[64];
+ dst_key_t *key = NULL;
+
+ switch (alg) {
+#ifndef PK11_MD5_DISABLE
+ case DST_ALG_HMACMD5:
+#endif
+ 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("create entropy context", isc_entropy_create(mctx, &ectx));
+
+ if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+ randomfile = NULL;
+ open_keyboard = ISC_ENTROPY_KEYBOARDYES;
+ }
+ DO("start entropy source", isc_entropy_usebestsource(ectx,
+ &entropy_source,
+ randomfile,
+ open_keyboard));
+
+ entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY;
+
+ DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags));
+
+ DO("generate key", dst_key_generate(dns_rootname, alg,
+ keysize, 0, 0,
+ DNS_KEYPROTO_ANY,
+ dns_rdataclass_in, mctx, &key));
+
+ 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));
+
+ /*
+ * Shut down the entropy source now so the "stop typing" message
+ * does not muck with the output.
+ */
+ if (entropy_source != NULL)
+ isc_entropy_destroysource(&entropy_source);
+
+ if (key != NULL)
+ dst_key_free(&key);
+
+ isc_entropy_detach(&ectx);
+ 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 = alg_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);
+ fprintf(stderr, "wrote key file \"%s\"\n", keyfile);
+}
diff --git a/bin/confgen/keygen.h b/bin/confgen/keygen.h
new file mode 100644
index 0000000..58debab
--- /dev/null
+++ b/bin/confgen/keygen.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef RNDC_KEYGEN_H
+#define RNDC_KEYGEN_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+void generate_key(isc_mem_t *mctx, const char *randomfile, 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
+
+#endif /* RNDC_KEYGEN_H */
diff --git a/bin/confgen/rndc-confgen.8 b/bin/confgen/rndc-confgen.8
new file mode 100644
index 0000000..1021020
--- /dev/null
+++ b/bin/confgen/rndc-confgen.8
@@ -0,0 +1,221 @@
+.\" Copyright (C) 2001, 2003-2005, 2007, 2009, 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: rndc-confgen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2013-03-14
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "RNDC\-CONFGEN" "8" "2013\-03\-14" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+rndc-confgen \- rndc key generation tool
+.SH "SYNOPSIS"
+.HP \w'\fBrndc\-confgen\fR\ 'u
+\fBrndc\-confgen\fR [\fB\-a\fR] [\fB\-A\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-c\ \fR\fB\fIkeyfile\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\fB\-s\ \fR\fB\fIaddress\fR\fR] [\fB\-t\ \fR\fB\fIchrootdir\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR]
+.SH "DESCRIPTION"
+.PP
+\fBrndc\-confgen\fR
+generates configuration files for
+\fBrndc\fR\&. It can be used as a convenient alternative to writing the
+rndc\&.conf
+file and the corresponding
+\fBcontrols\fR
+and
+\fBkey\fR
+statements in
+named\&.conf
+by hand\&. Alternatively, it can be run with the
+\fB\-a\fR
+option to set up a
+rndc\&.key
+file and avoid the need for a
+rndc\&.conf
+file and a
+\fBcontrols\fR
+statement altogether\&.
+.SH "OPTIONS"
+.PP
+\-a
+.RS 4
+Do automatic
+\fBrndc\fR
+configuration\&. This creates a file
+rndc\&.key
+in
+/etc
+(or whatever
+\fIsysconfdir\fR
+was specified as when
+BIND
+was built) that is read by both
+\fBrndc\fR
+and
+\fBnamed\fR
+on startup\&. The
+rndc\&.key
+file defines a default command channel and authentication key allowing
+\fBrndc\fR
+to communicate with
+\fBnamed\fR
+on the local host with no further configuration\&.
+.sp
+Running
+\fBrndc\-confgen \-a\fR
+allows BIND 9 and
+\fBrndc\fR
+to be used as drop\-in replacements for BIND 8 and
+\fBndc\fR, with no changes to the existing BIND 8
+named\&.conf
+file\&.
+.sp
+If a more elaborate configuration than that generated by
+\fBrndc\-confgen \-a\fR
+is required, for example if rndc is to be used remotely, you should run
+\fBrndc\-confgen\fR
+without the
+\fB\-a\fR
+option and set up a
+rndc\&.conf
+and
+named\&.conf
+as directed\&.
+.RE
+.PP
+\-A \fIalgorithm\fR
+.RS 4
+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\-md5 or if MD5 was disabled hmac\-sha256\&.
+.RE
+.PP
+\-b \fIkeysize\fR
+.RS 4
+Specifies the size of the authentication key in bits\&. Must be between 1 and 512 bits; the default is the hash size\&.
+.RE
+.PP
+\-c \fIkeyfile\fR
+.RS 4
+Used with the
+\fB\-a\fR
+option to specify an alternate location for
+rndc\&.key\&.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBrndc\-confgen\fR\&.
+.RE
+.PP
+\-k \fIkeyname\fR
+.RS 4
+Specifies the key name of the rndc authentication key\&. This must be a valid domain name\&. The default is
+\fBrndc\-key\fR\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Specifies the command channel port where
+\fBnamed\fR
+listens for connections from
+\fBrndc\fR\&. The default is 953\&.
+.RE
+.PP
+\-r \fIrandomfile\fR
+.RS 4
+Specifies a source of random data for generating the authorization\&. If the operating system does not provide a
+/dev/random
+or equivalent device, the default source of randomness is keyboard input\&.
+randomdev
+specifies the name of a character device or file containing random data to be used instead of the default\&. The special value
+keyboard
+indicates that keyboard input should be used\&.
+.RE
+.PP
+\-s \fIaddress\fR
+.RS 4
+Specifies the IP address where
+\fBnamed\fR
+listens for command channel connections from
+\fBrndc\fR\&. The default is the loopback address 127\&.0\&.0\&.1\&.
+.RE
+.PP
+\-t \fIchrootdir\fR
+.RS 4
+Used with the
+\fB\-a\fR
+option to specify a directory where
+\fBnamed\fR
+will run chrooted\&. An additional copy of the
+rndc\&.key
+will be written relative to this directory so that it will be found by the chrooted
+\fBnamed\fR\&.
+.RE
+.PP
+\-u \fIuser\fR
+.RS 4
+Used with the
+\fB\-a\fR
+option to set the owner of the
+rndc\&.key
+file generated\&. If
+\fB\-t\fR
+is also specified only the file in the chroot area has its owner changed\&.
+.RE
+.SH "EXAMPLES"
+.PP
+To allow
+\fBrndc\fR
+to be used with no manual configuration, run
+.PP
+\fBrndc\-confgen \-a\fR
+.PP
+To print a sample
+rndc\&.conf
+file and corresponding
+\fBcontrols\fR
+and
+\fBkey\fR
+statements to be manually inserted into
+named\&.conf, run
+.PP
+\fBrndc\-confgen\fR
+.SH "SEE ALSO"
+.PP
+\fBrndc\fR(8),
+\fBrndc.conf\fR(5),
+\fBnamed\fR(8),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2001, 2003-2005, 2007, 2009, 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c
new file mode 100644
index 0000000..5ca3d76
--- /dev/null
+++ b/bin/confgen/rndc-confgen.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: rndc-confgen.c,v 1.7 2011/03/12 04:59:46 tbox Exp $ */
+
+/*! \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 <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/assertions.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/keyboard.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 <pk11/site.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+#include <confgen/os.h>
+
+#include "util.h"
+#include "keygen.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;
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(int status) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(int status) {
+
+#ifndef PK11_MD5_DISABLE
+ fprintf(stderr, "\
+Usage:\n\
+ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \
+[-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-md5)\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\
+ -r randomfile: source of random data (use \"keyboard\" for key timing)\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);
+#else
+ fprintf(stderr, "\
+Usage:\n\
+ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \
+[-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\
+ -r randomfile: source of random data (use \"keyboard\" for key timing)\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);
+#endif
+
+ 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 *randomfile = 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;
+ 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;
+#ifndef PK11_MD5_DISABLE
+ alg = DST_ALG_HMACMD5;
+#else
+ alg = DST_ALG_HMACSHA256;
+#endif
+ 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 'r':
+ randomfile = isc_commandline_argument;
+ 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 (keysize < 0)
+ keysize = alg_bits(alg);
+ algname = alg_totext(alg);
+
+ DO("create memory context", isc_mem_create(0, 0, &mctx));
+ isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
+
+ generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer);
+
+ if (keyonly) {
+ write_key_file(keyfile, chrootdir == NULL ? user : NULL,
+ keyname, &key_txtbuffer, alg);
+
+ if (chrootdir != NULL) {
+ char *buf;
+ len = strlen(chrootdir) + strlen(keyfile) + 2;
+ buf = isc_mem_get(mctx, len);
+ if (buf == NULL)
+ fatal("isc_mem_get(%d) failed\n", len);
+ snprintf(buf, len, "%s%s%s", chrootdir,
+ (*keyfile != '/') ? "/" : "", keyfile);
+
+ write_key_file(buf, user, keyname, &key_txtbuffer, alg);
+ 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.docbook b/bin/confgen/rndc-confgen.docbook
new file mode 100644
index 0000000..97e3017
--- /dev/null
+++ b/bin/confgen/rndc-confgen.docbook
@@ -0,0 +1,289 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.rndc-confgen">
+ <info>
+ <date>2013-03-14</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>rndc-confgen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>rndc-confgen</application></refname>
+ <refpurpose>rndc key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2001</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2009</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>rndc-confgen</command>
+ <arg choice="opt" rep="norepeat"><option>-a</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-A <replaceable class="parameter">algorithm</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">keysize</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">keyfile</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">keyname</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">randomfile</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">address</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">chrootdir</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-u <replaceable class="parameter">user</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>rndc-confgen</command>
+ generates configuration files
+ for <command>rndc</command>. It can be used as a
+ convenient alternative to writing the
+ <filename>rndc.conf</filename> file
+ and the corresponding <command>controls</command>
+ and <command>key</command>
+ statements in <filename>named.conf</filename> by hand.
+ Alternatively, it can be run with the <command>-a</command>
+ option to set up a <filename>rndc.key</filename> file and
+ avoid the need for a <filename>rndc.conf</filename> file
+ and a <command>controls</command> statement altogether.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ Do automatic <command>rndc</command> configuration.
+ This creates a file <filename>rndc.key</filename>
+ in <filename>/etc</filename> (or whatever
+ <varname>sysconfdir</varname>
+ was specified as when <acronym>BIND</acronym> was
+ built)
+ that is read by both <command>rndc</command>
+ and <command>named</command> on startup. The
+ <filename>rndc.key</filename> file defines a default
+ command channel and authentication key allowing
+ <command>rndc</command> to communicate with
+ <command>named</command> on the local host
+ with no further configuration.
+ </para>
+ <para>
+ Running <command>rndc-confgen -a</command> allows
+ BIND 9 and <command>rndc</command> to be used as
+ drop-in
+ replacements for BIND 8 and <command>ndc</command>,
+ with no changes to the existing BIND 8
+ <filename>named.conf</filename> file.
+ </para>
+ <para>
+ If a more elaborate configuration than that
+ generated by <command>rndc-confgen -a</command>
+ is required, for example if rndc is to be used remotely,
+ you should run <command>rndc-confgen</command> without
+ the
+ <command>-a</command> option and set up a
+ <filename>rndc.conf</filename> and
+ <filename>named.conf</filename>
+ as directed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ 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-md5 or
+ if MD5 was disabled hmac-sha256.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the size of the authentication key in bits.
+ Must be between 1 and 512 bits; the default is the
+ hash size.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">keyfile</replaceable></term>
+ <listitem>
+ <para>
+ Used with the <command>-a</command> option to specify
+ an alternate location for <filename>rndc.key</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>rndc-confgen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">keyname</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the key name of the rndc authentication key.
+ This must be a valid domain name.
+ The default is <constant>rndc-key</constant>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the command channel port where <command>named</command>
+ listens for connections from <command>rndc</command>.
+ The default is 953.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomfile</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a source of random data for generating the
+ authorization. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">address</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the IP address where <command>named</command>
+ listens for command channel connections from
+ <command>rndc</command>. The default is the loopback
+ address 127.0.0.1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">chrootdir</replaceable></term>
+ <listitem>
+ <para>
+ Used with the <command>-a</command> option to specify
+ a directory where <command>named</command> will run
+ chrooted. An additional copy of the <filename>rndc.key</filename>
+ will be written relative to this directory so that
+ it will be found by the chrooted <command>named</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">user</replaceable></term>
+ <listitem>
+ <para>
+ Used with the <command>-a</command> option to set the
+ owner
+ of the <filename>rndc.key</filename> file generated.
+ If
+ <command>-t</command> is also specified only the file
+ in
+ the chroot area has its owner changed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>EXAMPLES</title></info>
+
+ <para>
+ To allow <command>rndc</command> to be used with
+ no manual configuration, run
+ </para>
+ <para><userinput>rndc-confgen -a</userinput>
+ </para>
+ <para>
+ To print a sample <filename>rndc.conf</filename> file and
+ corresponding <command>controls</command> and <command>key</command>
+ statements to be manually inserted into <filename>named.conf</filename>,
+ run
+ </para>
+ <para><userinput>rndc-confgen</userinput>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/confgen/rndc-confgen.html b/bin/confgen/rndc-confgen.html
new file mode 100644
index 0000000..cf58434
--- /dev/null
+++ b/bin/confgen/rndc-confgen.html
@@ -0,0 +1,243 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2001, 2003-2005, 2007, 2009, 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc-confgen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.rndc-confgen"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">rndc-confgen</span>
+ &#8212; rndc key generation tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">rndc-confgen</code>
+ [<code class="option">-a</code>]
+ [<code class="option">-A <em class="replaceable"><code>algorithm</code></em></code>]
+ [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>keyfile</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-k <em class="replaceable"><code>keyname</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>port</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>address</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>chrootdir</code></em></code>]
+ [<code class="option">-u <em class="replaceable"><code>user</code></em></code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>rndc-confgen</strong></span>
+ generates configuration files
+ for <span class="command"><strong>rndc</strong></span>. It can be used as a
+ convenient alternative to writing the
+ <code class="filename">rndc.conf</code> file
+ and the corresponding <span class="command"><strong>controls</strong></span>
+ and <span class="command"><strong>key</strong></span>
+ statements in <code class="filename">named.conf</code> by hand.
+ Alternatively, it can be run with the <span class="command"><strong>-a</strong></span>
+ option to set up a <code class="filename">rndc.key</code> file and
+ avoid the need for a <code class="filename">rndc.conf</code> file
+ and a <span class="command"><strong>controls</strong></span> statement altogether.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a</span></dt>
+<dd>
+ <p>
+ Do automatic <span class="command"><strong>rndc</strong></span> configuration.
+ This creates a file <code class="filename">rndc.key</code>
+ in <code class="filename">/etc</code> (or whatever
+ <code class="varname">sysconfdir</code>
+ was specified as when <acronym class="acronym">BIND</acronym> was
+ built)
+ that is read by both <span class="command"><strong>rndc</strong></span>
+ and <span class="command"><strong>named</strong></span> on startup. The
+ <code class="filename">rndc.key</code> file defines a default
+ command channel and authentication key allowing
+ <span class="command"><strong>rndc</strong></span> to communicate with
+ <span class="command"><strong>named</strong></span> on the local host
+ with no further configuration.
+ </p>
+ <p>
+ Running <span class="command"><strong>rndc-confgen -a</strong></span> allows
+ BIND 9 and <span class="command"><strong>rndc</strong></span> to be used as
+ drop-in
+ replacements for BIND 8 and <span class="command"><strong>ndc</strong></span>,
+ with no changes to the existing BIND 8
+ <code class="filename">named.conf</code> file.
+ </p>
+ <p>
+ If a more elaborate configuration than that
+ generated by <span class="command"><strong>rndc-confgen -a</strong></span>
+ is required, for example if rndc is to be used remotely,
+ you should run <span class="command"><strong>rndc-confgen</strong></span> without
+ the
+ <span class="command"><strong>-a</strong></span> option and set up a
+ <code class="filename">rndc.conf</code> and
+ <code class="filename">named.conf</code>
+ as directed.
+ </p>
+ </dd>
+<dt><span class="term">-A <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+ <p>
+ 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-md5 or
+ if MD5 was disabled hmac-sha256.
+ </p>
+ </dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the size of the authentication key in bits.
+ Must be between 1 and 512 bits; the default is the
+ hash size.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>keyfile</code></em></span></dt>
+<dd>
+ <p>
+ Used with the <span class="command"><strong>-a</strong></span> option to specify
+ an alternate location for <code class="filename">rndc.key</code>.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Prints a short summary of the options and arguments to
+ <span class="command"><strong>rndc-confgen</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyname</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the key name of the rndc authentication key.
+ This must be a valid domain name.
+ The default is <code class="constant">rndc-key</code>.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the command channel port where <span class="command"><strong>named</strong></span>
+ listens for connections from <span class="command"><strong>rndc</strong></span>.
+ The default is 953.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomfile</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a source of random data for generating the
+ authorization. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>address</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the IP address where <span class="command"><strong>named</strong></span>
+ listens for command channel connections from
+ <span class="command"><strong>rndc</strong></span>. The default is the loopback
+ address 127.0.0.1.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>chrootdir</code></em></span></dt>
+<dd>
+ <p>
+ Used with the <span class="command"><strong>-a</strong></span> option to specify
+ a directory where <span class="command"><strong>named</strong></span> will run
+ chrooted. An additional copy of the <code class="filename">rndc.key</code>
+ will be written relative to this directory so that
+ it will be found by the chrooted <span class="command"><strong>named</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd>
+ <p>
+ Used with the <span class="command"><strong>-a</strong></span> option to set the
+ owner
+ of the <code class="filename">rndc.key</code> file generated.
+ If
+ <span class="command"><strong>-t</strong></span> is also specified only the file
+ in
+ the chroot area has its owner changed.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>EXAMPLES</h2>
+
+ <p>
+ To allow <span class="command"><strong>rndc</strong></span> to be used with
+ no manual configuration, run
+ </p>
+ <p><strong class="userinput"><code>rndc-confgen -a</code></strong>
+ </p>
+ <p>
+ To print a sample <code class="filename">rndc.conf</code> file and
+ corresponding <span class="command"><strong>controls</strong></span> and <span class="command"><strong>key</strong></span>
+ statements to be manually inserted into <code class="filename">named.conf</code>,
+ run
+ </p>
+ <p><strong class="userinput"><code>rndc-confgen</code></strong>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">rndc</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc.conf</span>(5)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/confgen/unix/Makefile.in b/bin/confgen/unix/Makefile.in
new file mode 100644
index 0000000..64e3cb8
--- /dev/null
+++ b/bin/confgen/unix/Makefile.in
@@ -0,0 +1,28 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \
+ ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+OBJS = os.@O@
+
+SRCS = os.c
+
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/bin/confgen/unix/os.c b/bin/confgen/unix/os.c
new file mode 100644
index 0000000..b305b34
--- /dev/null
+++ b/bin/confgen/unix/os.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <confgen/os.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.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/util.c b/bin/confgen/util.c
new file mode 100644
index 0000000..0066e7c
--- /dev/null
+++ b/bin/confgen/util.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/print.h>
+
+#include "util.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);
+ fputs("\n", stderr);
+ }
+}
+
+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..fa4a62b
--- /dev/null
+++ b/bin/confgen/util.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef RNDC_UTIL_H
+#define RNDC_UTIL_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+#include <isc/formatcheck.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);
+
+ISC_PLATFORM_NORETURN_PRE void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+ISC_LANG_ENDDECLS
+
+#endif /* RNDC_UTIL_H */
diff --git a/bin/confgen/win32/confgentool.dsp.in b/bin/confgen/win32/confgentool.dsp.in
new file mode 100644
index 0000000..833361b
--- /dev/null
+++ b/bin/confgen/win32/confgentool.dsp.in
@@ -0,0 +1,135 @@
+# Microsoft Developer Studio Project File - Name="confgentool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104
+
+CFG=confgentool - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "confgentool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "confgentool.mak" CFG="confgentool - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "confgentool - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE "confgentool - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "confgentool - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fdconfgentool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/confgentool.lib"
+LIB32=lib.exe
+# ADD BASE LIB32
+# ADD LIB32 /out:"Release/confgentool.lib"
+
+!ELSEIF "$(CFG)" == "confgentool - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fdconfgentool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug /out:"Debug/confgentool.lib"
+LIB32=lib.exe
+# ADD BASE LIB32
+# ADD LIB32 /out:"Debug/confgentool.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "confgentool - @PLATFORM@ Release"
+# Name "confgentool - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\keygen.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\keygen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/confgen/win32/confgentool.dsw b/bin/confgen/win32/confgentool.dsw
new file mode 100644
index 0000000..5a27174
--- /dev/null
+++ b/bin/confgen/win32/confgentool.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "confgentool"=".\confgentool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/confgen/win32/confgentool.vcxproj.filters.in b/bin/confgen/win32/confgentool.vcxproj.filters.in
new file mode 100644
index 0000000..231e4e1
--- /dev/null
+++ b/bin/confgen/win32/confgentool.vcxproj.filters.in
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\keygen.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\confgen\os.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\keygen.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\util.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="os.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/confgen/win32/confgentool.vcxproj.in b/bin/confgen/win32/confgentool.vcxproj.in
new file mode 100644
index 0000000..5798e7b
--- /dev/null
+++ b/bin/confgen/win32/confgentool.vcxproj.in
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{64964B03-4815-41F0-9057-E766A94AF197}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>confgentool</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\confgen\os.h" />
+ <ClInclude Include="..\keygen.h" />
+ <ClInclude Include="..\util.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\keygen.c" />
+ <ClCompile Include="..\util.c" />
+ <ClCompile Include="os.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/confgen/win32/confgentool.vcxproj.user b/bin/confgen/win32/confgentool.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/confgen/win32/confgentool.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/confgen/win32/ddnsconfgen.dsp.in b/bin/confgen/win32/ddnsconfgen.dsp.in
new file mode 100644
index 0000000..625351d
--- /dev/null
+++ b/bin/confgen/win32/ddnsconfgen.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="ddnsconfgen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=ddnsconfgen - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ddnsconfgen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ddnsconfgen.mak" CFG="ddnsconfgen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ddnsconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "ddnsconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/confgentool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/ddns-confgen.exe"
+
+!ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/confgentool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/ddns-confgen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "ddnsconfgen - @PLATFORM@ Release"
+# Name "ddnsconfgen - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\ddns-confgen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/confgen/win32/ddnsconfgen.dsw b/bin/confgen/win32/ddnsconfgen.dsw
new file mode 100644
index 0000000..d331818
--- /dev/null
+++ b/bin/confgen/win32/ddnsconfgen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ddnsconfgen"=".\ddnsconfgen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/confgen/win32/ddnsconfgen.mak.in b/bin/confgen/win32/ddnsconfgen.mak.in
new file mode 100644
index 0000000..9433404
--- /dev/null
+++ b/bin/confgen/win32/ddnsconfgen.mak.in
@@ -0,0 +1,337 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on ddnsconfgen.dsp
+!IF "$(CFG)" == ""
+CFG=ddnsconfgen - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to ddnsconfgen - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ddnsconfgen - @PLATFORM@ Release" && "$(CFG)" != "ddnsconfgen - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ddnsconfgen.mak" CFG="ddnsconfgen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ddnsconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "ddnsconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\ddns-confgen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\ddns-confgen.obj"
+ -@erase "$(INTDIR)\keygen.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\ddns-confgen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\ddnsconfgen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ddnsconfgen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\ddns-confgen.pdb" @MACHINE@ /out:"../../../Build/Release/ddns-confgen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\ddns-confgen.obj" \
+ "$(INTDIR)\keygen.obj" \
+ "$(INTDIR)\util.obj"
+
+"..\..\..\Build\Release\ddns-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\ddns-confgen.exe" "$(OUTDIR)\ddnsconfgen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\ddns-confgen.obj"
+ -@erase "$(INTDIR)\ddns-confgen.sbr"
+ -@erase "$(INTDIR)\keygen.obj"
+ -@erase "$(INTDIR)\keygen.sbr"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\ddnsconfgen.bsc"
+ -@erase "$(OUTDIR)\ddns-confgen.pdb"
+ -@erase "..\..\..\Build\Debug\ddns-confgen.exe"
+ -@erase "..\..\..\Build\Debug\ddns-confgen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\ddnsconfgen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\os.sbr" \
+ "$(INTDIR)\ddns-confgen.sbr" \
+ "$(INTDIR)\keygen.sbr" \
+ "$(INTDIR)\util.sbr"
+
+"$(OUTDIR)\ddnsconfgen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\ddns-confgen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/ddns-confgen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\ddns-confgen.obj" \
+ "$(INTDIR)\keygen.obj" \
+ "$(INTDIR)\util.obj"
+
+"..\..\..\Build\Debug\ddns-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("ddnsconfgen.dep")
+!INCLUDE "ddnsconfgen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "ddnsconfgen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" || "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE="..\ddns-confgen.c"
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ddns-confgen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ddns-confgen.obj" "$(INTDIR)\ddns-confgen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\keygen.c
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\keygen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\keygen.obj" "$(INTDIR)\keygen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\util.c
+
+!IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/confgen/win32/ddnsconfgen.vcxproj.filters.in b/bin/confgen/win32/ddnsconfgen.vcxproj.filters.in
new file mode 100644
index 0000000..ccdaa81
--- /dev/null
+++ b/bin/confgen/win32/ddnsconfgen.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\ddns-confgen.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/confgen/win32/ddnsconfgen.vcxproj.in b/bin/confgen/win32/ddnsconfgen.vcxproj.in
new file mode 100644
index 0000000..3d88005
--- /dev/null
+++ b/bin/confgen/win32/ddnsconfgen.vcxproj.in
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1EA4FC64-F33B-4A50-970A-EA052BBE9CF1}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ddnsconfgen</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>ddns-confgen</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>ddns-confgen</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>cd ..\..\..\Build\$(Configuration)
+copy /Y ddns-confgen.exe tsig-keygen.exe
+copy /Y ddns-confgen.ilk tsig-keygen.ilk
+</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>cd ..\..\..\Build\$(Configuration)
+copy /Y ddns-confgen.exe tsig-keygen.exe
+</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\ddns-confgen.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/confgen/win32/ddnsconfgen.vcxproj.user b/bin/confgen/win32/ddnsconfgen.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/confgen/win32/ddnsconfgen.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/confgen/win32/os.c b/bin/confgen/win32/os.c
new file mode 100644
index 0000000..4ef9d64
--- /dev/null
+++ b/bin/confgen/win32/os.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <confgen/os.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <io.h>
+#include <sys/stat.h>
+
+int
+set_user(FILE *fd, const char *user) {
+ return (0);
+}
diff --git a/bin/confgen/win32/rndcconfgen.dsp.in b/bin/confgen/win32/rndcconfgen.dsp.in
new file mode 100644
index 0000000..e4569c6
--- /dev/null
+++ b/bin/confgen/win32/rndcconfgen.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="rndcconfgen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=rndcconfgen - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rndcconfgen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndcconfgen.mak" CFG="rndcconfgen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndcconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rndcconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/confgentool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/rndc-confgen.exe"
+
+!ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/confgentool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/rndc-confgen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rndcconfgen - @PLATFORM@ Release"
+# Name "rndcconfgen - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\rndc-confgen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/confgen/win32/rndcconfgen.dsw b/bin/confgen/win32/rndcconfgen.dsw
new file mode 100644
index 0000000..cf17691
--- /dev/null
+++ b/bin/confgen/win32/rndcconfgen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rndconfgen"=".\rndconfgen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/confgen/win32/rndcconfgen.mak.in b/bin/confgen/win32/rndcconfgen.mak.in
new file mode 100644
index 0000000..4b0814d
--- /dev/null
+++ b/bin/confgen/win32/rndcconfgen.mak.in
@@ -0,0 +1,336 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on confgen.dsp
+!IF "$(CFG)" == ""
+CFG=rndcconfgen - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to rndcconfgen - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rndcconfgen - @PLATFORM@ Release" && "$(CFG)" != "rndcconfgen - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndcconfgen.mak" CFG="rndcconfgen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndcconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rndcconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\rndc-confgen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\rndc-confgen.obj"
+ -@erase "$(INTDIR)\keygen.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\rndc-confgen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\confgen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\confgen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\rndc-confgen.pdb" @MACHINE@ /out:"../../../Build/Release/rndc-confgen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\rndc-confgen.obj" \
+ "$(INTDIR)\keygen.obj" \
+ "$(INTDIR)\util.obj"
+
+"..\..\..\Build\Release\rndc-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\rndc-confgen.exe" "$(OUTDIR)\confgen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\rndc-confgen.obj"
+ -@erase "$(INTDIR)\rndc-confgen.sbr"
+ -@erase "$(INTDIR)\keygen.obj"
+ -@erase "$(INTDIR)\keygen.sbr"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\confgen.bsc"
+ -@erase "$(OUTDIR)\rndc-confgen.pdb"
+ -@erase "..\..\..\Build\Debug\rndc-confgen.exe"
+ -@erase "..\..\..\Build\Debug\rndc-confgen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\confgen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\os.sbr" \
+ "$(INTDIR)\rndc-confgen.sbr" \
+ "$(INTDIR)\keygen.sbr" \
+ "$(INTDIR)\util.sbr"
+
+"$(OUTDIR)\confgen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rndc-confgen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/rndc-confgen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\rndc-confgen.obj" \
+ "$(INTDIR)\keygen.obj" \
+ "$(INTDIR)\util.obj"
+
+"..\..\..\Build\Debug\rndc-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("confgen.dep")
+!INCLUDE "confgen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "confgen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" || "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE="..\rndc-confgen.c"
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\rndc-confgen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\rndc-confgen.obj" "$(INTDIR)\rndc-confgen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\keygen.c
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\keygen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\keygen.obj" "$(INTDIR)\keygen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\util.c
+
+!IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/confgen/win32/rndcconfgen.vcxproj.filters.in b/bin/confgen/win32/rndcconfgen.vcxproj.filters.in
new file mode 100644
index 0000000..20f6b5a
--- /dev/null
+++ b/bin/confgen/win32/rndcconfgen.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rndc-confgen.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/confgen/win32/rndcconfgen.vcxproj.in b/bin/confgen/win32/rndcconfgen.vcxproj.in
new file mode 100644
index 0000000..01c9af2
--- /dev/null
+++ b/bin/confgen/win32/rndcconfgen.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1E2C1635-3093-4D59-80E7-4743AC10F22F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>rndcconfgen</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>rndc-confgen</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>rndc-confgen</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rndc-confgen.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/confgen/win32/rndcconfgen.vcxproj.user b/bin/confgen/win32/rndcconfgen.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/confgen/win32/rndcconfgen.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/delv/Makefile.in b/bin/delv/Makefile.in
new file mode 100644
index 0000000..e2d2802
--- /dev/null
+++ b/bin/delv/Makefile.in
@@ -0,0 +1,81 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${ISC_INCLUDES} \
+ ${IRS_INCLUDES} ${ISCCFG_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@ -DVERSION=\"${VERSION}\" \
+ -DSYSCONFDIR=\"${sysconfdir}\"
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+IRSLIBS = ../../lib/irs/libirs.@A@
+
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+IRSDEPLIBS = ../../lib/irs/libirs.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${IRSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${IRSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
+NOSYMLIBS = ${DNSLIBS} ${IRSLIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = delv@EXEEXT@
+
+OBJS = delv.@O@
+
+SRCS = delv.c
+
+MANPAGES = delv.1
+
+HTMLPAGES = delv.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+delv@EXEEXT@: delv.@O@ ${DEPLIBS}
+ export BASEOBJS="delv.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+
+install:: delv@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ delv@EXEEXT@ ${DESTDIR}${bindir}
+ ${INSTALL_DATA} ${srcdir}/delv.1 ${DESTDIR}${mandir}/man1
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man1/delv.1
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/delv@EXEEXT@
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
diff --git a/bin/delv/delv.1 b/bin/delv/delv.1
new file mode 100644
index 0000000..f8e0da5
--- /dev/null
+++ b/bin/delv/delv.1
@@ -0,0 +1,441 @@
+.\" Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: delv
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-04-23
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DELV" "1" "2014\-04\-23" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+delv \- DNS lookup and validation utility
+.SH "SYNOPSIS"
+.HP \w'\fBdelv\fR\ 'u
+\fBdelv\fR [@server] [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-a\ \fR\fB\fIanchor\-file\fR\fR] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIlevel\fR\fR] [\fB\-i\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [name] [type] [class] [queryopt...]
+.HP \w'\fBdelv\fR\ 'u
+\fBdelv\fR [\fB\-h\fR]
+.HP \w'\fBdelv\fR\ 'u
+\fBdelv\fR [\fB\-v\fR]
+.HP \w'\fBdelv\fR\ 'u
+\fBdelv\fR [queryopt...] [query...]
+.SH "DESCRIPTION"
+.PP
+\fBdelv\fR
+is a tool for sending DNS queries and validating the results, using the same internal resolver and validator logic as
+\fBnamed\fR\&.
+.PP
+\fBdelv\fR
+will send 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, and queries for DNSKEY, DS and DLV 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\&.
+.PP
+By default, responses are validated using built\-in DNSSEC trust anchor for the root zone ("\&.")\&. Records returned by
+\fBdelv\fR
+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
+\fBdelv\fR
+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\&.
+.PP
+Unless it is told to query a specific name server,
+\fBdelv\fR
+will try each of the servers listed in
+/etc/resolv\&.conf\&. If no usable server addresses are found,
+\fBdelv\fR
+will send queries to the localhost addresses (127\&.0\&.0\&.1 for IPv4, ::1 for IPv6)\&.
+.PP
+When no command line arguments or options are given,
+\fBdelv\fR
+will perform an NS query for "\&." (the root zone)\&.
+.SH "SIMPLE USAGE"
+.PP
+A typical invocation of
+\fBdelv\fR
+looks like:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ delv @server name type
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+where:
+.PP
+\fBserver\fR
+.RS 4
+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
+\fIserver\fR
+argument is a hostname,
+\fBdelv\fR
+resolves that name before querying that name server (note, however, that this initial lookup is
+\fInot\fR
+validated by DNSSEC)\&.
+.sp
+If no
+\fIserver\fR
+argument is provided,
+\fBdelv\fR
+consults
+/etc/resolv\&.conf; if an address is found there, it queries the name server at that address\&. If either of the
+\fB\-4\fR
+or
+\fB\-6\fR
+options are in use, then only addresses for the corresponding transport will be tried\&. If no usable addresses are found,
+\fBdelv\fR
+will send queries to the localhost addresses (127\&.0\&.0\&.1 for IPv4, ::1 for IPv6)\&.
+.RE
+.PP
+\fBname\fR
+.RS 4
+is the domain name to be looked up\&.
+.RE
+.PP
+\fBtype\fR
+.RS 4
+indicates what type of query is required \(em ANY, A, MX, etc\&.
+\fItype\fR
+can be any valid query type\&. If no
+\fItype\fR
+argument is supplied,
+\fBdelv\fR
+will perform a lookup for an A record\&.
+.RE
+.SH "OPTIONS"
+.PP
+\-a \fIanchor\-file\fR
+.RS 4
+Specifies a file from which to read DNSSEC trust anchors\&. The default is
+/etc/bind\&.keys, which is included with
+BIND
+9 and contains one or more trust anchors for the root zone ("\&.")\&.
+.sp
+Keys that do not match the root zone name are ignored\&. An alternate key name can be specified using the
+\fB+root=NAME\fR
+options\&. DNSSEC Lookaside Validation can also be turned on by using the
+\fB+dlv=NAME\fR
+to specify the name of a zone containing DLV records\&.
+.sp
+Note: When reading the trust anchor file,
+\fBdelv\fR
+treats
+\fBmanaged\-keys\fR
+statements and
+\fBtrusted\-keys\fR
+statements identically\&. That is, for a managed key, it is the
+\fIinitial\fR
+key that is trusted; RFC 5011 key management is not supported\&.
+\fBdelv\fR
+will not consult the managed\-keys database maintained by
+\fBnamed\fR\&. This means that if either of the keys in
+/etc/bind\&.keys
+is revoked and rolled over, it will be necessary to update
+/etc/bind\&.keys
+to use DNSSEC validation in
+\fBdelv\fR\&.
+.RE
+.PP
+\-b \fIaddress\fR
+.RS 4
+Sets the source IP address of the query to
+\fIaddress\fR\&. This must be a valid address on one of the host\*(Aqs network interfaces or "0\&.0\&.0\&.0" or "::"\&. An optional source port may be specified by appending "#<port>"
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Sets the query class for the requested data\&. Currently, only class "IN" is supported in
+\fBdelv\fR
+and any other value is ignored\&.
+.RE
+.PP
+\-d \fIlevel\fR
+.RS 4
+Set the systemwide debug level to
+\fBlevel\fR\&. The allowed range is from 0 to 99\&. The default is 0 (no debugging)\&. Debugging traces from
+\fBdelv\fR
+become more verbose as the debug level increases\&. See the
+\fB+mtrace\fR,
+\fB+rtrace\fR, and
+\fB+vtrace\fR
+options below for additional debugging details\&.
+.RE
+.PP
+\-h
+.RS 4
+Display the
+\fBdelv\fR
+help usage output and exit\&.
+.RE
+.PP
+\-i
+.RS 4
+Insecure mode\&. This disables internal DNSSEC validation\&. (Note, however, this does not set the CD bit on upstream queries\&. If the server being queried is performing DNSSEC validation, then it will not return invalid data; this can cause
+\fBdelv\fR
+to time out\&. When it is necessary to examine invalid data to debug a DNSSEC problem, use
+\fBdig +cd\fR\&.)
+.RE
+.PP
+\-m
+.RS 4
+Enables memory usage debugging\&.
+.RE
+.PP
+\-p \fIport#\fR
+.RS 4
+Specifies a destination port to use for queries instead of the standard DNS port number 53\&. This option would be used with a name server that has been configured to listen for queries on a non\-standard port number\&.
+.RE
+.PP
+\-q \fIname\fR
+.RS 4
+Sets the query name to
+\fIname\fR\&. While the query name can be specified without using the
+\fB\-q\fR, 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)\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Sets the query type to
+\fItype\fR, which can be any valid query type supported in BIND 9 except for zone transfer types AXFR and IXFR\&. As with
+\fB\-q\fR, this is useful to distinguish query name type or class when they are ambiguous\&. it is sometimes necessary to disambiguate names from types\&.
+.sp
+The default query type is "A", unless the
+\fB\-x\fR
+option is supplied to indicate a reverse lookup, in which case it is "PTR"\&.
+.RE
+.PP
+\-v
+.RS 4
+Print the
+\fBdelv\fR
+version and exit\&.
+.RE
+.PP
+\-x \fIaddr\fR
+.RS 4
+Performs a reverse lookup, mapping an addresses to a name\&.
+\fIaddr\fR
+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address\&. When
+\fB\-x\fR
+is used, there is no need to provide the
+\fIname\fR
+or
+\fItype\fR
+arguments\&.
+\fBdelv\fR
+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\&.
+.RE
+.PP
+\-4
+.RS 4
+Forces
+\fBdelv\fR
+to only use IPv4\&.
+.RE
+.PP
+\-6
+.RS 4
+Forces
+\fBdelv\fR
+to only use IPv6\&.
+.RE
+.SH "QUERY OPTIONS"
+.PP
+\fBdelv\fR
+provides a number of query options which affect the way results are displayed, and in some cases the way lookups are performed\&.
+.PP
+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
+\fB+keyword=value\fR\&. The query options are:
+.PP
+\fB+[no]cdflag\fR
+.RS 4
+Controls whether to set the CD (checking disabled) bit in queries sent by
+\fBdelv\fR\&. This may be useful when troubleshooting DNSSEC problems from behind a validating resolver\&. A validating resolver will block invalid responses, making it difficult to retrieve them for analysis\&. Setting the CD flag on queries will cause the resolver to return invalid responses, which
+\fBdelv\fR
+can then validate internally and report the errors in detail\&.
+.RE
+.PP
+\fB+[no]class\fR
+.RS 4
+Controls whether to display the CLASS when printing a record\&. The default is to display the CLASS\&.
+.RE
+.PP
+\fB+[no]ttl\fR
+.RS 4
+Controls whether to display the TTL when printing a record\&. The default is to display the TTL\&.
+.RE
+.PP
+\fB+[no]rtrace\fR
+.RS 4
+Toggle resolver fetch logging\&. This reports the name and type of each query sent by
+\fBdelv\fR
+in the process of carrying out the resolution and validation process: this includes including the original query and all subsequent queries to follow CNAMEs and to establish a chain of trust for DNSSEC validation\&.
+.sp
+This is equivalent to setting the debug level to 1 in the "resolver" logging category\&. Setting the systemwide debug level to 1 using the
+\fB\-d\fR
+option will product the same output (but will affect other logging categories as well)\&.
+.RE
+.PP
+\fB+[no]mtrace\fR
+.RS 4
+Toggle message logging\&. This produces a detailed dump of the responses received by
+\fBdelv\fR
+in the process of carrying out the resolution and validation process\&.
+.sp
+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
+\fB\-d\fR
+option will produce the same output (but will affect other logging categories as well)\&.
+.RE
+.PP
+\fB+[no]vtrace\fR
+.RS 4
+Toggle validation logging\&. This shows the internal process of the validator as it determines whether an answer is validly signed, unsigned, or invalid\&.
+.sp
+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
+\fB\-d\fR
+option will produce the same output (but will affect other logging categories as well)\&.
+.RE
+.PP
+\fB+[no]short\fR
+.RS 4
+Provide a terse answer\&. The default is to print the answer in a verbose form\&.
+.RE
+.PP
+\fB+[no]comments\fR
+.RS 4
+Toggle the display of comment lines in the output\&. The default is to print comments\&.
+.RE
+.PP
+\fB+[no]rrcomments\fR
+.RS 4
+Toggle 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\&.
+.RE
+.PP
+\fB+[no]crypto\fR
+.RS 4
+Toggle the display of cryptographic fields in DNSSEC records\&. The contents of these field 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 ]"\&.
+.RE
+.PP
+\fB+[no]trust\fR
+.RS 4
+Controls whether to display the trust level when printing a record\&. The default is to display the trust level\&.
+.RE
+.PP
+\fB+[no]split[=W]\fR
+.RS 4
+Split long hex\- or base64\-formatted fields in resource records into chunks of
+\fIW\fR
+characters (where
+\fIW\fR
+is rounded up to the nearest multiple of 4)\&.
+\fI+nosplit\fR
+or
+\fI+split=0\fR
+causes fields not to be split at all\&. The default is 56 characters, or 44 characters when multiline mode is active\&.
+.RE
+.PP
+\fB+[no]all\fR
+.RS 4
+Set or clear the display options
+\fB+[no]comments\fR,
+\fB+[no]rrcomments\fR, and
+\fB+[no]trust\fR
+as a group\&.
+.RE
+.PP
+\fB+[no]multiline\fR
+.RS 4
+Print 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
+\fBdelv\fR
+output\&.
+.RE
+.PP
+\fB+[no]dnssec\fR
+.RS 4
+Indicates whether to display RRSIG records in the
+\fBdelv\fR
+output\&. The default is to do so\&. Note that (unlike in
+\fBdig\fR) this does
+\fInot\fR
+control whether to request DNSSEC records or whether to validate them\&. DNSSEC records are always requested, and validation will always occur unless suppressed by the use of
+\fB\-i\fR
+or
+\fB+noroot\fR
+and
+\fB+nodlv\fR\&.
+.RE
+.PP
+\fB+[no]root[=ROOT]\fR
+.RS 4
+Indicates whether to perform conventional (non\-lookaside) 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
+\fB\-a\fR
+must be used to specify a file containing the key\&.
+.RE
+.PP
+\fB+[no]dlv[=DLV]\fR
+.RS 4
+Indicates whether to perform DNSSEC lookaside validation, and if so, specifies the name of the DLV trust anchor\&. The
+\fB\-a\fR
+option must also be used to specify a file containing the DLV key\&.
+.RE
+.PP
+\fB+[no]tcp\fR
+.RS 4
+Controls whether to use TCP when sending queries\&. The default is to use UDP unless a truncated response has been received\&.
+.RE
+.PP
+\fB+[no]unknownformat\fR
+.RS 4
+Print all RDATA in unknown RR type presentation format (RFC 3597)\&. The default is to print RDATA for known types in the type\*(Aqs presentation format\&.
+.RE
+.SH "FILES"
+.PP
+/etc/bind\&.keys
+.PP
+/etc/resolv\&.conf
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBnamed\fR(8),
+RFC4034,
+RFC4035,
+RFC4431,
+RFC5074,
+RFC5155\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/delv/delv.c b/bin/delv/delv.c
new file mode 100644
index 0000000..d0b5515
--- /dev/null
+++ b/bin/delv/delv.c
@@ -0,0 +1,1707 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+#include <bind.keys.h>
+
+#ifndef WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/lib.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#ifdef WIN32
+#include <isc/ntpaths.h>
+#endif
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <irs/resconf.h>
+#include <irs/netdb.h>
+
+#include <isccfg/log.h>
+#include <isccfg/namedconf.h>
+
+#include <dns/byaddr.h>
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/keytable.h>
+#include <dns/keyvalues.h>
+#include <dns/lib.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/result.h>
+#include <dns/secalg.h>
+#include <dns/view.h>
+
+#include <dst/dst.h>
+#include <dst/result.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;
+
+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,
+ dlv_validation = true;
+
+static bool use_tcp = false;
+
+static char *anchorfile = NULL;
+static char *trust_anchor = NULL;
+static char *dlv_anchor = NULL;
+static int trusted_keys = 0;
+
+static dns_fixedname_t afn, dfn;
+static dns_name_t *anchor_name = NULL, *dlv_name = NULL;
+
+/* Default bind.keys contents */
+static char anchortext[] = MANAGED_KEYS;
+
+/*
+ * 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) {
+ fputs(
+"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"
+" -x dot-notation (shortcut for reverse lookups)\n"
+" -d level (set debugging level)\n"
+" -a anchor-file (specify root and dlv trust anchors)\n"
+" -b address[#port] (bind to source address/port)\n"
+" -p port (specify port number)\n"
+" -q name (specify query name)\n"
+" -t type (specify query type)\n"
+" -c class (option included for compatibility;\n"
+" only IN is supported)\n"
+" -4 (use IPv4 query transport only)\n"
+" -6 (use IPv6 query transport only)\n"
+" -i (disable DNSSEC validation)\n"
+" -m (enable memory usage debugging)\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]crypto (Control display of cryptographic\n"
+" fields in records)\n"
+" +[no]multiline (Print records in an expanded format)\n"
+" +[no]comments (Control display of comment lines)\n"
+" +[no]rrcomments (Control display of per-record "
+ "comments)\n"
+" +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" format)\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]rtrace (Trace resolver fetches)\n"
+" +[no]mtrace (Trace messages received)\n"
+" +[no]vtrace (Trace validation process)\n"
+" +[no]dlv (DNSSEC lookaside validation anchor)\n"
+" +[no]root (DNSSEC validation trust anchor)\n"
+" +[no]dnssec (Display DNSSEC records)\n"
+" -h (print help and exit)\n"
+" -v (print version and exit)\n",
+ stderr);
+ exit(1);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+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;
+
+ result = isc_log_create(mctx, &lctx, &logconfig);
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't set up logging");
+
+ 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;
+
+ result = isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTPREFIX);
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't set up log channel 'stderr'");
+
+ isc_log_setdebuglevel(lctx, loglevel);
+
+ result = isc_log_settag(logconfig, ";; ");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't set log tag");
+
+ 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) {
+ result = isc_log_createchannel(logconfig, "resolver",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DEBUG(1),
+ &destination,
+ ISC_LOG_PRINTPREFIX);
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't set up log channel 'resolver'");
+
+ 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) {
+ result = isc_log_createchannel(logconfig, "validator",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DEBUG(3),
+ &destination,
+ ISC_LOG_PRINTPREFIX);
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't set up log channel 'validator'");
+
+ 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) {
+ result = isc_log_createchannel(logconfig, "messages",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DEBUG(10),
+ &destination,
+ ISC_LOG_PRINTPREFIX);
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't set up log channel 'messages'");
+
+ 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) {
+ const char *astr = "", *tstr = "";
+
+ REQUIRE(rdataset != NULL);
+
+ if (!showtrust || !dns_rdataset_isassociated(rdataset))
+ return;
+
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
+ astr = "negative response, ";
+
+ switch (rdataset->trust) {
+ case dns_trust_none:
+ tstr = "untrusted";
+ break;
+ case dns_trust_pending_additional:
+ tstr = "signed additional data, pending validation";
+ break;
+ case dns_trust_pending_answer:
+ tstr = "signed answer, pending validation";
+ break;
+ case dns_trust_additional:
+ tstr = "unsigned additional data";
+ break;
+ case dns_trust_glue:
+ tstr = "glue data";
+ break;
+ case dns_trust_answer:
+ if (root_validation || dlv_validation)
+ tstr = "unsigned answer";
+ else
+ tstr = "answer not validated";
+ break;
+ case dns_trust_authauthority:
+ tstr = "authority data";
+ break;
+ case dns_trust_authanswer:
+ tstr = "authoritative";
+ break;
+ case dns_trust_secure:
+ tstr = "fully validated";
+ break;
+ case dns_trust_ultimate:
+ tstr = "ultimate trust";
+ break;
+ }
+
+ printf("; %s%s\n", astr, tstr);
+}
+
+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)
+ putchar('\n');
+ print_status(rdataset);
+ trust = rdataset->trust;
+ first = false;
+ }
+
+ do {
+ t = isc_mem_get(mctx, len);
+ if (t == NULL)
+ return (ISC_R_NOMEMORY);
+
+ 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 {
+ if ((rdataset->attributes &
+ DNS_RDATASETATTR_NEGATIVE) != 0)
+ isc_buffer_putstr(&target, "; ");
+
+ result = dns_master_rdatasettotext(owner, rdataset,
+ style, &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 (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_stylecreate2(&style, styleflags,
+ 24, 24, 24, 32, 80, 8,
+ splitwidth, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 32, 40, 80, 8,
+ splitwidth, mctx);
+ else
+ result = dns_master_stylecreate2(&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 keystruct;
+ uint32_t flags, proto, alg;
+ const char *keystr, *keynamestr;
+ unsigned char keydata[4096];
+ isc_buffer_t keydatabuf;
+ 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, match_dlv = false;
+
+ keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+ CHECK(convert_name(&fkeyname, &keyname, keynamestr));
+
+ if (!root_validation && !dlv_validation)
+ return (ISC_R_SUCCESS);
+
+ if (anchor_name)
+ match_root = dns_name_equal(keyname, anchor_name);
+ if (dlv_name)
+ match_dlv = dns_name_equal(keyname, dlv_name);
+
+ if (!match_root && !match_dlv)
+ return (ISC_R_SUCCESS);
+ if ((!root_validation && match_root) || (!dlv_validation && match_dlv))
+ return (ISC_R_SUCCESS);
+
+ if (match_root)
+ delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s",
+ trust_anchor);
+ if (match_dlv)
+ delv_log(ISC_LOG_DEBUG(3), "adding DLV trust anchor %s",
+ dlv_anchor);
+
+ flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
+ proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
+ alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
+
+ 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 (flags > 0xffff)
+ CHECK(ISC_R_RANGE);
+ if (proto > 0xff)
+ CHECK(ISC_R_RANGE);
+ if (alg > 0xff)
+ CHECK(ISC_R_RANGE);
+
+ keystruct.flags = (uint16_t)flags;
+ keystruct.protocol = (uint8_t)proto;
+ keystruct.algorithm = (uint8_t)alg;
+
+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
+ keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
+ CHECK(isc_base64_decodestring(keystr, &keydatabuf));
+ isc_buffer_usedregion(&keydatabuf, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ CHECK(dns_rdata_fromstruct(NULL,
+ keystruct.common.rdclass,
+ keystruct.common.rdtype,
+ &keystruct, &rrdatabuf));
+
+ CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
+ keyname, &rrdatabuf));
+ trusted_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 *keys = NULL;
+ const cfg_obj_t *managed_keys = NULL;
+ cfg_obj_t *bindkeys = NULL;
+ const char *filename = anchorfile;
+
+ if (!root_validation && !dlv_validation)
+ return (ISC_R_SUCCESS);
+
+ if (filename == NULL) {
+#ifndef WIN32
+ filename = SYSCONFDIR "/bind.keys";
+#else
+ static char buf[MAX_PATH];
+ strlcpy(buf, isc_ntpaths_get(SYS_CONF_DIR), sizeof(buf));
+ strlcat(buf, "\\bind.keys", sizeof(buf));
+ filename = buf;
+#endif
+ }
+
+ if (trust_anchor == NULL) {
+ trust_anchor = isc_mem_strdup(mctx, ".");
+ if (trust_anchor == NULL)
+ fatal("out of memory");
+ }
+
+ if (trust_anchor != NULL)
+ CHECK(convert_name(&afn, &anchor_name, trust_anchor));
+ if (dlv_anchor != NULL)
+ CHECK(convert_name(&dfn, &dlv_name, dlv_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);
+ result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys,
+ &bindkeys);
+ if (result != ISC_R_SUCCESS)
+ fatal("Unable to parse built-in keys");
+ }
+
+ INSIST(bindkeys != NULL);
+ cfg_map_get(bindkeys, "trusted-keys", &keys);
+ cfg_map_get(bindkeys, "managed-keys", &managed_keys);
+
+ if (keys != NULL)
+ CHECK(load_keys(keys, client));
+ if (managed_keys != NULL)
+ CHECK(load_keys(managed_keys, client));
+ result = ISC_R_SUCCESS;
+
+ if (trusted_keys == 0)
+ fatal("No trusted keys were loaded");
+
+ if (dlv_validation)
+ dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor);
+
+ cleanup:
+ 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));
+ if (sa == NULL)
+ return (ISC_R_NOMEMORY);
+ 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));
+ if (sa == NULL)
+ return (ISC_R_NOMEMORY);
+ 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));
+ if (sa == NULL) {
+ result = ISC_R_NOMEMORY;
+ break;
+ }
+ 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));
+ if (sa == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ 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));
+ if (sa == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ 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 char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+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 option_store[256];
+ char *cmd, *value, *ptr;
+ bool state = true;
+
+ strlcpy(option_store, option, sizeof(option_store));
+ ptr = option_store;
+ cmd = next_token(&ptr,"=");
+ if (cmd == NULL) {
+ printf(";; Invalid option %s\n", option_store);
+ return;
+ }
+ value = ptr;
+ if (strncasecmp(cmd, "no", 2)==0) {
+ cmd += 2;
+ state = false;
+ }
+
+#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 && no_sigs)
+ break;
+ dlv_validation = state;
+ if (value != NULL) {
+ dlv_anchor = isc_mem_strdup(mctx, value);
+ if (dlv_anchor == NULL)
+ fatal("out of memory");
+ }
+ 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);
+ if (trust_anchor == NULL)
+ fatal("out of memory");
+ }
+ 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;
+ 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 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);
+ /* NOTREACHED */
+ case 'i':
+ no_sigs = true;
+ dlv_validation = false;
+ root_validation = false;
+ break;
+ case 'm':
+ /* handled in preparse_args() */
+ break;
+ case 'v':
+ fputs("delv " VERSION "\n", stderr);
+ exit(0);
+ /* NOTREACHED */
+ default:
+ INSIST(0);
+ }
+ 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);
+ if (anchorfile == NULL)
+ fatal("out of memory");
+ 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);
+ if (curqname == NULL)
+ fatal("out of memory");
+ 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 (curqname == NULL)
+ fatal("out of memory");
+ 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();
+ }
+ /* NOTREACHED */
+ 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];
+ }
+ }
+}
+
+/*
+ * 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 (curqname == NULL)
+ fatal("out of memory");
+ }
+ }
+ }
+
+ /*
+ * 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 (qname == NULL)
+ fatal("out of memory");
+
+ 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_createptrname2(&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;
+ dns_rdataset_t *rdataset;
+ dns_namelist_t namelist;
+ unsigned int resopt, clopt;
+ isc_appctx_t *actx = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+ dns_master_style_t *style = NULL;
+#ifndef WIN32
+ struct sigaction sa;
+#endif
+
+ progname = argv[0];
+ preparse_args(argc, argv);
+
+ argc--;
+ argv++;
+
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_lib_init failed: %d", result);
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create mctx");
+
+ CHECK(isc_appctx_create(mctx, &actx));
+ CHECK(isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr));
+ CHECK(isc_socketmgr_createinctx(mctx, actx, &socketmgr));
+ CHECK(isc_timermgr_createinctx(mctx, actx, &timermgr));
+
+ parse_args(argc, argv);
+
+ CHECK(setup_style(&style));
+
+ setup_logging(stderr);
+
+ CHECK(isc_app_ctxstart(actx));
+
+#ifndef WIN32
+ /* 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");
+#endif
+
+ /* Create client */
+ clopt = DNS_CLIENTCREATEOPT_USECACHE;
+ result = dns_client_createx2(mctx, actx, taskmgr, socketmgr, timermgr,
+ clopt, &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_ALLOWRUN | DNS_CLIENTRESOPT_NOCDFLAG;
+ if (no_sigs)
+ resopt |= DNS_CLIENTRESOPT_NODNSSEC;
+ if (!root_validation && !dlv_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)
+ delv_log(ISC_LOG_ERROR, "resolution failed: %s",
+ isc_result_totext(result));
+
+ 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 (dlv_anchor != NULL)
+ isc_mem_free(mctx, dlv_anchor);
+ 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_destroy(&client);
+ if (taskmgr != NULL)
+ isc_taskmgr_destroy(&taskmgr);
+ if (timermgr != NULL)
+ isc_timermgr_destroy(&timermgr);
+ if (socketmgr != NULL)
+ isc_socketmgr_destroy(&socketmgr);
+ if (actx != NULL)
+ isc_appctx_destroy(&actx);
+ if (lctx != NULL)
+ isc_log_destroy(&lctx);
+ isc_mem_detach(&mctx);
+
+ dns_lib_shutdown();
+
+ return (0);
+}
diff --git a/bin/delv/delv.docbook b/bin/delv/delv.docbook
new file mode 100644
index 0000000..f8c4f79
--- /dev/null
+++ b/bin/delv/delv.docbook
@@ -0,0 +1,701 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.delv">
+ <info>
+ <date>2014-04-23</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>delv</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>delv</refname>
+ <refpurpose>DNS lookup and validation utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>delv</command>
+ <arg choice="opt" rep="norepeat">@server</arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">anchor-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">address</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port#</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q <replaceable class="parameter">name</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x <replaceable class="parameter">addr</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat">name</arg>
+ <arg choice="opt" rep="norepeat">type</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="opt" rep="repeat">queryopt</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>delv</command>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>delv</command>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>delv</command>
+ <arg choice="opt" rep="repeat">queryopt</arg>
+ <arg choice="opt" rep="repeat">query</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>delv</command>
+ is a tool for sending
+ DNS queries and validating the results, using the same internal
+ resolver and validator logic as <command>named</command>.
+ </para>
+ <para>
+ <command>delv</command> will send 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, and queries for DNSKEY, DS and DLV 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.
+ </para>
+ <para>
+ By default, responses are validated using built-in DNSSEC trust
+ anchor for the root zone ("."). Records returned by
+ <command>delv</command> 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 <command>delv</command> 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.
+ </para>
+ <para>
+ Unless it is told to query a specific name server,
+ <command>delv</command> will try each of the servers listed in
+ <filename>/etc/resolv.conf</filename>. If no usable server
+ addresses are found, <command>delv</command> will send
+ queries to the localhost addresses (127.0.0.1 for IPv4, ::1
+ for IPv6).
+ </para>
+ <para>
+ When no command line arguments or options are given,
+ <command>delv</command> will perform an NS query for "."
+ (the root zone).
+ </para>
+ </refsection>
+
+ <refsection><info><title>SIMPLE USAGE</title></info>
+
+
+ <para>
+ A typical invocation of <command>delv</command> looks like:
+ <programlisting> delv @server name type </programlisting>
+ where:
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>server</constant></term>
+ <listitem>
+ <para>
+ 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
+ <parameter>server</parameter> argument is a hostname,
+ <command>delv</command> resolves that name before
+ querying that name server (note, however, that this
+ initial lookup is <emphasis>not</emphasis> validated
+ by DNSSEC).
+ </para>
+ <para>
+ If no <parameter>server</parameter> argument is
+ provided, <command>delv</command> consults
+ <filename>/etc/resolv.conf</filename>; if an
+ address is found there, it queries the name server at
+ that address. If either of the <option>-4</option> or
+ <option>-6</option> options are in use, then
+ only addresses for the corresponding transport
+ will be tried. If no usable addresses are found,
+ <command>delv</command> will send queries to
+ the localhost addresses (127.0.0.1 for IPv4,
+ ::1 for IPv6).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>name</constant></term>
+ <listitem>
+ <para>
+ is the domain name to be looked up.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type</constant></term>
+ <listitem>
+ <para>
+ indicates what type of query is required &mdash;
+ ANY, A, MX, etc.
+ <parameter>type</parameter> can be any valid query
+ type. If no
+ <parameter>type</parameter> argument is supplied,
+ <command>delv</command> will perform a lookup for an
+ A record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>-a <replaceable class="parameter">anchor-file</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a file from which to read DNSSEC trust anchors.
+ The default is <filename>/etc/bind.keys</filename>, which
+ is included with <acronym>BIND</acronym> 9 and contains
+ one or more trust anchors for the root zone (".").
+ </para>
+ <para>
+ Keys that do not match the root zone name are ignored.
+ An alternate key name can be specified using the
+ <option>+root=NAME</option> options. DNSSEC Lookaside
+ Validation can also be turned on by using the
+ <option>+dlv=NAME</option> to specify the name of a
+ zone containing DLV records.
+ </para>
+ <para>
+ Note: When reading the trust anchor file,
+ <command>delv</command> treats <option>managed-keys</option>
+ statements and <option>trusted-keys</option> statements
+ identically. That is, for a managed key, it is the
+ <emphasis>initial</emphasis> key that is trusted; RFC 5011
+ key management is not supported. <command>delv</command>
+ will not consult the managed-keys database maintained by
+ <command>named</command>. This means that if either of the
+ keys in <filename>/etc/bind.keys</filename> is revoked
+ and rolled over, it will be necessary to update
+ <filename>/etc/bind.keys</filename> to use DNSSEC
+ validation in <command>delv</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">address</replaceable></term>
+ <listitem>
+ <para>
+ Sets the source IP address of the query to
+ <parameter>address</parameter>. 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
+ "#&lt;port&gt;"
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Sets the query class for the requested data. Currently,
+ only class "IN" is supported in <command>delv</command>
+ and any other value is ignored.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Set the systemwide debug level to <option>level</option>.
+ The allowed range is from 0 to 99.
+ The default is 0 (no debugging).
+ Debugging traces from <command>delv</command> become
+ more verbose as the debug level increases.
+ See the <option>+mtrace</option>, <option>+rtrace</option>,
+ and <option>+vtrace</option> options below for additional
+ debugging details.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Display the <command>delv</command> help usage output and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i</term>
+ <listitem>
+ <para>
+ Insecure mode. This disables internal DNSSEC validation.
+ (Note, however, this does not set the CD bit on upstream
+ queries. If the server being queried is performing DNSSEC
+ validation, then it will not return invalid data; this
+ can cause <command>delv</command> to time out. When it
+ is necessary to examine invalid data to debug a DNSSEC
+ problem, use <command>dig +cd</command>.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m</term>
+ <listitem>
+ <para>
+ Enables memory usage debugging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port#</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a destination port to use for queries instead of
+ the standard DNS port number 53. This option would be used
+ with a name server that has been configured to listen
+ for queries on a non-standard port number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q <replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ Sets the query name to <parameter>name</parameter>.
+ 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).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Sets the query type to <parameter>type</parameter>, which
+ can be any valid query type supported in BIND 9 except
+ for zone transfer types AXFR and IXFR. As with
+ <option>-q</option>, this is useful to distinguish
+ query name type or class when they are ambiguous.
+ it is sometimes necessary to disambiguate names from types.
+ </para>
+ <para>
+ The default query type is "A", unless the <option>-x</option>
+ option is supplied to indicate a reverse lookup, in which case
+ it is "PTR".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the <command>delv</command> version and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x <replaceable class="parameter">addr</replaceable></term>
+ <listitem>
+ <para>
+ Performs a reverse lookup, mapping an addresses to
+ a name. <parameter>addr</parameter> is an IPv4 address in
+ dotted-decimal notation, or a colon-delimited IPv6 address.
+ When <option>-x</option> is used, there is no need to provide
+ the <parameter>name</parameter> or <parameter>type</parameter>
+ arguments. <command>delv</command> automatically performs a
+ lookup for a name like <literal>11.12.13.10.in-addr.arpa</literal>
+ and sets the query type to PTR. IPv6 addresses are looked up
+ using nibble format under the IP6.ARPA domain.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Forces <command>delv</command> to only use IPv4.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Forces <command>delv</command> to only use IPv6.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>QUERY OPTIONS</title></info>
+
+
+ <para><command>delv</command>
+ provides a number of query options which affect the way results are
+ displayed, and in some cases the way lookups are performed.
+ </para>
+
+ <para>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<literal>+</literal>). Some keywords set or reset an
+ option. These may be preceded by the string
+ <literal>no</literal> to negate the meaning of that keyword.
+ Other keywords assign values to options like the timeout interval.
+ They have the form <option>+keyword=value</option>.
+ The query options are:
+
+ <variablelist>
+ <varlistentry>
+ <term><option>+[no]cdflag</option></term>
+ <listitem>
+ <para>
+ Controls whether to set the CD (checking disabled) bit in
+ queries sent by <command>delv</command>. This may be useful
+ when troubleshooting DNSSEC problems from behind a validating
+ resolver. A validating resolver will block invalid responses,
+ making it difficult to retrieve them for analysis. Setting
+ the CD flag on queries will cause the resolver to return
+ invalid responses, which <command>delv</command> can then
+ validate internally and report the errors in detail.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]class</option></term>
+ <listitem>
+ <para>
+ Controls whether to display the CLASS when printing
+ a record. The default is to display the CLASS.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttl</option></term>
+ <listitem>
+ <para>
+ Controls whether to display the TTL when printing
+ a record. The default is to display the TTL.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rtrace</option></term>
+ <listitem>
+ <para>
+ Toggle resolver fetch logging. This reports the
+ name and type of each query sent by <command>delv</command>
+ in the process of carrying out the resolution and validation
+ process: this includes including the original query and
+ all subsequent queries to follow CNAMEs and to establish a
+ chain of trust for DNSSEC validation.
+ </para>
+ <para>
+ 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> option will
+ product the same output (but will affect other logging
+ categories as well).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]mtrace</option></term>
+ <listitem>
+ <para>
+ Toggle message logging. This produces a detailed dump of
+ the responses received by <command>delv</command> in the
+ process of carrying out the resolution and validation process.
+ </para>
+ <para>
+ 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> option will produce the same output
+ (but will affect other logging categories as well).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]vtrace</option></term>
+ <listitem>
+ <para>
+ Toggle validation logging. This shows the internal
+ process of the validator as it determines whether an
+ answer is validly signed, unsigned, or invalid.
+ </para>
+ <para>
+ 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> option will produce the same output
+ (but will affect other logging categories as well).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]short</option></term>
+ <listitem>
+ <para>
+ Provide a terse answer. The default is to print the answer in a
+ verbose form.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]comments</option></term>
+ <listitem>
+ <para>
+ Toggle the display of comment lines in the output. The default
+ is to print comments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rrcomments</option></term>
+ <listitem>
+ <para>
+ Toggle 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]crypto</option></term>
+ <listitem>
+ <para>
+ Toggle the display of cryptographic fields in DNSSEC records.
+ The contents of these field 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 ]".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]trust</option></term>
+ <listitem>
+ <para>
+ Controls whether to display the trust level when printing
+ a record. The default is to display the trust level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]split[=W]</option></term>
+ <listitem>
+ <para>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <parameter>W</parameter> characters
+ (where <parameter>W</parameter> is rounded up to the nearest
+ multiple of 4).
+ <parameter>+nosplit</parameter> or
+ <parameter>+split=0</parameter> causes fields not to be
+ split at all. The default is 56 characters, or 44 characters
+ when multiline mode is active.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]all</option></term>
+ <listitem>
+ <para>
+ Set or clear the display options
+ <option>+[no]comments</option>,
+ <option>+[no]rrcomments</option>, and
+ <option>+[no]trust</option> as a group.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]multiline</option></term>
+ <listitem>
+ <para>
+ Print 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 <command>delv</command>
+ output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]dnssec</option></term>
+ <listitem>
+ <para>
+ Indicates whether to display RRSIG records in the
+ <command>delv</command> output. The default is to
+ do so. Note that (unlike in <command>dig</command>)
+ this does <emphasis>not</emphasis> control whether to
+ request DNSSEC records or whether to validate them.
+ DNSSEC records are always requested, and validation
+ will always occur unless suppressed by the use of
+ <option>-i</option> or <option>+noroot</option> and
+ <option>+nodlv</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]root[=ROOT]</option></term>
+ <listitem>
+ <para>
+ Indicates whether to perform conventional (non-lookaside)
+ 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</option> must be used to specify a file
+ containing the key.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]dlv[=DLV]</option></term>
+ <listitem>
+ <para>
+ Indicates whether to perform DNSSEC lookaside validation,
+ and if so, specifies the name of the DLV trust anchor.
+ The <option>-a</option> option must also be used to specify
+ a file containing the DLV key.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]tcp</option></term>
+ <listitem>
+ <para>
+ Controls whether to use TCP when sending queries.
+ The default is to use UDP unless a truncated
+ response has been received.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]unknownformat</option></term>
+ <listitem>
+ <para>
+ Print 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.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/bind.keys</filename></para>
+ <para><filename>/etc/resolv.conf</filename></para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC4034</citetitle>,
+ <citetitle>RFC4035</citetitle>,
+ <citetitle>RFC4431</citetitle>,
+ <citetitle>RFC5074</citetitle>,
+ <citetitle>RFC5155</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/delv/delv.html b/bin/delv/delv.html
new file mode 100644
index 0000000..22c70cd
--- /dev/null
+++ b/bin/delv/delv.html
@@ -0,0 +1,592 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>delv</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.delv"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ delv
+ &#8212; DNS lookup and validation utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">delv</code>
+ [@server]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [<code class="option">-a <em class="replaceable"><code>anchor-file</code></em></code>]
+ [<code class="option">-b <em class="replaceable"><code>address</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-i</code>]
+ [<code class="option">-m</code>]
+ [<code class="option">-p <em class="replaceable"><code>port#</code></em></code>]
+ [<code class="option">-q <em class="replaceable"><code>name</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-x <em class="replaceable"><code>addr</code></em></code>]
+ [name]
+ [type]
+ [class]
+ [queryopt...]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">delv</code>
+ [<code class="option">-h</code>]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">delv</code>
+ [<code class="option">-v</code>]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">delv</code>
+ [queryopt...]
+ [query...]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>delv</strong></span>
+ is a tool for sending
+ DNS queries and validating the results, using the same internal
+ resolver and validator logic as <span class="command"><strong>named</strong></span>.
+ </p>
+ <p>
+ <span class="command"><strong>delv</strong></span> will send 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, and queries for DNSKEY, DS and DLV 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.
+ </p>
+ <p>
+ By default, responses are validated using built-in DNSSEC trust
+ anchor for the root zone ("."). Records returned by
+ <span class="command"><strong>delv</strong></span> 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 <span class="command"><strong>delv</strong></span> 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.
+ </p>
+ <p>
+ Unless it is told to query a specific name server,
+ <span class="command"><strong>delv</strong></span> will try each of the servers listed in
+ <code class="filename">/etc/resolv.conf</code>. If no usable server
+ addresses are found, <span class="command"><strong>delv</strong></span> will send
+ queries to the localhost addresses (127.0.0.1 for IPv4, ::1
+ for IPv6).
+ </p>
+ <p>
+ When no command line arguments or options are given,
+ <span class="command"><strong>delv</strong></span> will perform an NS query for "."
+ (the root zone).
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SIMPLE USAGE</h2>
+
+
+ <p>
+ A typical invocation of <span class="command"><strong>delv</strong></span> looks like:
+ </p>
+<pre class="programlisting"> delv @server name type </pre>
+<p>
+ where:
+
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">server</code></span></dt>
+<dd>
+ <p>
+ 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
+ <em class="parameter"><code>server</code></em> argument is a hostname,
+ <span class="command"><strong>delv</strong></span> resolves that name before
+ querying that name server (note, however, that this
+ initial lookup is <span class="emphasis"><em>not</em></span> validated
+ by DNSSEC).
+ </p>
+ <p>
+ If no <em class="parameter"><code>server</code></em> argument is
+ provided, <span class="command"><strong>delv</strong></span> consults
+ <code class="filename">/etc/resolv.conf</code>; if an
+ address is found there, it queries the name server at
+ that address. If either of the <code class="option">-4</code> or
+ <code class="option">-6</code> options are in use, then
+ only addresses for the corresponding transport
+ will be tried. If no usable addresses are found,
+ <span class="command"><strong>delv</strong></span> will send queries to
+ the localhost addresses (127.0.0.1 for IPv4,
+ ::1 for IPv6).
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">name</code></span></dt>
+<dd>
+ <p>
+ is the domain name to be looked up.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">type</code></span></dt>
+<dd>
+ <p>
+ indicates what type of query is required &#8212;
+ ANY, A, MX, etc.
+ <em class="parameter"><code>type</code></em> can be any valid query
+ type. If no
+ <em class="parameter"><code>type</code></em> argument is supplied,
+ <span class="command"><strong>delv</strong></span> will perform a lookup for an
+ A record.
+ </p>
+ </dd>
+</dl></div>
+<p>
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>OPTIONS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a <em class="replaceable"><code>anchor-file</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a file from which to read DNSSEC trust anchors.
+ The default is <code class="filename">/etc/bind.keys</code>, which
+ is included with <acronym class="acronym">BIND</acronym> 9 and contains
+ one or more trust anchors for the root zone (".").
+ </p>
+ <p>
+ Keys that do not match the root zone name are ignored.
+ An alternate key name can be specified using the
+ <code class="option">+root=NAME</code> options. DNSSEC Lookaside
+ Validation can also be turned on by using the
+ <code class="option">+dlv=NAME</code> to specify the name of a
+ zone containing DLV records.
+ </p>
+ <p>
+ Note: When reading the trust anchor file,
+ <span class="command"><strong>delv</strong></span> treats <code class="option">managed-keys</code>
+ statements and <code class="option">trusted-keys</code> statements
+ identically. That is, for a managed key, it is the
+ <span class="emphasis"><em>initial</em></span> key that is trusted; RFC 5011
+ key management is not supported. <span class="command"><strong>delv</strong></span>
+ will not consult the managed-keys database maintained by
+ <span class="command"><strong>named</strong></span>. This means that if either of the
+ keys in <code class="filename">/etc/bind.keys</code> is revoked
+ and rolled over, it will be necessary to update
+ <code class="filename">/etc/bind.keys</code> to use DNSSEC
+ validation in <span class="command"><strong>delv</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-b <em class="replaceable"><code>address</code></em></span></dt>
+<dd>
+ <p>
+ Sets the source IP address of the query to
+ <em class="parameter"><code>address</code></em>. 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
+ "#&lt;port&gt;"
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Sets the query class for the requested data. Currently,
+ only class "IN" is supported in <span class="command"><strong>delv</strong></span>
+ and any other value is ignored.
+ </p>
+ </dd>
+<dt><span class="term">-d <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Set the systemwide debug level to <code class="option">level</code>.
+ The allowed range is from 0 to 99.
+ The default is 0 (no debugging).
+ Debugging traces from <span class="command"><strong>delv</strong></span> become
+ more verbose as the debug level increases.
+ See the <code class="option">+mtrace</code>, <code class="option">+rtrace</code>,
+ and <code class="option">+vtrace</code> options below for additional
+ debugging details.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Display the <span class="command"><strong>delv</strong></span> help usage output and exit.
+ </p>
+ </dd>
+<dt><span class="term">-i</span></dt>
+<dd>
+ <p>
+ Insecure mode. This disables internal DNSSEC validation.
+ (Note, however, this does not set the CD bit on upstream
+ queries. If the server being queried is performing DNSSEC
+ validation, then it will not return invalid data; this
+ can cause <span class="command"><strong>delv</strong></span> to time out. When it
+ is necessary to examine invalid data to debug a DNSSEC
+ problem, use <span class="command"><strong>dig +cd</strong></span>.)
+ </p>
+ </dd>
+<dt><span class="term">-m</span></dt>
+<dd>
+ <p>
+ Enables memory usage debugging.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port#</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a destination port to use for queries instead of
+ the standard DNS port number 53. This option would be used
+ with a name server that has been configured to listen
+ for queries on a non-standard port number.
+ </p>
+ </dd>
+<dt><span class="term">-q <em class="replaceable"><code>name</code></em></span></dt>
+<dd>
+ <p>
+ Sets the query name to <em class="parameter"><code>name</code></em>.
+ While the query name can be specified without using the
+ <code class="option">-q</code>, 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).
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ Sets the query type to <em class="parameter"><code>type</code></em>, which
+ can be any valid query type supported in BIND 9 except
+ for zone transfer types AXFR and IXFR. As with
+ <code class="option">-q</code>, this is useful to distinguish
+ query name type or class when they are ambiguous.
+ it is sometimes necessary to disambiguate names from types.
+ </p>
+ <p>
+ The default query type is "A", unless the <code class="option">-x</code>
+ option is supplied to indicate a reverse lookup, in which case
+ it is "PTR".
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Print the <span class="command"><strong>delv</strong></span> version and exit.
+ </p>
+ </dd>
+<dt><span class="term">-x <em class="replaceable"><code>addr</code></em></span></dt>
+<dd>
+ <p>
+ Performs a reverse lookup, mapping an addresses to
+ a name. <em class="parameter"><code>addr</code></em> is an IPv4 address in
+ dotted-decimal notation, or a colon-delimited IPv6 address.
+ When <code class="option">-x</code> is used, there is no need to provide
+ the <em class="parameter"><code>name</code></em> or <em class="parameter"><code>type</code></em>
+ arguments. <span class="command"><strong>delv</strong></span> automatically performs a
+ lookup for a name like <code class="literal">11.12.13.10.in-addr.arpa</code>
+ and sets the query type to PTR. IPv6 addresses are looked up
+ using nibble format under the IP6.ARPA domain.
+ </p>
+ </dd>
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Forces <span class="command"><strong>delv</strong></span> to only use IPv4.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Forces <span class="command"><strong>delv</strong></span> to only use IPv6.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>QUERY OPTIONS</h2>
+
+
+ <p><span class="command"><strong>delv</strong></span>
+ provides a number of query options which affect the way results are
+ displayed, and in some cases the way lookups are performed.
+ </p>
+
+ <p>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<code class="literal">+</code>). Some keywords set or reset an
+ option. These may be preceded by the string
+ <code class="literal">no</code> to negate the meaning of that keyword.
+ Other keywords assign values to options like the timeout interval.
+ They have the form <code class="option">+keyword=value</code>.
+ The query options are:
+
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="option">+[no]cdflag</code></span></dt>
+<dd>
+ <p>
+ Controls whether to set the CD (checking disabled) bit in
+ queries sent by <span class="command"><strong>delv</strong></span>. This may be useful
+ when troubleshooting DNSSEC problems from behind a validating
+ resolver. A validating resolver will block invalid responses,
+ making it difficult to retrieve them for analysis. Setting
+ the CD flag on queries will cause the resolver to return
+ invalid responses, which <span class="command"><strong>delv</strong></span> can then
+ validate internally and report the errors in detail.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]class</code></span></dt>
+<dd>
+ <p>
+ Controls whether to display the CLASS when printing
+ a record. The default is to display the CLASS.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttl</code></span></dt>
+<dd>
+ <p>
+ Controls whether to display the TTL when printing
+ a record. The default is to display the TTL.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rtrace</code></span></dt>
+<dd>
+ <p>
+ Toggle resolver fetch logging. This reports the
+ name and type of each query sent by <span class="command"><strong>delv</strong></span>
+ in the process of carrying out the resolution and validation
+ process: this includes including the original query and
+ all subsequent queries to follow CNAMEs and to establish a
+ chain of trust for DNSSEC validation.
+ </p>
+ <p>
+ This is equivalent to setting the debug level to 1 in
+ the "resolver" logging category. Setting the systemwide
+ debug level to 1 using the <code class="option">-d</code> option will
+ product the same output (but will affect other logging
+ categories as well).
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]mtrace</code></span></dt>
+<dd>
+ <p>
+ Toggle message logging. This produces a detailed dump of
+ the responses received by <span class="command"><strong>delv</strong></span> in the
+ process of carrying out the resolution and validation process.
+ </p>
+ <p>
+ 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 <code class="option">-d</code> option will produce the same output
+ (but will affect other logging categories as well).
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]vtrace</code></span></dt>
+<dd>
+ <p>
+ Toggle validation logging. This shows the internal
+ process of the validator as it determines whether an
+ answer is validly signed, unsigned, or invalid.
+ </p>
+ <p>
+ 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 <code class="option">-d</code> option will produce the same output
+ (but will affect other logging categories as well).
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]short</code></span></dt>
+<dd>
+ <p>
+ Provide a terse answer. The default is to print the answer in a
+ verbose form.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]comments</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of comment lines in the output. The default
+ is to print comments.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rrcomments</code></span></dt>
+<dd>
+ <p>
+ Toggle 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]crypto</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of cryptographic fields in DNSSEC records.
+ The contents of these field 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 ]".
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]trust</code></span></dt>
+<dd>
+ <p>
+ Controls whether to display the trust level when printing
+ a record. The default is to display the trust level.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]split[=W]</code></span></dt>
+<dd>
+ <p>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <em class="parameter"><code>W</code></em> characters
+ (where <em class="parameter"><code>W</code></em> is rounded up to the nearest
+ multiple of 4).
+ <em class="parameter"><code>+nosplit</code></em> or
+ <em class="parameter"><code>+split=0</code></em> causes fields not to be
+ split at all. The default is 56 characters, or 44 characters
+ when multiline mode is active.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]all</code></span></dt>
+<dd>
+ <p>
+ Set or clear the display options
+ <code class="option">+[no]comments</code>,
+ <code class="option">+[no]rrcomments</code>, and
+ <code class="option">+[no]trust</code> as a group.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]multiline</code></span></dt>
+<dd>
+ <p>
+ Print 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 <span class="command"><strong>delv</strong></span>
+ output.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]dnssec</code></span></dt>
+<dd>
+ <p>
+ Indicates whether to display RRSIG records in the
+ <span class="command"><strong>delv</strong></span> output. The default is to
+ do so. Note that (unlike in <span class="command"><strong>dig</strong></span>)
+ this does <span class="emphasis"><em>not</em></span> control whether to
+ request DNSSEC records or whether to validate them.
+ DNSSEC records are always requested, and validation
+ will always occur unless suppressed by the use of
+ <code class="option">-i</code> or <code class="option">+noroot</code> and
+ <code class="option">+nodlv</code>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]root[=ROOT]</code></span></dt>
+<dd>
+ <p>
+ Indicates whether to perform conventional (non-lookaside)
+ 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 <code class="option">-a</code> must be used to specify a file
+ containing the key.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]dlv[=DLV]</code></span></dt>
+<dd>
+ <p>
+ Indicates whether to perform DNSSEC lookaside validation,
+ and if so, specifies the name of the DLV trust anchor.
+ The <code class="option">-a</code> option must also be used to specify
+ a file containing the DLV key.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]tcp</code></span></dt>
+<dd>
+ <p>
+ Controls whether to use TCP when sending queries.
+ The default is to use UDP unless a truncated
+ response has been received.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]unknownformat</code></span></dt>
+<dd>
+ <p>
+ Print 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.
+ </p>
+ </dd>
+</dl></div>
+<p>
+
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/bind.keys</code></p>
+ <p><code class="filename">/etc/resolv.conf</code></p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dig</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <em class="citetitle">RFC4034</em>,
+ <em class="citetitle">RFC4035</em>,
+ <em class="citetitle">RFC4431</em>,
+ <em class="citetitle">RFC5074</em>,
+ <em class="citetitle">RFC5155</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/delv/win32/delv.dsp.in b/bin/delv/win32/delv.dsp.in
new file mode 100644
index 0000000..403ec3e
--- /dev/null
+++ b/bin/delv/win32/delv.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="delv" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=delv - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "delv.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "delv.mak" CFG="delv - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "delv - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "delv - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "delv - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/irs/win32/Release/libirs.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/delv.exe"
+
+!ELSEIF "$(CFG)" == "delv - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/irs/win32/Debug/libirs.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/delv.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "delv - @PLATFORM@ Release"
+# Name "delv - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\delv.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/delv/win32/delv.dsw b/bin/delv/win32/delv.dsw
new file mode 100644
index 0000000..35c8608
--- /dev/null
+++ b/bin/delv/win32/delv.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "delv"=".\delv.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/delv/win32/delv.mak.in b/bin/delv/win32/delv.mak.in
new file mode 100644
index 0000000..3797f97
--- /dev/null
+++ b/bin/delv/win32/delv.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on delv.dsp
+!IF "$(CFG)" == ""
+CFG=delv - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to delv - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "delv - @PLATFORM@ Release" && "$(CFG)" != "delv - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "delv.mak" CFG="delv - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "delv - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "delv - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "delv - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "delv - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\delv.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\delv.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\delv.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\delv.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\delv.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/irs/win32/Release/libirs.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\delv.pdb" @MACHINE@ /out:"../../../Build/Release/delv.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\delv.obj"
+
+"..\..\..\Build\Release\delv.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "delv - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\delv.exe" "$(OUTDIR)\delv.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\delv.obj"
+ -@erase "$(INTDIR)\delv.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\delv.pdb"
+ -@erase "$(OUTDIR)\delv.bsc"
+ -@erase "..\..\..\Build\Debug\delv.exe"
+ -@erase "..\..\..\Build\Debug\delv.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\delv.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\delv.sbr"
+
+"$(OUTDIR)\delv.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/irs/win32/Debug/libirs.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\delv.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/delv.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\delv.obj"
+
+"..\..\..\Build\Debug\delv.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("delv.dep")
+!INCLUDE "delv.dep"
+!ELSE
+!MESSAGE Warning: cannot find "delv.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "delv - @PLATFORM@ Release" || "$(CFG)" == "delv - @PLATFORM@ Debug"
+SOURCE="..\delv.c"
+
+!IF "$(CFG)" == "delv - @PLATFORM@ Release"
+
+
+"$(INTDIR)\delv.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "delv - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\delv.obj" "$(INTDIR)\delv.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/delv/win32/delv.vcxproj.filters.in b/bin/delv/win32/delv.vcxproj.filters.in
new file mode 100644
index 0000000..c1af2f3
--- /dev/null
+++ b/bin/delv/win32/delv.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\delv.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/bin/delv/win32/delv.vcxproj.in b/bin/delv/win32/delv.vcxproj.in
new file mode 100644
index 0000000..da98e50
--- /dev/null
+++ b/bin/delv/win32/delv.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BE172EFE-C1DC-4812-BFB9-8C5F8ADB7E9F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>delv</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GEOIP_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\win32\include;..\..\..\lib\dns\include;..\..\..\lib\irs\win32\include;..\..\..\lib\irs\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\irs\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;libisccfg.lib;libirs.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GEOIP_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\win32\include;..\..\..\lib\dns\include;..\..\..\lib\irs\win32\include;..\..\..\lib\irs\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\irs\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;libisccfg.lib;libirs.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\delv.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/delv/win32/delv.vcxproj.user b/bin/delv/win32/delv.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/delv/win32/delv.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
new file mode 100644
index 0000000..a9830a9
--- /dev/null
+++ b/bin/dig/Makefile.in
@@ -0,0 +1,111 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+READLINE_LIB = @READLINE_LIB@
+
+CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} \
+ ${BIND9_INCLUDES} ${ISC_INCLUDES} \
+ ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @LIBIDN2_CFLAGS@ @DST_OPENSSL_INC@
+
+CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \
+ ${ISCCFGDEPLIBS} ${LWRESDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
+ ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@
+
+NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
+ ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@
+
+SUBDIRS =
+
+TARGETS = dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@
+
+OBJS = dig.@O@ dighost.@O@ host.@O@ nslookup.@O@
+
+UOBJS =
+
+SRCS = dig.c dighost.c host.c nslookup.c
+
+MANPAGES = dig.1 host.1 nslookup.1
+
+HTMLPAGES = dig.html host.html nslookup.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="nslookup.@O@ dighost.@O@ ${READLINE_LIB} ${UOBJS}"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+
+install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ dig@EXEEXT@ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ host@EXEEXT@ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ nslookup@EXEEXT@ ${DESTDIR}${bindir}
+ for m in ${MANPAGES}; do \
+ ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1 || exit 1; \
+ done
+
+uninstall::
+ for m in ${MANPAGES}; do \
+ rm -f ${DESTDIR}${mandir}/man1/$$m || exit 1; \
+ done
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/nslookup@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/host@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/dig@EXEEXT@
diff --git a/bin/dig/dig.1 b/bin/dig/dig.1
new file mode 100644
index 0000000..771f201
--- /dev/null
+++ b/bin/dig/dig.1
@@ -0,0 +1,803 @@
+.\" Copyright (C) 2000-2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dig
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-02-19
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DIG" "1" "2014\-02\-19" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dig \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP \w'\fBdig\fR\ 'u
+\fBdig\fR [@server] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIfilename\fR\fR] [\fB\-k\ \fR\fB\fIfilename\fR\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIname:key\fR\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [name] [type] [class] [queryopt...]
+.HP \w'\fBdig\fR\ 'u
+\fBdig\fR [\fB\-h\fR]
+.HP \w'\fBdig\fR\ 'u
+\fBdig\fR [global\-queryopt...] [query...]
+.SH "DESCRIPTION"
+.PP
+\fBdig\fR
+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
+\fBdig\fR
+to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output\&. Other lookup tools tend to have less functionality than
+\fBdig\fR\&.
+.PP
+Although
+\fBdig\fR
+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
+\fB\-h\fR
+option is given\&. Unlike earlier versions, the BIND 9 implementation of
+\fBdig\fR
+allows multiple lookups to be issued from the command line\&.
+.PP
+Unless it is told to query a specific name server,
+\fBdig\fR
+will try each of the servers listed in
+/etc/resolv\&.conf\&. If no usable server addresses are found,
+\fBdig\fR
+will send the query to the local host\&.
+.PP
+When no command line arguments or options are given,
+\fBdig\fR
+will perform an NS query for "\&." (the root)\&.
+.PP
+It is possible to set per\-user defaults for
+\fBdig\fR
+via
+${HOME}/\&.digrc\&. This file is read and any options in it are applied before the command line arguments\&.
+.PP
+The IN and CH class names overlap with the IN and CH top level domain names\&. Either use the
+\fB\-t\fR
+and
+\fB\-c\fR
+options to specify the type and class, use the
+\fB\-q\fR
+the specify the domain name, or use "IN\&." and "CH\&." when looking up these top level domains\&.
+.SH "SIMPLE USAGE"
+.PP
+A typical invocation of
+\fBdig\fR
+looks like:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ dig @server name type
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+where:
+.PP
+\fBserver\fR
+.RS 4
+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
+\fIserver\fR
+argument is a hostname,
+\fBdig\fR
+resolves that name before querying that name server\&.
+.sp
+If no
+\fIserver\fR
+argument is provided,
+\fBdig\fR
+consults
+/etc/resolv\&.conf; if an address is found there, it queries the name server at that address\&. If either of the
+\fB\-4\fR
+or
+\fB\-6\fR
+options are in use, then only addresses for the corresponding transport will be tried\&. If no usable addresses are found,
+\fBdig\fR
+will send the query to the local host\&. The reply from the name server that responds is displayed\&.
+.RE
+.PP
+\fBname\fR
+.RS 4
+is the name of the resource record that is to be looked up\&.
+.RE
+.PP
+\fBtype\fR
+.RS 4
+indicates what type of query is required \(em ANY, A, MX, SIG, etc\&.
+\fItype\fR
+can be any valid query type\&. If no
+\fItype\fR
+argument is supplied,
+\fBdig\fR
+will perform a lookup for an A record\&.
+.RE
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only\&.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only\&.
+.RE
+.PP
+\-b \fIaddress\fR\fI[#port]\fR
+.RS 4
+Set the source IP address of the query\&. The
+\fIaddress\fR
+must be a valid address on one of the host\*(Aqs network interfaces, or "0\&.0\&.0\&.0" or "::"\&. An optional port may be specified by appending "#<port>"
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Set the query class\&. The default
+\fIclass\fR
+is IN; other classes are HS for Hesiod records or CH for Chaosnet records\&.
+.RE
+.PP
+\-f \fIfile\fR
+.RS 4
+Batch mode:
+\fBdig\fR
+reads a list of lookup requests to process from the given
+\fIfile\fR\&. Each line in the file should be organized in the same way they would be presented as queries to
+\fBdig\fR
+using the command\-line interface\&.
+.RE
+.PP
+\-i
+.RS 4
+Do reverse IPv6 lookups using the obsolete RFC 1886 IP6\&.INT domain, which is no longer in use\&. Obsolete bit string label queries (RFC 2874) are not attempted\&.
+.RE
+.PP
+\-k \fIkeyfile\fR
+.RS 4
+Sign queries using TSIG using a key read from the given file\&. Key files can be generated using
+\fBtsig-keygen\fR(8)\&. When using TSIG authentication with
+\fBdig\fR, 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
+\fBkey\fR
+and
+\fBserver\fR
+statements in
+named\&.conf\&.
+.RE
+.PP
+\-m
+.RS 4
+Enable memory usage debugging\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Send the query to a non\-standard port on the server, instead of the default port 53\&. This option would be used to test a name server that has been configured to listen for queries on a non\-standard port number\&.
+.RE
+.PP
+\-q \fIname\fR
+.RS 4
+The domain name to query\&. This is useful to distinguish the
+\fIname\fR
+from other arguments\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+The resource record type to query\&. It 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
+\fB\-x\fR
+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
+\fItype\fR
+to
+ixfr=N\&. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone\*(Aqs SOA record was
+\fIN\fR\&.
+.sp
+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 will be displayed as described in RFC 3597\&.
+.RE
+.PP
+\-u
+.RS 4
+Print query times in microseconds instead of milliseconds\&.
+.RE
+.PP
+\-v
+.RS 4
+Print the version number and exit\&.
+.RE
+.PP
+\-x \fIaddr\fR
+.RS 4
+Simplified reverse lookups, for mapping addresses to names\&. The
+\fIaddr\fR
+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address\&. When the
+\fB\-x\fR
+is used, there is no need to provide the
+\fIname\fR,
+\fIclass\fR
+and
+\fItype\fR
+arguments\&.
+\fBdig\fR
+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 (but see also the
+\fB\-i\fR
+option)\&.
+.RE
+.PP
+\-y \fI[hmac:]\fR\fIkeyname:secret\fR
+.RS 4
+Sign queries using TSIG with the given authentication key\&.
+\fIkeyname\fR
+is the name of the key, and
+\fIsecret\fR
+is the base64 encoded shared secret\&.
+\fIhmac\fR
+is the name of the key algorithm; valid choices are
+hmac\-md5,
+hmac\-sha1,
+hmac\-sha224,
+hmac\-sha256,
+hmac\-sha384, or
+hmac\-sha512\&. If
+\fIhmac\fR
+is not specified, the default is
+hmac\-md5
+or if MD5 was disabled
+hmac\-sha256\&.
+.sp
+NOTE: You should use the
+\fB\-k\fR
+option and avoid the
+\fB\-y\fR
+option, because with
+\fB\-y\fR
+the shared secret is supplied as a command line argument in clear text\&. This may be visible in the output from
+\fBps\fR(1)
+or in a history file maintained by the user\*(Aqs shell\&.
+.RE
+.SH "QUERY OPTIONS"
+.PP
+\fBdig\fR
+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\&.
+.PP
+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
+\fB+keyword=value\fR\&. Keywords may be abbreviated, provided the abbreviation is unambiguous; for example,
++cd
+is equivalent to
++cdflag\&. The query options are:
+.PP
+\fB+[no]aaflag\fR
+.RS 4
+A synonym for
+\fI+[no]aaonly\fR\&.
+.RE
+.PP
+\fB+[no]aaonly\fR
+.RS 4
+Sets the "aa" flag in the query\&.
+.RE
+.PP
+\fB+[no]additional\fR
+.RS 4
+Display [do not display] the additional section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]adflag\fR
+.RS 4
+Set [do 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 indicate that some part of the answer was insecure or not validated\&. This bit is set by default\&.
+.RE
+.PP
+\fB+[no]all\fR
+.RS 4
+Set or clear all display flags\&.
+.RE
+.PP
+\fB+[no]answer\fR
+.RS 4
+Display [do not display] the answer section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]authority\fR
+.RS 4
+Display [do not display] the authority section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]badcookie\fR
+.RS 4
+Retry lookup with the new server cookie if a BADCOOKIE response is received\&.
+.RE
+.PP
+\fB+[no]besteffort\fR
+.RS 4
+Attempt to display the contents of messages which are malformed\&. The default is to not display malformed answers\&.
+.RE
+.PP
+\fB+bufsize=B\fR
+.RS 4
+Set the UDP message buffer size advertised using EDNS0 to
+\fIB\fR
+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 will cause a EDNS query to be sent\&.
+.RE
+.PP
+\fB+[no]cdflag\fR
+.RS 4
+Set [do not set] the CD (checking disabled) bit in the query\&. This requests the server to not perform DNSSEC validation of responses\&.
+.RE
+.PP
+\fB+[no]class\fR
+.RS 4
+Display [do not display] the CLASS when printing the record\&.
+.RE
+.PP
+\fB+[no]cmd\fR
+.RS 4
+Toggles the printing of the initial comment in the output identifying the version of
+\fBdig\fR
+and the query options that have been applied\&. This comment is printed by default\&.
+.RE
+.PP
+\fB+[no]comments\fR
+.RS 4
+Toggle the display of comment lines in the output\&. The default is to print comments\&.
+.RE
+.PP
+\fB+[no]cookie\fR\fB[=####]\fR
+.RS 4
+Send a COOKIE EDNS option, with optional value\&. Replaying a COOKIE from a previous response will allow the server to identify a previous client\&. The default is
+\fB+cookie\fR\&.
+.sp
+\fB+cookie\fR
+is also set when +trace is set to better emulate the default queries from a nameserver\&.
+.RE
+.PP
+\fB+[no]crypto\fR
+.RS 4
+Toggle the display of cryptographic fields in DNSSEC records\&. The contents of these field 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 ]"\&.
+.RE
+.PP
+\fB+[no]defname\fR
+.RS 4
+Deprecated, treated as a synonym for
+\fI+[no]search\fR
+.RE
+.PP
+\fB+[no]dnssec\fR
+.RS 4
+Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query\&.
+.RE
+.PP
+\fB+domain=somename\fR
+.RS 4
+Set the search list to contain the single domain
+\fIsomename\fR, as if specified in a
+\fBdomain\fR
+directive in
+/etc/resolv\&.conf, and enable search list processing as if the
+\fI+search\fR
+option were given\&.
+.RE
+.PP
+\fB+dscp=value\fR
+.RS 4
+Set the DSCP code point to be used when sending the query\&. Valid DSCP code points are in the range [0\&.\&.63]\&. By default no code point is explicitly set\&.
+.RE
+.PP
+\fB+[no]edns[=#]\fR
+.RS 4
+Specify the EDNS version to query with\&. Valid values are 0 to 255\&. Setting the EDNS version will cause a EDNS query to be sent\&.
+\fB+noedns\fR
+clears the remembered EDNS version\&. EDNS is set to 0 by default\&.
+.RE
+.PP
+\fB+[no]ednsflags[=#]\fR
+.RS 4
+Set 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) will silently be ignored\&. By default, no Z bits are set\&.
+.RE
+.PP
+\fB+[no]ednsnegotiation\fR
+.RS 4
+Enable / disable EDNS version negotiation\&. By default EDNS version negotiation is enabled\&.
+.RE
+.PP
+\fB+[no]ednsopt[=code[:value]]\fR
+.RS 4
+Specify EDNS option with code point
+\fBcode\fR
+and optionally payload of
+\fBvalue\fR
+as a hexadecimal string\&.
+\fBcode\fR
+can be either an EDNS option name (for example,
+NSID
+or
+ECS), or an arbitrary numeric value\&.
+\fB+noednsopt\fR
+clears the EDNS options to be sent\&.
+.RE
+.PP
+\fB+[no]expire\fR
+.RS 4
+Send an EDNS Expire option\&.
+.RE
+.PP
+\fB+[no]fail\fR
+.RS 4
+Do not try the next server if you receive a SERVFAIL\&. The default is to not try the next server which is the reverse of normal stub resolver behavior\&.
+.RE
+.PP
+\fB+[no]header\-only\fR
+.RS 4
+Send 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\&.
+.RE
+.PP
+\fB+[no]identify\fR
+.RS 4
+Show [or do not show] the IP address and port number that supplied the answer when the
+\fI+short\fR
+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\&.
+.RE
+.PP
+\fB+[no]idnin\fR
+.RS 4
+Process [do 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\&.
+.RE
+.PP
+\fB+[no]idnout\fR
+.RS 4
+Convert [do not convert] puny code on output\&. This requires IDN SUPPORT to have been enabled at compile time\&. The default is to convert output\&.
+.RE
+.PP
+\fB+[no]ignore\fR
+.RS 4
+Ignore truncation in UDP responses instead of retrying with TCP\&. By default, TCP retries are performed\&.
+.RE
+.PP
+\fB+[no]keepopen\fR
+.RS 4
+Keep the TCP socket open between queries and reuse it rather than creating a new TCP socket for each lookup\&. The default is
+\fB+nokeepopen\fR\&.
+.RE
+.PP
+\fB+[no]mapped\fR
+.RS 4
+Allow mapped IPv4 over IPv6 addresses to be used\&. The default is
+\fB+mapped\fR\&.
+.RE
+.PP
+\fB+[no]multiline\fR
+.RS 4
+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
+\fBdig\fR
+output\&.
+.RE
+.PP
+\fB+ndots=D\fR
+.RS 4
+Set the number of dots that have to appear in
+\fIname\fR
+to
+\fID\fR
+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 will be searched for in the domains listed in the
+\fBsearch\fR
+or
+\fBdomain\fR
+directive in
+/etc/resolv\&.conf
+if
+\fB+search\fR
+is set\&.
+.RE
+.PP
+\fB+[no]nsid\fR
+.RS 4
+Include an EDNS name server ID request when sending a query\&.
+.RE
+.PP
+\fB+[no]nssearch\fR
+.RS 4
+When this option is set,
+\fBdig\fR
+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\&.
+.RE
+.PP
+\fB+[no]onesoa\fR
+.RS 4
+Print only one (starting) SOA record when performing an AXFR\&. The default is to print both the starting and ending SOA records\&.
+.RE
+.PP
+\fB+[no]opcode=value\fR
+.RS 4
+Set [restore] the DNS message opcode to the specified value\&. The default value is QUERY (0)\&.
+.RE
+.PP
+\fB+[no]qr\fR
+.RS 4
+Print [do not print] the query as it is sent\&. By default, the query is not printed\&.
+.RE
+.PP
+\fB+[no]question\fR
+.RS 4
+Print [do not print] the question section of a query when an answer is returned\&. The default is to print the question section as a comment\&.
+.RE
+.PP
+\fB+[no]rdflag\fR
+.RS 4
+A synonym for
+\fI+[no]recurse\fR\&.
+.RE
+.PP
+\fB+[no]recurse\fR
+.RS 4
+Toggle the setting of the RD (recursion desired) bit in the query\&. This bit is set by default, which means
+\fBdig\fR
+normally sends recursive queries\&. Recursion is automatically disabled when the
+\fI+nssearch\fR
+or
+\fI+trace\fR
+query options are used\&.
+.RE
+.PP
+\fB+retry=T\fR
+.RS 4
+Sets the number of times to retry UDP queries to server to
+\fIT\fR
+instead of the default, 2\&. Unlike
+\fI+tries\fR, this does not include the initial query\&.
+.RE
+.PP
+\fB+[no]rrcomments\fR
+.RS 4
+Toggle 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\&.
+.RE
+.PP
+\fB+[no]search\fR
+.RS 4
+Use [do 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\&.
+.sp
+\*(Aqndots\*(Aq from
+resolv\&.conf
+(default 1) which may be overridden by
+\fI+ndots\fR
+determines if the name will be treated as relative or not and hence whether a search is eventually performed or not\&.
+.RE
+.PP
+\fB+[no]short\fR
+.RS 4
+Provide a terse answer\&. The default is to print the answer in a verbose form\&.
+.RE
+.PP
+\fB+[no]showsearch\fR
+.RS 4
+Perform [do not perform] a search showing intermediate results\&.
+.RE
+.PP
+\fB+[no]sigchase\fR
+.RS 4
+Chase DNSSEC signature chains\&. Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use
+\fBdelv\fR
+instead\&.
+.RE
+.PP
+\fB+split=W\fR
+.RS 4
+Split long hex\- or base64\-formatted fields in resource records into chunks of
+\fIW\fR
+characters (where
+\fIW\fR
+is rounded up to the nearest multiple of 4)\&.
+\fI+nosplit\fR
+or
+\fI+split=0\fR
+causes fields not to be split at all\&. The default is 56 characters, or 44 characters when multiline mode is active\&.
+.RE
+.PP
+\fB+[no]stats\fR
+.RS 4
+This query option toggles the printing of statistics: when the query was made, the size of the reply and so on\&. The default behavior is to print the query statistics\&.
+.RE
+.PP
+\fB+[no]subnet=addr[/prefix\-length]\fR
+.RS 4
+Send (don\*(Aqt send) an EDNS Client Subnet option with the specified IP address or network prefix\&.
+.sp
+\fBdig +subnet=0\&.0\&.0\&.0/0\fR, or simply
+\fBdig +subnet=0\fR
+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\*(Aqs address information must
+\fInot\fR
+be used when resolving this query\&.
+.RE
+.PP
+\fB+[no]tcp\fR
+.RS 4
+Use [do not 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\&.
+.RE
+.PP
+\fB+timeout=T\fR
+.RS 4
+Sets the timeout for a query to
+\fIT\fR
+seconds\&. The default timeout is 5 seconds\&. An attempt to set
+\fIT\fR
+to less than 1 will result in a query timeout of 1 second being applied\&.
+.RE
+.PP
+\fB+[no]topdown\fR
+.RS 4
+When chasing DNSSEC signature chains perform a top\-down validation\&. Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use
+\fBdelv\fR
+instead\&.
+.RE
+.PP
+\fB+[no]trace\fR
+.RS 4
+Toggle 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,
+\fBdig\fR
+makes iterative queries to resolve the name being looked up\&. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup\&.
+.sp
+If @server is also specified, it affects only the initial query for the root zone name servers\&.
+.sp
+\fB+dnssec\fR
+is also set when +trace is set to better emulate the default queries from a nameserver\&.
+.RE
+.PP
+\fB+tries=T\fR
+.RS 4
+Sets the number of times to try UDP queries to server to
+\fIT\fR
+instead of the default, 3\&. If
+\fIT\fR
+is less than or equal to zero, the number of tries is silently rounded up to 1\&.
+.RE
+.PP
+\fB+trusted\-key=####\fR
+.RS 4
+Specifies a file containing trusted keys to be used with
+\fB+sigchase\fR\&. Each DNSKEY record must be on its own line\&.
+.sp
+If not specified,
+\fBdig\fR
+will look for
+/etc/trusted\-key\&.key
+then
+trusted\-key\&.key
+in the current directory\&.
+.sp
+Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use
+\fBdelv\fR
+instead\&.
+.RE
+.PP
+\fB+[no]ttlid\fR
+.RS 4
+Display [do not display] the TTL when printing the record\&.
+.RE
+.PP
+\fB+[no]ttlunits\fR
+.RS 4
+Display [do not display] the TTL in friendly human\-readable time units of "s", "m", "h", "d", and "w", representing seconds, minutes, hours, days and weeks\&. Implies +ttlid\&.
+.RE
+.PP
+\fB+[no]unknownformat\fR
+.RS 4
+Print all RDATA in unknown RR type presentation format (RFC 3597)\&. The default is to print RDATA for known types in the type\*(Aqs presentation format\&.
+.RE
+.PP
+\fB+[no]vc\fR
+.RS 4
+Use [do not use] TCP when querying name servers\&. This alternate syntax to
+\fI+[no]tcp\fR
+is provided for backwards compatibility\&. The "vc" stands for "virtual circuit"\&.
+.RE
+.PP
+\fB+[no]zflag\fR
+.RS 4
+Set [do not set] the last unassigned DNS header flag in a DNS query\&. This flag is off by default\&.
+.RE
+.SH "MULTIPLE QUERIES"
+.PP
+The BIND 9 implementation of
+\fBdig \fR
+supports specifying multiple queries on the command line (in addition to supporting the
+\fB\-f\fR
+batch file option)\&. Each of those queries can be supplied with its own set of flags, options and query options\&.
+.PP
+In this case, each
+\fIquery\fR
+argument represent 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\&.
+.PP
+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 the
+\fB+[no]cmd\fR
+option) can be overridden by a query\-specific set of query options\&. For example:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+dig +qr www\&.isc\&.org any \-x 127\&.0\&.0\&.1 isc\&.org ns +noqr
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+shows how
+\fBdig\fR
+could 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
+\fI+qr\fR
+is applied, so that
+\fBdig\fR
+shows the initial query it made for each lookup\&. The final query has a local query option of
+\fI+noqr\fR
+which means that
+\fBdig\fR
+will not print the initial query when it looks up the NS records for
+isc\&.org\&.
+.SH "IDN SUPPORT"
+.PP
+If
+\fBdig\fR
+has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names\&.
+\fBdig\fR
+appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server\&. If you\*(Aqd like to turn off the IDN support for some reason, use parameters
+\fI+noidnin\fR
+and
+\fI+noidnout\fR\&.
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.PP
+${HOME}/\&.digrc
+.SH "SEE ALSO"
+.PP
+\fBdelv\fR(1),
+\fBhost\fR(1),
+\fBnamed\fR(8),
+\fBdnssec-keygen\fR(8),
+RFC 1035\&.
+.SH "BUGS"
+.PP
+There are probably too many query options\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
new file mode 100644
index 0000000..39f74be
--- /dev/null
+++ b/bin/dig/dig.c
@@ -0,0 +1,2293 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <isc/app.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <pk11/site.h>
+
+#include <dns/byaddr.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/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#include <dig/dig.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 char *batchname = NULL;
+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,
+ ip6_int = false, plusquest = false, pluscomm = false,
+ multiline = false, nottl = false, noclass = false,
+ onesoa = false, use_usec = false,
+ nocrypto = false, ttlunits = false,
+ ipv4only = false, ipv6only = false;
+static uint32_t splitwidth = 0xffffffff;
+
+/*% rrcomments are neither explicitly enabled nor disabled by default */
+static int rrcomments = 0;
+
+/*% 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) {
+ fputs(
+"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", fp);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ print_usage(stderr);
+ fputs("\nUse \"dig -h\" (or \"dig -h | more\") "
+ "for complete list of options\n", stderr);
+ exit(1);
+}
+
+/*% version */
+static void
+version(void) {
+ fputs("DiG " VERSION "\n", stderr);
+}
+
+/*% help */
+static void
+help(void) {
+ print_usage(stdout);
+ fputs(
+"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"
+" -i (use IP6.INT for IPv6 reverse lookups)\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"
+" -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"
+" +[no]comments (Control display of comment lines)\n"
+" +[no]cookie (Add a COOKIE option to the request)\n"
+" +[no]crypto (Control display of cryptographic "
+ "fields in records)\n"
+" +[no]defname (Use search list (+[no]search))\n"
+" +[no]dnssec (Request DNSSEC records)\n"
+" +domain=### (Set default domainname)\n"
+" +[no]dscp[=###] (Set the DSCP value to ### [0..63])\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]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]identify (ID responders in short answers)\n"
+" +[no]idnin (Parse IDN names)\n"
+" +[no]idnout (Convert IDN response)\n"
+" +[no]ignore (Don't revert to TCP for TC responses.)\n"
+" +[no]keepopen (Keep the TCP socket open between queries)\n"
+" +[no]mapped (Allow mapped IPv4 over IPv6)\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"
+" +[no]qr (Print question before sending)\n"
+" +[no]question (Control display of question section)\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 answer)\n"
+" +[no]showsearch (Search with intermediate results)\n"
+#ifdef DIG_SIGCHASE
+" +[no]sigchase (Chase DNSSEC signatures)\n"
+#endif
+" +[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]tcp (TCP mode (+[no]vc))\n"
+" +timeout=### (Set query timeout) [5]\n"
+#if defined(DIG_SIGCHASE) && DIG_SIGCHASE_TD
+" +[no]topdown (Do +sigchase in top-down mode)\n"
+#endif
+" +[no]trace (Trace delegation down from root [+dnssec])\n"
+#ifdef DIG_SIGCHASE
+" +trusted-key=#### (Trusted Key to use with +sigchase)\n"
+#endif
+" +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]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",
+ stdout);
+}
+
+/*%
+ * 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;
+#ifdef WIN32
+ wchar_t time_str[100];
+#else
+ char time_str[100];
+#endif
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+
+ if (query->lookup->stats && !short_form) {
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ if (use_usec)
+ printf(";; Query time: %ld usec\n", (long) diff);
+ else
+ printf(";; Query time: %ld msec\n", (long) diff / 1000);
+ printf(";; SERVER: %s(%s)\n", fromtext, query->servname);
+ time(&tnow);
+#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32)
+ (void)localtime_r(&tnow, &tmnow);
+#else
+ tmnow = *localtime(&tnow);
+#endif
+
+#ifdef WIN32
+ /*
+ * On Windows, time zone name ("%Z") may be a localized
+ * wide-character string, which strftime() handles incorrectly.
+ */
+ if (wcsftime(time_str, sizeof(time_str)/sizeof(time_str[0]),
+ L"%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U)
+ printf(";; WHEN: %ls\n", time_str);
+#else
+ if (strftime(time_str, sizeof(time_str),
+ "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U)
+ printf(";; WHEN: %s\n", time_str);
+#endif
+ 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 && !short_form) {
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ if (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 (rrcomments > 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ if (nocrypto)
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ if (query->lookup->print_unknown_format)
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ 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 (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
+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);
+}
+#ifdef DIG_SIGCHASE
+static isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ isc_result_t result;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+
+ if (rdataset == NULL || owner_name == NULL || target == NULL)
+ return(false);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (ttlunits)
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ if (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ if (nocrypto)
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ /* Turn on rrcomments if explicitly enabled */
+ if (rrcomments > 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ if (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 if not explicitly disabled */
+ if (rrcomments >= 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 24, 32, 80, 8,
+ splitwidth, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 32, 40, 80, 8,
+ splitwidth, mctx);
+ else
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 32, 40, 48, 80, 8,
+ splitwidth, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ result = dns_master_rdatasettotext(owner_name, rdataset, style, target);
+
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+
+ return(result);
+}
+#endif
+
+static bool
+isdotlocal(dns_message_t *msg) {
+ isc_result_t result;
+ static unsigned char local_ndata[] = { "\005local\0" };
+ 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, 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;
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ 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 (rrcomments > 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ if (ttlunits)
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ 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_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 (rrcomments >= 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 24, 32, 80, 8,
+ splitwidth, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 32, 40, 80, 8,
+ splitwidth, mctx);
+ else
+ result = dns_master_stylecreate2(&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)
+ fputs(query->lookup->cmdline, stdout);
+ query->lookup->cmdline[0]=0;
+ }
+ debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders",
+ query->lookup->comments ? "comments" : "nocomments",
+ short_form ? "short_form" : "long_form");
+
+ flags = 0;
+ if (!headers) {
+ flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+ if (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;
+
+ result = isc_buffer_allocate(mctx, &buf, len);
+ check_result(result, "isc_buffer_allocate");
+
+ if (query->lookup->comments && !short_form) {
+ if (query->lookup->cmdline[0] != 0)
+ 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) {
+ result = dns_message_pseudosectiontotext(msg,
+ DNS_PSEUDOSECTION_OPT,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+buftoosmall:
+ len += OUTPUTBUF;
+ isc_buffer_free(&buf);
+ result = isc_buffer_allocate(mctx, &buf, len);
+ if (result == ISC_R_SUCCESS)
+ goto repopulate_buffer;
+ else
+ goto cleanup;
+ }
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ }
+
+ if (query->lookup->section_question && headers) {
+ if (!short_form) {
+ 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) {
+ 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 {
+ 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) {
+ 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) {
+ 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)
+ printf("\n");
+
+ printf("%.*s", (int)isc_buffer_usedlength(buf),
+ (char *)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+
+cleanup:
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+ 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 " VERSION " <<>>",
+ first?"\n":"");
+ 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));
+ }
+ }
+}
+
+/*%
+ * 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 void
+plus_option(const char *option, bool is_batchfile,
+ dig_lookup_t *lookup)
+{
+ isc_result_t result;
+ char option_store[256];
+ char *cmd, *value, *ptr, *code;
+ uint32_t num;
+ bool state = true;
+ size_t n;
+
+ strlcpy(option_store, option, sizeof(option_store));
+ ptr = option_store;
+ cmd = next_token(&ptr, "=");
+ if (cmd == NULL) {
+ printf(";; Invalid option %s\n", option_store);
+ return;
+ }
+ value = ptr;
+ if (strncasecmp(cmd, "no", 2)==0) {
+ cmd += 2;
+ state = false;
+ }
+
+#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)
+
+ 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 (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ result = parse_uint(&num, value, COMMSIZE,
+ "buffer size");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse buffer size");
+ 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");
+ 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 = 0;
+ lookup->sendcookie = state;
+ if (value != NULL) {
+ n = strlcpy(hexcookie, value,
+ sizeof(hexcookie));
+ if (n >= sizeof(hexcookie))
+ fatal("COOKIE data too large");
+ lookup->cookie = hexcookie;
+ } else
+ lookup->cookie = NULL;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("crypto");
+ 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': /* dnssec */
+ FULLCHECK("dnssec");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ lookup->dnssec = state;
+ break;
+ case 'o': /* domain */
+ FULLCHECK("domain");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ strlcpy(domainopt, value, sizeof(domainopt));
+ break;
+ case 's': /* dscp */
+ FULLCHECK("dscp");
+ if (!state) {
+ lookup->dscp = -1;
+ break;
+ }
+ if (value == NULL)
+ goto need_value;
+ result = parse_uint(&num, value, 0x3f, "DSCP");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse DSCP value");
+ lookup->dscp = num;
+ 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 = 0;
+ break;
+ }
+ result = parse_uint(&num,
+ value,
+ 255,
+ "edns");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse "
+ "edns");
+ 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)
+ fatal("Couldn't parse "
+ "ednsflags");
+ 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(value,
+ ":");
+ }
+ if (code == NULL) {
+ fatal("ednsopt no "
+ "code point "
+ "specified");
+ }
+ value = strtok(NULL, "\0");
+ save_opt(lookup, code, value);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'x':
+ FULLCHECK("expire");
+ lookup->expire = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'f': /* fail */
+ FULLCHECK("fail");
+ lookup->servfail_stops = state;
+ break;
+ case 'h':
+ FULLCHECK("header-only");
+ lookup->header_only = state;
+ 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 WITH_IDN_SUPPORT
+ fprintf(stderr, ";; IDN input support"
+ " not enabled\n");
+#else
+ lookup->idnin = state;
+#endif
+ break;
+ case 'o':
+ FULLCHECK("idnout");
+#ifndef WITH_IDN_OUT_SUPPORT
+ fprintf(stderr, ";; IDN output support"
+ " not enabled\n");
+#else
+ lookup->idnout = state;
+#endif
+ 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':
+ FULLCHECK("keepopen");
+ keep_open = state;
+ break;
+ case 'm': /* multiline */
+ switch (cmd[1]) {
+ case 'a':
+ FULLCHECK("mapped");
+ lookup->mapped = state;
+ break;
+ case 'u':
+ FULLCHECK("multiline");
+ 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)
+ fatal("Couldn't parse ndots");
+ ndots = num;
+ break;
+ case 's':
+ switch (cmd[2]) {
+ case 'i': /* nsid */
+ FULLCHECK("nsid");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ 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;
+ rrcomments = 0;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'o':
+ switch (cmd[1]) {
+ case 'n':
+ FULLCHECK("onesoa");
+ 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)
+ fatal("Couldn't parse opcode");
+ lookup->opcode = (dns_opcode_t)num;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'q':
+ switch (cmd[1]) {
+ case 'r': /* qr */
+ FULLCHECK("qr");
+ 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 '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)
+ fatal("Couldn't parse retries");
+ lookup->retries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r': /* rrcomments */
+ FULLCHECK("rrcomments");
+ 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;
+ rrcomments = -1;
+ }
+ break;
+ case 'w': /* showsearch */
+ FULLCHECK("showsearch");
+ if (!lookup->trace) {
+ showsearch = state;
+ usesearch = state;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+#ifdef DIG_SIGCHASE
+ case 'i': /* sigchase */
+ FULLCHECK("sigchase");
+ lookup->sigchase = state;
+ if (lookup->sigchase)
+ lookup->dnssec = true;
+ break;
+#endif
+ 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)
+ fatal("Couldn't parse split");
+ 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 = 0;
+ 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)
+ fatal("Couldn't parse client");
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ if (!is_batchfile) {
+ lookup->tcp_mode = state;
+ lookup->tcp_mode_set = true;
+ }
+ 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)
+ fatal("Couldn't parse timeout");
+ if (timeout == 0)
+ timeout = 1;
+ break;
+#if DIG_SIGCHASE_TD
+ case 'o': /* topdown */
+ FULLCHECK("topdown");
+ lookup->do_topdown = state;
+ break;
+#endif
+ case 'r':
+ switch (cmd[2]) {
+ case 'a': /* trace */
+ FULLCHECK("trace");
+ lookup->trace = state;
+ lookup->trace_root = state;
+ if (state) {
+ lookup->recurse = false;
+ lookup->identify = true;
+ lookup->comments = false;
+ 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)
+ fatal("Couldn't parse tries");
+ if (lookup->retries == 0)
+ lookup->retries = 1;
+ break;
+#ifdef DIG_SIGCHASE
+ case 'u': /* trusted-key */
+ FULLCHECK("trusted-key");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ n = strlcpy(trustedkey, ptr,
+ sizeof(trustedkey));
+ if (n >= sizeof(trustedkey))
+ fatal("trusted key too large");
+ break;
+#endif
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[2]) {
+ case 'l':
+ switch (cmd[3]) {
+ case 0:
+ case 'i': /* ttlid */
+ FULLCHECK2("ttl", "ttlid");
+ nottl = !state;
+ break;
+ case 'u': /* ttlunits */
+ FULLCHECK("ttlunits");
+ nottl = false;
+ ttlunits = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'u':
+ FULLCHECK("unknownformat");
+ lookup->print_unknown_format = state;
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ if (!is_batchfile) {
+ lookup->tcp_mode = state;
+ lookup->tcp_mode_set = true;
+ }
+ break;
+ case 'z': /* zflag */
+ FULLCHECK("zflag");
+ lookup->zflag = state;
+ 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 = "46dhimnuv";
+static const char *dash_opts = "46bcdfhikmnptvyx";
+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;
+ 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");
+ /* NOTREACHED */
+ return (false);
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ /* NOTREACHED */
+ 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':
+ ip6_int = true;
+ break;
+ case 'm': /* memdebug */
+ /* memdebug is handled in preparse_args() */
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'u':
+ 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(&bind_address, &in6, srcport);
+ isc_net_disableipv4();
+ } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
+ isc_sockaddr_fromin(&bind_address, &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':
+ batchname = 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;
+ 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':
+ ptr = next_token(&value, ":"); /* hmac type or name */
+ if (ptr == NULL) {
+ usage();
+ }
+ ptr2 = next_token(&value, ":"); /* name or secret */
+ if (ptr2 == NULL)
+ usage();
+ ptr3 = next_token(&value, ":"); /* secret or NULL */
+ if (ptr3 != NULL) {
+ parse_hmac(ptr);
+ ptr = ptr2;
+ ptr2 = ptr3;
+ } else {
+#ifndef PK11_MD5_DISABLE
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+#else
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+#endif
+ digestbits = 0;
+ }
+ 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,
+ ip6_int, 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);
+ (*lookup)->ip6_int = ip6_int;
+ 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();
+ }
+ /* NOTREACHED */
+ 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 'm':
+ 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;
+ }
+ option = &option[1];
+ }
+ }
+}
+
+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[256];
+#endif
+ char *input;
+ int i;
+ 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 = 0;
+ default_lookup->sendcookie = true;
+
+#ifndef NOPOSIX
+ /*
+ * Treat ${HOME}/.digrc as a special batchfile
+ */
+ INSIST(batchfp == NULL);
+ homedir = getenv("HOME");
+ if (homedir != NULL) {
+ unsigned int n;
+ 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 = 1;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 62) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] =
+ next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+
+ for(i = 0; i < bargc; i++)
+ debug(".digrc argv %d: %s",
+ i, bargv[i]);
+ parse_args(true, true, bargc,
+ (char **)bargv);
+ }
+ fclose(batchfp);
+ }
+#endif
+ }
+
+ 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] == '+') {
+ plus_option(&rv[0][1], is_batchfile,
+ 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
+ */
+ if ((batchname != NULL) && !(is_batchfile)) {
+ if (strcmp(batchname, "-") == 0)
+ batchfp = stdin;
+ else
+ batchfp = fopen(batchname, "r");
+ if (batchfp == NULL) {
+ perror(batchname);
+ 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) {
+ bargc = 1;
+ debug("batch line %s", batchline);
+ if (batchline[0] == '\r' || batchline[0] == '\n'
+ || batchline[0] == '#' || batchline[0] == ';')
+ goto next_line;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 14) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+
+ for(i = 0; i < bargc; i++)
+ debug("batch argv %d: %s", i, bargv[i]);
+ 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];
+ char *input;
+ int i;
+
+ if (batchname == NULL) {
+ isc_app_shutdown();
+ return;
+ }
+
+ fflush(stdout);
+ if (feof(batchfp)) {
+ batchname = NULL;
+ isc_app_shutdown();
+ if (batchfp != stdin)
+ fclose(batchfp);
+ return;
+ }
+
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ debug("batch line %s", batchline);
+ bargc = 1;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 14) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv0;
+
+ for(i = 0; i < bargc; i++)
+ debug("batch argv %d: %s", i, bargv[i]);
+ parse_args(true, false, bargc, (char **)bargv);
+ start_lookup();
+ } else {
+ batchname = NULL;
+ if (batchfp != stdin)
+ fclose(batchfp);
+ isc_app_shutdown();
+ return;
+ }
+}
+
+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 */
+#ifdef DIG_SIGCHASE
+ dighost_printrdataset = printrdataset;
+#endif
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = query_finished;
+
+ 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() {
+ 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()
+{
+ start_lookup();
+}
+
+void
+dig_shutdown() {
+ destroy_lookup(default_lookup);
+ if (batchname != NULL) {
+ if (batchfp != stdin)
+ fclose(batchfp);
+ batchname = NULL;
+ }
+
+#ifdef DIG_SIGCHASE
+ clean_trustedkey();
+#endif
+
+ 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.docbook b/bin/dig/dig.docbook
new file mode 100644
index 0000000..6b14a44
--- /dev/null
+++ b/bin/dig/dig.docbook
@@ -0,0 +1,1329 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dig">
+ <info>
+ <date>2014-02-19</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>dig</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>dig</refname>
+ <refpurpose>DNS lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dig</command>
+ <arg choice="opt" rep="norepeat">@server</arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">address</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port#</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q <replaceable class="parameter">name</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x <replaceable class="parameter">addr</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-y <replaceable class="parameter"><optional>hmac:</optional>name:key</replaceable></option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat">name</arg>
+ <arg choice="opt" rep="norepeat">type</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="opt" rep="repeat">queryopt</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>dig</command>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>dig</command>
+ <arg choice="opt" rep="repeat">global-queryopt</arg>
+ <arg choice="opt" rep="repeat">query</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dig</command> 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 <command>dig</command> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <command>dig</command>.
+ </para>
+
+ <para>
+ Although <command>dig</command> 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> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <command>dig</command> allows multiple lookups to be issued
+ from the
+ command line.
+ </para>
+
+ <para>
+ Unless it is told to query a specific name server,
+ <command>dig</command> will try each of the servers listed in
+ <filename>/etc/resolv.conf</filename>. If no usable server addresses
+ are found, <command>dig</command> will send the query to the local
+ host.
+ </para>
+
+ <para>
+ When no command line arguments or options are given,
+ <command>dig</command> will perform an NS query for "." (the root).
+ </para>
+
+ <para>
+ It is possible to set per-user defaults for <command>dig</command> via
+ <filename>${HOME}/.digrc</filename>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </para>
+
+ <para>
+ The IN and CH class names overlap with the IN and CH top level
+ domain names. Either use the <option>-t</option> and
+ <option>-c</option> options to specify the type and class,
+ use the <option>-q</option> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>SIMPLE USAGE</title></info>
+
+
+ <para>
+ A typical invocation of <command>dig</command> looks like:
+ <programlisting> dig @server name type </programlisting>
+ where:
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>server</constant></term>
+ <listitem>
+ <para>
+ 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
+ <parameter>server</parameter> argument is a hostname,
+ <command>dig</command> resolves that name before querying
+ that name server.
+ </para>
+ <para>
+ If no <parameter>server</parameter> argument is
+ provided, <command>dig</command> consults
+ <filename>/etc/resolv.conf</filename>; if an
+ address is found there, it queries the name server at
+ that address. If either of the <option>-4</option> or
+ <option>-6</option> options are in use, then
+ only addresses for the corresponding transport
+ will be tried. If no usable addresses are found,
+ <command>dig</command> will send the query to the
+ local host. The reply from the name server that
+ responds is displayed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>name</constant></term>
+ <listitem>
+ <para>
+ is the name of the resource record that is to be looked up.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type</constant></term>
+ <listitem>
+ <para>
+ indicates what type of query is required &mdash;
+ ANY, A, MX, SIG, etc.
+ <parameter>type</parameter> can be any valid query
+ type. If no
+ <parameter>type</parameter> argument is supplied,
+ <command>dig</command> will perform a lookup for an
+ A record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">address<optional>#port</optional></replaceable></term>
+ <listitem>
+ <para>
+ Set the source IP address of the query.
+ The <parameter>address</parameter> 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 "#&lt;port&gt;"
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Set the query class. The
+ default <parameter>class</parameter> is IN; other classes
+ are HS for Hesiod records or CH for Chaosnet records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ Batch mode: <command>dig</command> reads a list of lookup
+ requests to process from the
+ given <parameter>file</parameter>. Each line in the file
+ should be organized in the same way they would be
+ presented as queries to
+ <command>dig</command> using the command-line interface.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i</term>
+ <listitem>
+ <para>
+ Do reverse IPv6 lookups using the obsolete RFC 1886 IP6.INT
+ domain, which is no longer in use. Obsolete bit string
+ label queries (RFC 2874) are not attempted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">keyfile</replaceable></term>
+ <listitem>
+ <para>
+ Sign queries using TSIG using a key read from the given file.
+ Key files can be generated using
+ <citerefentry>
+ <refentrytitle>tsig-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ When using TSIG authentication with <command>dig</command>,
+ 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 <command>key</command>
+ and <command>server</command> statements in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m</term>
+ <listitem>
+ <para>
+ Enable memory usage debugging.
+ <!-- It enables ISC_MEM_DEBUGTRACE and ISC_MEM_DEBUGRECORD
+ documented in include/isc/mem.h -->
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Send the query to a non-standard port on the server,
+ instead of the default port 53. This option would be used
+ to test a name server that has been configured to listen
+ for queries on a non-standard port number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q <replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The domain name to query. This is useful to distinguish
+ the <parameter>name</parameter> from other arguments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ The resource record type to query. It 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>
+ 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
+ <parameter>type</parameter> to <literal>ixfr=N</literal>.
+ The incremental zone transfer will contain the changes
+ made to the zone since the serial number in the zone's SOA
+ record was
+ <parameter>N</parameter>.
+ </para>
+ <para>
+ 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 will be displayed as
+ described in RFC 3597.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u</term>
+ <listitem>
+ <para>
+ Print query times in microseconds instead of milliseconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x <replaceable class="parameter">addr</replaceable></term>
+ <listitem>
+ <para>
+ Simplified reverse lookups, for mapping addresses to
+ names. The <parameter>addr</parameter> 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 <parameter>name</parameter>, <parameter>class</parameter>
+ and <parameter>type</parameter>
+ arguments. <command>dig</command> automatically performs a
+ lookup for a name like
+ <literal>94.2.0.192.in-addr.arpa</literal> 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 (but see also the <option>-i</option>
+ option).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y <replaceable class="parameter"><optional>hmac:</optional>keyname:secret</replaceable></term>
+ <listitem>
+ <para>
+ Sign queries using TSIG with the given authentication key.
+ <parameter>keyname</parameter> is the name of the key, and
+ <parameter>secret</parameter> is the base64 encoded shared secret.
+ <parameter>hmac</parameter> is the name of the key algorithm;
+ valid choices are <literal>hmac-md5</literal>,
+ <literal>hmac-sha1</literal>, <literal>hmac-sha224</literal>,
+ <literal>hmac-sha256</literal>, <literal>hmac-sha384</literal>, or
+ <literal>hmac-sha512</literal>. If <parameter>hmac</parameter>
+ is not specified, the default is <literal>hmac-md5</literal>
+ or if MD5 was disabled <literal>hmac-sha256</literal>.
+ </para>
+ <para>
+ NOTE: You should use the <option>-k</option> option and
+ avoid the <option>-y</option> option, because
+ with <option>-y</option> the shared secret is supplied as
+ a command line argument in clear text. This may be visible
+ in the output from
+ <citerefentry>
+ <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ or in a history file maintained by the user's shell.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>QUERY OPTIONS</title></info>
+
+
+ <para><command>dig</command>
+ 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.
+ </para>
+
+ <para>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<literal>+</literal>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <literal>no</literal> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <option>+keyword=value</option>.
+ Keywords may be abbreviated, provided the abbreviation is
+ unambiguous; for example, <literal>+cd</literal> is equivalent
+ to <literal>+cdflag</literal>.
+ The query options are:
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>+[no]aaflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]aaonly</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]aaonly</option></term>
+ <listitem>
+ <para>
+ Sets the "aa" flag in the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]additional</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the additional section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]adflag</option></term>
+ <listitem>
+ <para>
+ Set [do 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 indicate that some part
+ of the answer was insecure or not validated. This
+ bit is set by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]all</option></term>
+ <listitem>
+ <para>
+ Set or clear all display flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]answer</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the answer section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]authority</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the authority section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]badcookie</option></term>
+ <listitem>
+ <para>
+ Retry lookup with the new server cookie if a
+ BADCOOKIE response is received.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]besteffort</option></term>
+ <listitem>
+ <para>
+ Attempt to display the contents of messages which are
+ malformed. The default is to not display malformed
+ answers.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+bufsize=B</option></term>
+ <listitem>
+ <para>
+ Set the UDP message buffer size advertised using EDNS0
+ to <parameter>B</parameter> 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 will cause a
+ EDNS query to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cdflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the CD (checking disabled) bit in
+ the query. This requests the server to not perform
+ DNSSEC validation of responses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]class</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the CLASS when printing the
+ record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cmd</option></term>
+ <listitem>
+ <para>
+ Toggles the printing of the initial comment in the
+ output identifying the version of <command>dig</command>
+ and the query options that have been applied. This
+ comment is printed by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]comments</option></term>
+ <listitem>
+ <para>
+ Toggle the display of comment lines in the output.
+ The default is to print comments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cookie<optional>=####</optional></option></term>
+ <listitem>
+ <para>
+ Send a COOKIE EDNS option, with optional
+ value. Replaying a COOKIE from a previous response will
+ allow the server to identify a previous client. The
+ default is <option>+cookie</option>.
+ </para>
+ <para>
+ <command>+cookie</command> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]crypto</option></term>
+ <listitem>
+ <para>
+ Toggle the display of cryptographic fields in DNSSEC
+ records. The contents of these field 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 ]".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]defname</option></term>
+ <listitem>
+ <para>
+ Deprecated, treated as a synonym for
+ <parameter>+[no]search</parameter>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]dnssec</option></term>
+ <listitem>
+ <para>
+ Requests DNSSEC records be sent by setting the DNSSEC
+ OK bit (DO) in the OPT record in the additional section
+ of the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+domain=somename</option></term>
+ <listitem>
+ <para>
+ Set the search list to contain the single domain
+ <parameter>somename</parameter>, as if specified in
+ a <command>domain</command> directive in
+ <filename>/etc/resolv.conf</filename>, and enable
+ search list processing as if the
+ <parameter>+search</parameter> option were given.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+dscp=value</option></term> <listitem>
+ <para>
+ Set the DSCP code point to be used when sending the
+ query. Valid DSCP code points are in the range
+ [0..63]. By default no code point is explicitly set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]edns[=#]</option></term>
+ <listitem>
+ <para>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause
+ a EDNS query to be sent. <option>+noedns</option>
+ clears the remembered EDNS version. EDNS is set to
+ 0 by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsflags[=#]</option></term>
+ <listitem>
+ <para>
+ Set 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) will silently be
+ ignored. By default, no Z bits are set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsnegotiation</option></term>
+ <listitem>
+ <para>
+ Enable / disable EDNS version negotiation. By default
+ EDNS version negotiation is enabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsopt[=code[:value]]</option></term>
+ <listitem>
+ <para>
+ Specify EDNS option with code point <option>code</option>
+ and optionally payload of <option>value</option> as a
+ hexadecimal string. <option>code</option> can be
+ either an EDNS option name (for example,
+ <literal>NSID</literal> or <literal>ECS</literal>),
+ or an arbitrary numeric value. <option>+noednsopt</option>
+ clears the EDNS options to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]expire</option></term>
+ <listitem>
+ <para>
+ Send an EDNS Expire option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]fail</option></term>
+ <listitem>
+ <para>
+ Do not try the next server if you receive a SERVFAIL.
+ The default is to not try the next server which is
+ the reverse of normal stub resolver behavior.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]header-only</option></term>
+ <listitem>
+ <para>
+ Send 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]identify</option></term>
+ <listitem>
+ <para>
+ Show [or do not show] the IP address and port number
+ that supplied the answer when the
+ <parameter>+short</parameter> 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]idnin</option></term>
+ <listitem>
+ <para>
+ Process [do 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]idnout</option></term>
+ <listitem>
+ <para>
+ Convert [do not convert] puny code on output.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to convert output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ignore</option></term>
+ <listitem>
+ <para>
+ Ignore truncation in UDP responses instead of retrying
+ with TCP. By default, TCP retries are performed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]keepopen</option></term>
+ <listitem>
+ <para>
+ Keep the TCP socket open between queries and reuse
+ it rather than creating a new TCP socket for each
+ lookup. The default is <option>+nokeepopen</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]mapped</option></term>
+ <listitem>
+ <para>
+ Allow mapped IPv4 over IPv6 addresses to be used. The
+ default is <option>+mapped</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]multiline</option></term>
+ <listitem>
+ <para>
+ 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 <command>dig</command>
+ output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+ndots=D</option></term>
+ <listitem>
+ <para>
+ Set the number of dots that have to appear in
+ <parameter>name</parameter> to <parameter>D</parameter>
+ for it to be considered absolute. The default value
+ is that defined using the ndots statement in
+ <filename>/etc/resolv.conf</filename>, or 1 if no
+ ndots statement is present. Names with fewer dots
+ are interpreted as relative names and will be searched
+ for in the domains listed in the <option>search</option>
+ or <option>domain</option> directive in
+ <filename>/etc/resolv.conf</filename> if
+ <option>+search</option> is set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nsid</option></term>
+ <listitem>
+ <para>
+ Include an EDNS name server ID request when sending
+ a query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nssearch</option></term>
+ <listitem>
+ <para>
+ When this option is set, <command>dig</command>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]onesoa</option></term>
+ <listitem>
+ <para>
+ Print only one (starting) SOA record when performing
+ an AXFR. The default is to print both the starting
+ and ending SOA records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]opcode=value</option></term>
+ <listitem>
+ <para>
+ Set [restore] the DNS message opcode to the specified
+ value. The default value is QUERY (0).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]qr</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the query as it is sent. By
+ default, the query is not printed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]question</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the question section of a query
+ when an answer is returned. The default is to print
+ the question section as a comment.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rdflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]recurse</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]recurse</option></term>
+ <listitem>
+ <para>
+ Toggle the setting of the RD (recursion desired) bit
+ in the query. This bit is set by default, which means
+ <command>dig</command> normally sends recursive
+ queries. Recursion is automatically disabled when
+ the <parameter>+nssearch</parameter> or
+ <parameter>+trace</parameter> query options are used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+retry=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to retry UDP queries to
+ server to <parameter>T</parameter> instead of the
+ default, 2. Unlike <parameter>+tries</parameter>,
+ this does not include the initial query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rrcomments</option></term>
+ <listitem>
+ <para>
+ Toggle 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]search</option></term>
+ <listitem>
+ <para>
+ Use [do not use] the search list defined by the
+ searchlist or domain directive in
+ <filename>resolv.conf</filename> (if any). The search
+ list is not used by default.
+ </para>
+ <para>
+ 'ndots' from <filename>resolv.conf</filename> (default 1)
+ which may be overridden by <parameter>+ndots</parameter>
+ determines if the name will be treated as relative
+ or not and hence whether a search is eventually
+ performed or not.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]short</option></term>
+ <listitem>
+ <para>
+ Provide a terse answer. The default is to print the
+ answer in a verbose form.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]showsearch</option></term>
+ <listitem>
+ <para>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]sigchase</option></term>
+ <listitem>
+ <para>
+ Chase DNSSEC signature chains. Requires dig be compiled
+ with -DDIG_SIGCHASE. This feature is deprecated.
+ Use <command>delv</command> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+split=W</option></term>
+ <listitem>
+ <para>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <parameter>W</parameter>
+ characters (where <parameter>W</parameter> is rounded
+ up to the nearest multiple of 4).
+ <parameter>+nosplit</parameter> or
+ <parameter>+split=0</parameter> causes fields not to
+ be split at all. The default is 56 characters, or
+ 44 characters when multiline mode is active.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]stats</option></term>
+ <listitem>
+ <para>
+ This query option toggles the printing of statistics:
+ when the query was made, the size of the reply and
+ so on. The default behavior is to print the query
+ statistics.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]subnet=addr[/prefix-length]</option></term>
+ <listitem>
+ <para>
+ Send (don't send) an EDNS Client Subnet option with the
+ specified IP address or network prefix.
+ </para>
+ <para>
+ <command>dig +subnet=0.0.0.0/0</command>, or simply
+ <command>dig +subnet=0</command> 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
+ <emphasis>not</emphasis> be used when resolving
+ this query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]tcp</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. The
+ default behavior is to use UDP unless a type
+ <literal>any</literal> or <literal>ixfr=N</literal>
+ query is requested, in which case the default is TCP.
+ AXFR queries always use TCP.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+timeout=T</option></term>
+ <listitem>
+ <para>
+
+ Sets the timeout for a query to
+ <parameter>T</parameter> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <parameter>T</parameter> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]topdown</option></term>
+ <listitem>
+ <para>
+ When chasing DNSSEC signature chains perform a top-down
+ validation. Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <command>delv</command> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]trace</option></term>
+ <listitem>
+ <para>
+ Toggle 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,
+ <command>dig</command> makes iterative queries to
+ resolve the name being looked up. It will follow
+ referrals from the root servers, showing the answer
+ from each server that was used to resolve the lookup.
+ </para> <para>
+ If @server is also specified, it affects only the
+ initial query for the root zone name servers.
+ </para> <para>
+ <command>+dnssec</command> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+tries=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to try UDP queries to server
+ to <parameter>T</parameter> instead of the default,
+ 3. If <parameter>T</parameter> is less than or equal
+ to zero, the number of tries is silently rounded up
+ to 1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+trusted-key=####</option></term>
+ <listitem>
+ <para>
+ Specifies a file containing trusted keys to be used
+ with <option>+sigchase</option>. Each DNSKEY record
+ must be on its own line.
+ </para> <para>
+ If not specified, <command>dig</command> will look
+ for <filename>/etc/trusted-key.key</filename> then
+ <filename>trusted-key.key</filename> in the current
+ directory.
+ </para> <para>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <command>delv</command> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlid</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL when printing the
+ record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlunits</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL in friendly human-readable
+ time units of "s", "m", "h", "d", and "w", representing
+ seconds, minutes, hours, days and weeks. Implies +ttlid.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]unknownformat</option></term>
+ <listitem>
+ <para>
+ Print 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]vc</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. This
+ alternate syntax to <parameter>+[no]tcp</parameter>
+ is provided for backwards compatibility. The "vc"
+ stands for "virtual circuit".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]zflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the last unassigned DNS header flag in a
+ DNS query. This flag is off by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+ </refsection>
+
+ <refsection><info><title>MULTIPLE QUERIES</title></info>
+
+
+ <para>
+ The BIND 9 implementation of <command>dig </command>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <option>-f</option> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </para>
+
+ <para>
+ In this case, each <parameter>query</parameter> argument
+ represent 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.
+ </para>
+
+ <para>
+ 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
+ the <option>+[no]cmd</option> option) can be
+ overridden by a query-specific set of query options. For example:
+ <programlisting>
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</programlisting>
+ shows how <command>dig</command> could be used from the
+ command line
+ to make three lookups: an ANY query for <literal>www.isc.org</literal>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <literal>isc.org</literal>.
+
+ A global query option of <parameter>+qr</parameter> is
+ applied, so
+ that <command>dig</command> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <parameter>+noqr</parameter> which means that <command>dig</command>
+ will not print the initial query when it looks up the NS records for
+ <literal>isc.org</literal>.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>IDN SUPPORT</title></info>
+
+ <para>
+ If <command>dig</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>dig</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, use
+ parameters <parameter>+noidnin</parameter> and
+ <parameter>+noidnout</parameter>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ <para><filename>${HOME}/.digrc</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>delv</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>host</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC 1035</citetitle>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>BUGS</title></info>
+
+ <para>
+ There are probably too many query options.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dig/dig.html b/bin/dig/dig.html
new file mode 100644
index 0000000..b749057
--- /dev/null
+++ b/bin/dig/dig.html
@@ -0,0 +1,1075 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dig</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dig"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ dig
+ &#8212; DNS lookup utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dig</code>
+ [@server]
+ [<code class="option">-b <em class="replaceable"><code>address</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-k <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-m</code>]
+ [<code class="option">-p <em class="replaceable"><code>port#</code></em></code>]
+ [<code class="option">-q <em class="replaceable"><code>name</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-x <em class="replaceable"><code>addr</code></em></code>]
+ [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]name:key</code></em></code>]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [name]
+ [type]
+ [class]
+ [queryopt...]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">dig</code>
+ [<code class="option">-h</code>]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">dig</code>
+ [global-queryopt...]
+ [query...]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dig</strong></span> 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 <span class="command"><strong>dig</strong></span> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <span class="command"><strong>dig</strong></span>.
+ </p>
+
+ <p>
+ Although <span class="command"><strong>dig</strong></span> 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 <code class="option">-h</code> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <span class="command"><strong>dig</strong></span> allows multiple lookups to be issued
+ from the
+ command line.
+ </p>
+
+ <p>
+ Unless it is told to query a specific name server,
+ <span class="command"><strong>dig</strong></span> will try each of the servers listed in
+ <code class="filename">/etc/resolv.conf</code>. If no usable server addresses
+ are found, <span class="command"><strong>dig</strong></span> will send the query to the local
+ host.
+ </p>
+
+ <p>
+ When no command line arguments or options are given,
+ <span class="command"><strong>dig</strong></span> will perform an NS query for "." (the root).
+ </p>
+
+ <p>
+ It is possible to set per-user defaults for <span class="command"><strong>dig</strong></span> via
+ <code class="filename">${HOME}/.digrc</code>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </p>
+
+ <p>
+ The IN and CH class names overlap with the IN and CH top level
+ domain names. Either use the <code class="option">-t</code> and
+ <code class="option">-c</code> options to specify the type and class,
+ use the <code class="option">-q</code> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SIMPLE USAGE</h2>
+
+
+ <p>
+ A typical invocation of <span class="command"><strong>dig</strong></span> looks like:
+ </p>
+<pre class="programlisting"> dig @server name type </pre>
+<p>
+ where:
+
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">server</code></span></dt>
+<dd>
+ <p>
+ 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
+ <em class="parameter"><code>server</code></em> argument is a hostname,
+ <span class="command"><strong>dig</strong></span> resolves that name before querying
+ that name server.
+ </p>
+ <p>
+ If no <em class="parameter"><code>server</code></em> argument is
+ provided, <span class="command"><strong>dig</strong></span> consults
+ <code class="filename">/etc/resolv.conf</code>; if an
+ address is found there, it queries the name server at
+ that address. If either of the <code class="option">-4</code> or
+ <code class="option">-6</code> options are in use, then
+ only addresses for the corresponding transport
+ will be tried. If no usable addresses are found,
+ <span class="command"><strong>dig</strong></span> will send the query to the
+ local host. The reply from the name server that
+ responds is displayed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">name</code></span></dt>
+<dd>
+ <p>
+ is the name of the resource record that is to be looked up.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">type</code></span></dt>
+<dd>
+ <p>
+ indicates what type of query is required &#8212;
+ ANY, A, MX, SIG, etc.
+ <em class="parameter"><code>type</code></em> can be any valid query
+ type. If no
+ <em class="parameter"><code>type</code></em> argument is supplied,
+ <span class="command"><strong>dig</strong></span> will perform a lookup for an
+ A record.
+ </p>
+ </dd>
+</dl></div>
+<p>
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Use IPv4 only.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Use IPv6 only.
+ </p>
+ </dd>
+<dt><span class="term">-b <em class="replaceable"><code>address[<span class="optional">#port</span>]</code></em></span></dt>
+<dd>
+ <p>
+ Set the source IP address of the query.
+ The <em class="parameter"><code>address</code></em> 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 "#&lt;port&gt;"
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Set the query class. The
+ default <em class="parameter"><code>class</code></em> is IN; other classes
+ are HS for Hesiod records or CH for Chaosnet records.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt>
+<dd>
+ <p>
+ Batch mode: <span class="command"><strong>dig</strong></span> reads a list of lookup
+ requests to process from the
+ given <em class="parameter"><code>file</code></em>. Each line in the file
+ should be organized in the same way they would be
+ presented as queries to
+ <span class="command"><strong>dig</strong></span> using the command-line interface.
+ </p>
+ </dd>
+<dt><span class="term">-i</span></dt>
+<dd>
+ <p>
+ Do reverse IPv6 lookups using the obsolete RFC 1886 IP6.INT
+ domain, which is no longer in use. Obsolete bit string
+ label queries (RFC 2874) are not attempted.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyfile</code></em></span></dt>
+<dd>
+ <p>
+ Sign queries using TSIG using a key read from the given file.
+ Key files can be generated using
+ <span class="citerefentry">
+ <span class="refentrytitle">tsig-keygen</span>(8)
+ </span>.
+ When using TSIG authentication with <span class="command"><strong>dig</strong></span>,
+ 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 <span class="command"><strong>key</strong></span>
+ and <span class="command"><strong>server</strong></span> statements in
+ <code class="filename">named.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-m</span></dt>
+<dd>
+ <p>
+ Enable memory usage debugging.
+
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Send the query to a non-standard port on the server,
+ instead of the default port 53. This option would be used
+ to test a name server that has been configured to listen
+ for queries on a non-standard port number.
+ </p>
+ </dd>
+<dt><span class="term">-q <em class="replaceable"><code>name</code></em></span></dt>
+<dd>
+ <p>
+ The domain name to query. This is useful to distinguish
+ the <em class="parameter"><code>name</code></em> from other arguments.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ The resource record type to query. It 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 <code class="option">-x</code>
+ 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
+ <em class="parameter"><code>type</code></em> to <code class="literal">ixfr=N</code>.
+ The incremental zone transfer will contain the changes
+ made to the zone since the serial number in the zone's SOA
+ record was
+ <em class="parameter"><code>N</code></em>.
+ </p>
+ <p>
+ 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 will be displayed as
+ described in RFC 3597.
+ </p>
+ </dd>
+<dt><span class="term">-u</span></dt>
+<dd>
+ <p>
+ Print query times in microseconds instead of milliseconds.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Print the version number and exit.
+ </p>
+ </dd>
+<dt><span class="term">-x <em class="replaceable"><code>addr</code></em></span></dt>
+<dd>
+ <p>
+ Simplified reverse lookups, for mapping addresses to
+ names. The <em class="parameter"><code>addr</code></em> is an IPv4 address
+ in dotted-decimal notation, or a colon-delimited IPv6
+ address. When the <code class="option">-x</code> is used, there is no
+ need to provide
+ the <em class="parameter"><code>name</code></em>, <em class="parameter"><code>class</code></em>
+ and <em class="parameter"><code>type</code></em>
+ arguments. <span class="command"><strong>dig</strong></span> automatically performs a
+ lookup for a name like
+ <code class="literal">94.2.0.192.in-addr.arpa</code> 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 (but see also the <code class="option">-i</code>
+ option).
+ </p>
+ </dd>
+<dt><span class="term">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></span></dt>
+<dd>
+ <p>
+ Sign queries using TSIG with the given authentication key.
+ <em class="parameter"><code>keyname</code></em> is the name of the key, and
+ <em class="parameter"><code>secret</code></em> is the base64 encoded shared secret.
+ <em class="parameter"><code>hmac</code></em> is the name of the key algorithm;
+ valid choices are <code class="literal">hmac-md5</code>,
+ <code class="literal">hmac-sha1</code>, <code class="literal">hmac-sha224</code>,
+ <code class="literal">hmac-sha256</code>, <code class="literal">hmac-sha384</code>, or
+ <code class="literal">hmac-sha512</code>. If <em class="parameter"><code>hmac</code></em>
+ is not specified, the default is <code class="literal">hmac-md5</code>
+ or if MD5 was disabled <code class="literal">hmac-sha256</code>.
+ </p>
+ <p>
+ NOTE: You should use the <code class="option">-k</code> option and
+ avoid the <code class="option">-y</code> option, because
+ with <code class="option">-y</code> the shared secret is supplied as
+ a command line argument in clear text. This may be visible
+ in the output from
+ <span class="citerefentry">
+ <span class="refentrytitle">ps</span>(1)
+ </span>
+ or in a history file maintained by the user's shell.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>QUERY OPTIONS</h2>
+
+
+ <p><span class="command"><strong>dig</strong></span>
+ 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.
+ </p>
+
+ <p>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<code class="literal">+</code>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <code class="literal">no</code> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <code class="option">+keyword=value</code>.
+ Keywords may be abbreviated, provided the abbreviation is
+ unambiguous; for example, <code class="literal">+cd</code> is equivalent
+ to <code class="literal">+cdflag</code>.
+ The query options are:
+
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="option">+[no]aaflag</code></span></dt>
+<dd>
+ <p>
+ A synonym for <em class="parameter"><code>+[no]aaonly</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]aaonly</code></span></dt>
+<dd>
+ <p>
+ Sets the "aa" flag in the query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]additional</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the additional section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]adflag</code></span></dt>
+<dd>
+ <p>
+ Set [do 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 indicate that some part
+ of the answer was insecure or not validated. This
+ bit is set by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]all</code></span></dt>
+<dd>
+ <p>
+ Set or clear all display flags.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]answer</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the answer section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]authority</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the authority section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]badcookie</code></span></dt>
+<dd>
+ <p>
+ Retry lookup with the new server cookie if a
+ BADCOOKIE response is received.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]besteffort</code></span></dt>
+<dd>
+ <p>
+ Attempt to display the contents of messages which are
+ malformed. The default is to not display malformed
+ answers.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+bufsize=B</code></span></dt>
+<dd>
+ <p>
+ Set the UDP message buffer size advertised using EDNS0
+ to <em class="parameter"><code>B</code></em> 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 will cause a
+ EDNS query to be sent.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cdflag</code></span></dt>
+<dd>
+ <p>
+ Set [do not set] the CD (checking disabled) bit in
+ the query. This requests the server to not perform
+ DNSSEC validation of responses.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]class</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the CLASS when printing the
+ record.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cmd</code></span></dt>
+<dd>
+ <p>
+ Toggles the printing of the initial comment in the
+ output identifying the version of <span class="command"><strong>dig</strong></span>
+ and the query options that have been applied. This
+ comment is printed by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]comments</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of comment lines in the output.
+ The default is to print comments.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cookie[<span class="optional">=####</span>]</code></span></dt>
+<dd>
+ <p>
+ Send a COOKIE EDNS option, with optional
+ value. Replaying a COOKIE from a previous response will
+ allow the server to identify a previous client. The
+ default is <code class="option">+cookie</code>.
+ </p>
+ <p>
+ <span class="command"><strong>+cookie</strong></span> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]crypto</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of cryptographic fields in DNSSEC
+ records. The contents of these field 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 ]".
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]defname</code></span></dt>
+<dd>
+ <p>
+ Deprecated, treated as a synonym for
+ <em class="parameter"><code>+[no]search</code></em>
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]dnssec</code></span></dt>
+<dd>
+ <p>
+ Requests DNSSEC records be sent by setting the DNSSEC
+ OK bit (DO) in the OPT record in the additional section
+ of the query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+domain=somename</code></span></dt>
+<dd>
+ <p>
+ Set the search list to contain the single domain
+ <em class="parameter"><code>somename</code></em>, as if specified in
+ a <span class="command"><strong>domain</strong></span> directive in
+ <code class="filename">/etc/resolv.conf</code>, and enable
+ search list processing as if the
+ <em class="parameter"><code>+search</code></em> option were given.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+dscp=value</code></span></dt>
+<dd>
+ <p>
+ Set the DSCP code point to be used when sending the
+ query. Valid DSCP code points are in the range
+ [0..63]. By default no code point is explicitly set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]edns[=#]</code></span></dt>
+<dd>
+ <p>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause
+ a EDNS query to be sent. <code class="option">+noedns</code>
+ clears the remembered EDNS version. EDNS is set to
+ 0 by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsflags[=#]</code></span></dt>
+<dd>
+ <p>
+ Set 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) will silently be
+ ignored. By default, no Z bits are set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsnegotiation</code></span></dt>
+<dd>
+ <p>
+ Enable / disable EDNS version negotiation. By default
+ EDNS version negotiation is enabled.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsopt[=code[:value]]</code></span></dt>
+<dd>
+ <p>
+ Specify EDNS option with code point <code class="option">code</code>
+ and optionally payload of <code class="option">value</code> as a
+ hexadecimal string. <code class="option">code</code> can be
+ either an EDNS option name (for example,
+ <code class="literal">NSID</code> or <code class="literal">ECS</code>),
+ or an arbitrary numeric value. <code class="option">+noednsopt</code>
+ clears the EDNS options to be sent.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]expire</code></span></dt>
+<dd>
+ <p>
+ Send an EDNS Expire option.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]fail</code></span></dt>
+<dd>
+ <p>
+ Do not try the next server if you receive a SERVFAIL.
+ The default is to not try the next server which is
+ the reverse of normal stub resolver behavior.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]header-only</code></span></dt>
+<dd>
+ <p>
+ Send 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]identify</code></span></dt>
+<dd>
+ <p>
+ Show [or do not show] the IP address and port number
+ that supplied the answer when the
+ <em class="parameter"><code>+short</code></em> 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]idnin</code></span></dt>
+<dd>
+ <p>
+ Process [do 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]idnout</code></span></dt>
+<dd>
+ <p>
+ Convert [do not convert] puny code on output.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to convert output.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ignore</code></span></dt>
+<dd>
+ <p>
+ Ignore truncation in UDP responses instead of retrying
+ with TCP. By default, TCP retries are performed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]keepopen</code></span></dt>
+<dd>
+ <p>
+ Keep the TCP socket open between queries and reuse
+ it rather than creating a new TCP socket for each
+ lookup. The default is <code class="option">+nokeepopen</code>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]mapped</code></span></dt>
+<dd>
+ <p>
+ Allow mapped IPv4 over IPv6 addresses to be used. The
+ default is <code class="option">+mapped</code>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]multiline</code></span></dt>
+<dd>
+ <p>
+ 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 <span class="command"><strong>dig</strong></span>
+ output.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+ndots=D</code></span></dt>
+<dd>
+ <p>
+ Set the number of dots that have to appear in
+ <em class="parameter"><code>name</code></em> to <em class="parameter"><code>D</code></em>
+ for it to be considered absolute. The default value
+ is that defined using the ndots statement in
+ <code class="filename">/etc/resolv.conf</code>, or 1 if no
+ ndots statement is present. Names with fewer dots
+ are interpreted as relative names and will be searched
+ for in the domains listed in the <code class="option">search</code>
+ or <code class="option">domain</code> directive in
+ <code class="filename">/etc/resolv.conf</code> if
+ <code class="option">+search</code> is set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]nsid</code></span></dt>
+<dd>
+ <p>
+ Include an EDNS name server ID request when sending
+ a query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]nssearch</code></span></dt>
+<dd>
+ <p>
+ When this option is set, <span class="command"><strong>dig</strong></span>
+ 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]onesoa</code></span></dt>
+<dd>
+ <p>
+ Print only one (starting) SOA record when performing
+ an AXFR. The default is to print both the starting
+ and ending SOA records.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]opcode=value</code></span></dt>
+<dd>
+ <p>
+ Set [restore] the DNS message opcode to the specified
+ value. The default value is QUERY (0).
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]qr</code></span></dt>
+<dd>
+ <p>
+ Print [do not print] the query as it is sent. By
+ default, the query is not printed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]question</code></span></dt>
+<dd>
+ <p>
+ Print [do not print] the question section of a query
+ when an answer is returned. The default is to print
+ the question section as a comment.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rdflag</code></span></dt>
+<dd>
+ <p>
+ A synonym for <em class="parameter"><code>+[no]recurse</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]recurse</code></span></dt>
+<dd>
+ <p>
+ Toggle the setting of the RD (recursion desired) bit
+ in the query. This bit is set by default, which means
+ <span class="command"><strong>dig</strong></span> normally sends recursive
+ queries. Recursion is automatically disabled when
+ the <em class="parameter"><code>+nssearch</code></em> or
+ <em class="parameter"><code>+trace</code></em> query options are used.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+retry=T</code></span></dt>
+<dd>
+ <p>
+ Sets the number of times to retry UDP queries to
+ server to <em class="parameter"><code>T</code></em> instead of the
+ default, 2. Unlike <em class="parameter"><code>+tries</code></em>,
+ this does not include the initial query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rrcomments</code></span></dt>
+<dd>
+ <p>
+ Toggle 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]search</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] the search list defined by the
+ searchlist or domain directive in
+ <code class="filename">resolv.conf</code> (if any). The search
+ list is not used by default.
+ </p>
+ <p>
+ 'ndots' from <code class="filename">resolv.conf</code> (default 1)
+ which may be overridden by <em class="parameter"><code>+ndots</code></em>
+ determines if the name will be treated as relative
+ or not and hence whether a search is eventually
+ performed or not.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]short</code></span></dt>
+<dd>
+ <p>
+ Provide a terse answer. The default is to print the
+ answer in a verbose form.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]showsearch</code></span></dt>
+<dd>
+ <p>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]sigchase</code></span></dt>
+<dd>
+ <p>
+ Chase DNSSEC signature chains. Requires dig be compiled
+ with -DDIG_SIGCHASE. This feature is deprecated.
+ Use <span class="command"><strong>delv</strong></span> instead.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+split=W</code></span></dt>
+<dd>
+ <p>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <em class="parameter"><code>W</code></em>
+ characters (where <em class="parameter"><code>W</code></em> is rounded
+ up to the nearest multiple of 4).
+ <em class="parameter"><code>+nosplit</code></em> or
+ <em class="parameter"><code>+split=0</code></em> causes fields not to
+ be split at all. The default is 56 characters, or
+ 44 characters when multiline mode is active.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]stats</code></span></dt>
+<dd>
+ <p>
+ This query option toggles the printing of statistics:
+ when the query was made, the size of the reply and
+ so on. The default behavior is to print the query
+ statistics.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]subnet=addr[/prefix-length]</code></span></dt>
+<dd>
+ <p>
+ Send (don't send) an EDNS Client Subnet option with the
+ specified IP address or network prefix.
+ </p>
+ <p>
+ <span class="command"><strong>dig +subnet=0.0.0.0/0</strong></span>, or simply
+ <span class="command"><strong>dig +subnet=0</strong></span> 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
+ <span class="emphasis"><em>not</em></span> be used when resolving
+ this query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]tcp</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] TCP when querying name servers. The
+ default behavior is to use UDP unless a type
+ <code class="literal">any</code> or <code class="literal">ixfr=N</code>
+ query is requested, in which case the default is TCP.
+ AXFR queries always use TCP.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+timeout=T</code></span></dt>
+<dd>
+ <p>
+
+ Sets the timeout for a query to
+ <em class="parameter"><code>T</code></em> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <em class="parameter"><code>T</code></em> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]topdown</code></span></dt>
+<dd>
+ <p>
+ When chasing DNSSEC signature chains perform a top-down
+ validation. Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <span class="command"><strong>delv</strong></span> instead.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]trace</code></span></dt>
+<dd>
+ <p>
+ Toggle 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,
+ <span class="command"><strong>dig</strong></span> makes iterative queries to
+ resolve the name being looked up. It will follow
+ referrals from the root servers, showing the answer
+ from each server that was used to resolve the lookup.
+ </p> <p>
+ If @server is also specified, it affects only the
+ initial query for the root zone name servers.
+ </p> <p>
+ <span class="command"><strong>+dnssec</strong></span> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+tries=T</code></span></dt>
+<dd>
+ <p>
+ Sets the number of times to try UDP queries to server
+ to <em class="parameter"><code>T</code></em> instead of the default,
+ 3. If <em class="parameter"><code>T</code></em> is less than or equal
+ to zero, the number of tries is silently rounded up
+ to 1.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+trusted-key=####</code></span></dt>
+<dd>
+ <p>
+ Specifies a file containing trusted keys to be used
+ with <code class="option">+sigchase</code>. Each DNSKEY record
+ must be on its own line.
+ </p> <p>
+ If not specified, <span class="command"><strong>dig</strong></span> will look
+ for <code class="filename">/etc/trusted-key.key</code> then
+ <code class="filename">trusted-key.key</code> in the current
+ directory.
+ </p> <p>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <span class="command"><strong>delv</strong></span> instead.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttlid</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the TTL when printing the
+ record.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttlunits</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the TTL in friendly human-readable
+ time units of "s", "m", "h", "d", and "w", representing
+ seconds, minutes, hours, days and weeks. Implies +ttlid.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]unknownformat</code></span></dt>
+<dd>
+ <p>
+ Print 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]vc</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] TCP when querying name servers. This
+ alternate syntax to <em class="parameter"><code>+[no]tcp</code></em>
+ is provided for backwards compatibility. The "vc"
+ stands for "virtual circuit".
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]zflag</code></span></dt>
+<dd>
+ <p>
+ Set [do not set] the last unassigned DNS header flag in a
+ DNS query. This flag is off by default.
+ </p>
+ </dd>
+</dl></div>
+<p>
+
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>MULTIPLE QUERIES</h2>
+
+
+ <p>
+ The BIND 9 implementation of <span class="command"><strong>dig </strong></span>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <code class="option">-f</code> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </p>
+
+ <p>
+ In this case, each <em class="parameter"><code>query</code></em> argument
+ represent 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.
+ </p>
+
+ <p>
+ 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
+ the <code class="option">+[no]cmd</code> option) can be
+ overridden by a query-specific set of query options. For example:
+ </p>
+<pre class="programlisting">
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</pre>
+<p>
+ shows how <span class="command"><strong>dig</strong></span> could be used from the
+ command line
+ to make three lookups: an ANY query for <code class="literal">www.isc.org</code>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <code class="literal">isc.org</code>.
+
+ A global query option of <em class="parameter"><code>+qr</code></em> is
+ applied, so
+ that <span class="command"><strong>dig</strong></span> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <em class="parameter"><code>+noqr</code></em> which means that <span class="command"><strong>dig</strong></span>
+ will not print the initial query when it looks up the NS records for
+ <code class="literal">isc.org</code>.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>IDN SUPPORT</h2>
+
+ <p>
+ If <span class="command"><strong>dig</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span class="command"><strong>dig</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, use
+ parameters <em class="parameter"><code>+noidnin</code></em> and
+ <em class="parameter"><code>+noidnout</code></em>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.13"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/resolv.conf</code>
+ </p>
+ <p><code class="filename">${HOME}/.digrc</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.14"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">delv</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">host</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <em class="citetitle">RFC 1035</em>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.15"></a><h2>BUGS</h2>
+
+ <p>
+ There are probably too many query options.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
new file mode 100644
index 0000000..aa5315d
--- /dev/null
+++ b/bin/dig/dighost.c
@@ -0,0 +1,6676 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \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 <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+#ifdef WITH_IDNKIT
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#ifdef WITH_LIBIDN2
+#include <idn2.h>
+#endif
+#endif /* WITH_IDN_SUPPORT */
+
+#include <dns/byaddr.h>
+#ifdef DIG_SIGCHASE
+#include <dns/callbacks.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/master.h>
+#include <dns/nsec.h>
+#include <isc/random.h>
+#include <ctype.h>
+#endif
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.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/result.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hex.h>
+#include <isc/lang.h>
+#include <isc/log.h>
+#include <isc/netaddr.h>
+#include <isc/netdb.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 <pk11/site.h>
+
+#include <isccfg/namedconf.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+#include <bind9/getaddresses.h>
+
+#include <dig/dig.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#if ! defined(NS_INADDRSZ)
+#define NS_INADDRSZ 4
+#endif
+
+#if ! defined(NS_IN6ADDRSZ)
+#define NS_IN6ADDRSZ 16
+#endif
+
+static lwres_context_t *lwctx = NULL;
+static lwres_conf_t *lwconf;
+
+dig_lookuplist_t lookup_list;
+dig_serverlist_t server_list;
+dig_searchlistlist_t search_list;
+
+bool
+ check_ra = false,
+ have_ipv4 = false,
+ have_ipv6 = false,
+ specified_source = false,
+ free_now = false,
+ cancel_now = false,
+ usesearch = false,
+ showsearch = false,
+ qr = false,
+ is_dst_up = false,
+ keep_open = false,
+ verbose = false;
+in_port_t port = 53;
+unsigned int timeout = 0;
+unsigned int extrabytes;
+isc_mem_t *mctx = NULL;
+isc_log_t *lctx = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_task_t *global_task = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_socketmgr_t *socketmgr = NULL;
+isc_sockaddr_t bind_address;
+isc_sockaddr_t bind_any;
+int sendcount = 0;
+int recvcount = 0;
+int sockcount = 0;
+int ndots = -1;
+int tries = 3;
+int lookup_counter = 0;
+
+static char servercookie[256];
+
+#ifdef WITH_IDN_SUPPORT
+static void idn_initialize(void);
+static isc_result_t idn_locale_to_ace(const char *from,
+ char *to,
+ size_t tolen);
+#endif /* WITH_IDN_SUPPORT */
+
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t idn_ace_to_locale(const char *from,
+ char *to,
+ size_t tolen);
+static isc_result_t output_filter(isc_buffer_t *buffer,
+ unsigned int used_org,
+ bool absolute);
+#define MAXDLEN 256
+
+#ifdef WITH_IDNKIT
+int idnoptions = 0;
+#endif
+#endif /* WITH_IDN_OUT_SUPPORT */
+
+isc_socket_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];
+dns_name_t *hmacname = NULL;
+unsigned int digestbits = 0;
+isc_buffer_t *namebuf = NULL;
+dns_tsigkey_t *tsigkey = NULL;
+bool validated = true;
+isc_entropy_t *entp = NULL;
+isc_mempool_t *commctx = NULL;
+bool debugging = false;
+bool debugtiming = false;
+bool memdebugging = false;
+char *progname = NULL;
+isc_mutex_t lookup_lock;
+dig_lookup_t *current_lookup = NULL;
+
+#ifdef DIG_SIGCHASE
+
+isc_result_t get_trusted_key(void);
+dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ bool *lookedup,
+ dns_name_t *rdata_name);
+dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
+ dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ int section);
+isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
+ dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ bool *lookedup);
+isc_result_t sigchase_verify_sig_key(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dst_key_t* dnsseckey,
+ dns_rdataset_t *sigrdataset);
+isc_result_t sigchase_verify_sig(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset);
+isc_result_t sigchase_verify_ds(dns_name_t *name,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset);
+void sigchase(dns_message_t *msg);
+void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
+void print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset);
+void dup_name(dns_name_t *source, dns_name_t* target);
+void free_name(dns_name_t *name);
+void dump_database(void);
+void dump_database_section(dns_message_t *msg, int section);
+dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
+ dns_rdatatype_t covers);
+isc_result_t contains_trusted_key(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset);
+void print_type(dns_rdatatype_t type);
+isc_result_t prove_nx_domain(dns_message_t * msg,
+ dns_name_t * name,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
+ dns_rdataset_t *nsec,
+ dns_rdataclass_t rdclass,
+ dns_rdatatype_t type,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
+ dns_rdataclass_t rdclass,
+ dns_rdatatype_t type,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+static void nameFromString(const char *str, dns_name_t *p_ret);
+int inf_name(dns_name_t * name1, dns_name_t * name2);
+isc_result_t removetmpkey(const char *file);
+void clean_trustedkey(void);
+isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
+ dns_rdataset_t *rdataset);
+#if DIG_SIGCHASE_BU
+isc_result_t getneededrr(dns_message_t *msg);
+void sigchase_bottom_up(dns_message_t *msg);
+void sigchase_bu(dns_message_t *msg);
+#endif
+#if DIG_SIGCHASE_TD
+isc_result_t initialization(dns_name_t *name);
+isc_result_t prepare_lookup(dns_name_t *name);
+isc_result_t grandfather_pb_test(dns_name_t * zone_name,
+ dns_rdataset_t *sigrdataset);
+isc_result_t child_of_zone(dns_name_t *name,
+ dns_name_t *zone_name,
+ dns_name_t *child_name);
+void sigchase_td(dns_message_t *msg);
+#endif
+char trustedkey[MXNAME] = "";
+
+dns_rdataset_t *chase_rdataset = NULL;
+dns_rdataset_t *chase_sigrdataset = NULL;
+dns_rdataset_t *chase_dsrdataset = NULL;
+dns_rdataset_t *chase_sigdsrdataset = NULL;
+dns_rdataset_t *chase_keyrdataset = NULL;
+dns_rdataset_t *chase_sigkeyrdataset = NULL;
+dns_rdataset_t *chase_nsrdataset = NULL;
+
+dns_name_t chase_name; /* the query name */
+#if DIG_SIGCHASE_TD
+/*
+ * the current name is the parent name when we follow delegation
+ */
+dns_name_t chase_current_name;
+/*
+ * the child name is used for delegation (NS DS responses in AUTHORITY section)
+ */
+dns_name_t chase_authority_name;
+#endif
+#if DIG_SIGCHASE_BU
+dns_name_t chase_signame;
+#endif
+
+
+bool chase_siglookedup = false;
+bool chase_keylookedup = false;
+bool chase_sigkeylookedup = false;
+bool chase_dslookedup = false;
+bool chase_sigdslookedup = false;
+#if DIG_SIGCHASE_TD
+bool chase_nslookedup = false;
+bool chase_lookedup = false;
+
+
+bool delegation_follow = false;
+bool grandfather_pb = false;
+bool have_response = false;
+bool have_delegation_ns = false;
+dns_message_t * error_message = NULL;
+#endif
+
+bool dsvalidating = false;
+bool chase_name_dup = false;
+
+ISC_LIST(dig_message_t) chase_message_list;
+ISC_LIST(dig_message_t) chase_message_list2;
+
+
+#define MAX_TRUSTED_KEY 5
+typedef struct struct_trusted_key_list {
+ dst_key_t * key[MAX_TRUSTED_KEY];
+ int nb_tk;
+} struct_tk_list;
+
+struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
+
+#endif
+
+#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");\
+}
+
+/* dynamic callbacks */
+
+#ifdef DIG_SIGCHASE
+isc_result_t
+(*dighost_printrdataset)(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target);
+#endif
+
+isc_result_t
+(*dighost_printmessage)(dig_query_t *query, dns_message_t *msg,
+ bool headers);
+
+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 */
+
+static void
+cancel_lookup(dig_lookup_t *lookup);
+
+static void
+recv_done(isc_task_t *task, isc_event_t *event);
+
+static void
+send_udp(dig_query_t *query);
+
+static void
+connect_timeout(isc_task_t *task, isc_event_t *event);
+
+static void
+launch_next_query(dig_query_t *query, bool include_question);
+
+static void
+check_next_lookup(dig_lookup_t *lookup);
+
+static bool
+next_origin(dig_lookup_t *oldlookup);
+
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+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) {
+ fputs(" ", stdout);
+ 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++)
+ fputs(" ", stdout);
+ fputs(" ", stdout);
+ 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 ip6_int,
+ 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;
+
+ if (ip6_int)
+ options |= DNS_BYADDROPT_IPV6INT;
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname2(&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
+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");
+ if (exitcode < 10)
+ exitcode = 10;
+ if (fatalexit != 0)
+ exitcode = fatalexit;
+ exit(exitcode);
+}
+
+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));
+ if (srv == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ strlcpy(srv->servername, servname, MXNAME);
+ strlcpy(srv->userarg, userarg, MXNAME);
+ ISC_LINK_INIT(srv, link);
+ return (srv);
+}
+
+static int
+addr2af(int lwresaddrtype)
+{
+ int af = 0;
+
+ switch (lwresaddrtype) {
+ case LWRES_ADDRTYPE_V4:
+ af = AF_INET;
+ break;
+
+ case LWRES_ADDRTYPE_V6:
+ af = AF_INET6;
+ break;
+ }
+
+ return (af);
+}
+
+/*%
+ * Create a copy of the server list from the lwres configuration structure.
+ * The dest list must have already had ISC_LIST_INIT applied.
+ */
+static void
+copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
+ dig_server_t *newsrv;
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
+ sizeof("%4000000000")];
+ int af;
+ int i;
+
+ debug("copy_server_list()");
+ for (i = 0; i < confdata->nsnext; i++) {
+ af = addr2af(confdata->nameservers[i].family);
+
+ if (af == AF_INET && !have_ipv4)
+ continue;
+ if (af == AF_INET6 && !have_ipv6)
+ continue;
+
+ lwres_net_ntop(af, confdata->nameservers[i].address,
+ tmp, sizeof(tmp));
+ if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
+ char buf[sizeof("%4000000000")];
+ snprintf(buf, sizeof(buf), "%%%u",
+ confdata->nameservers[i].zone);
+ strlcat(tmp, buf, sizeof(tmp));
+ }
+ newsrv = make_server(tmp, tmp);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_ENQUEUE(*dest, 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);
+ }
+}
+
+static isc_result_t
+add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
+
+ int i = confdata->nsnext;
+
+ if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
+ return (ISC_R_FAILURE);
+
+ switch (af) {
+ case AF_INET:
+ confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
+ confdata->nameservers[i].length = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
+ confdata->nameservers[i].length = NS_IN6ADDRSZ;
+ break;
+ default:
+ return (ISC_R_FAILURE);
+ }
+
+ if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
+ confdata->nsnext++;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_FAILURE);
+}
+
+/*%
+ * 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;
+
+ debug("make_empty_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
+ if (looknew == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ looknew->pending = true;
+ looknew->textname[0] = 0;
+ looknew->cmdline[0] = 0;
+ looknew->rdtype = dns_rdatatype_a;
+ looknew->qrdtype = dns_rdatatype_a;
+ looknew->rdclass = dns_rdataclass_in;
+ looknew->rdtypeset = false;
+ looknew->rdclassset = false;
+ looknew->sendspace = NULL;
+ looknew->sendmsg = NULL;
+ looknew->name = NULL;
+ looknew->oname = NULL;
+ looknew->xfr_q = NULL;
+ looknew->current_query = NULL;
+ looknew->doing_xfr = false;
+ looknew->ixfr_serial = 0;
+ looknew->trace = false;
+ looknew->trace_root = false;
+ looknew->identify = false;
+ looknew->identify_previous_line = false;
+ looknew->ignore = false;
+ looknew->servfail_stops = true;
+ looknew->besteffort = true;
+ looknew->dnssec = false;
+ looknew->ednsflags = 0;
+ looknew->opcode = dns_opcode_query;
+ looknew->expire = false;
+ looknew->nsid = false;
+ looknew->header_only = false;
+ looknew->sendcookie = false;
+ looknew->seenbadcookie = false;
+ looknew->badcookie = true;
+#ifdef WITH_IDN_SUPPORT
+ looknew->idnin = true;
+#else
+ looknew->idnin = false;
+#endif
+#ifdef WITH_IDN_OUT_SUPPORT
+ looknew->idnout = true;
+#else
+ looknew->idnout = false;
+#endif
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = false;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = false;
+ looknew->trace_root_sigchase = false;
+ looknew->rdtype_sigchaseset = false;
+ looknew->rdtype_sigchase = dns_rdatatype_any;
+ looknew->qrdtype_sigchase = dns_rdatatype_any;
+ looknew->rdclass_sigchase = dns_rdataclass_in;
+ looknew->rdclass_sigchaseset = false;
+#endif
+#endif
+ looknew->udpsize = 0;
+ looknew->edns = -1;
+ looknew->recurse = true;
+ looknew->aaonly = false;
+ looknew->adflag = false;
+ looknew->cdflag = false;
+ looknew->print_unknown_format = false;
+ looknew->zflag = false;
+ looknew->ns_search_only = false;
+ looknew->origin = NULL;
+ looknew->tsigctx = NULL;
+ looknew->querysig = NULL;
+ looknew->retries = tries;
+ looknew->nsfound = 0;
+ looknew->tcp_mode = false;
+ looknew->tcp_mode_set = false;
+ looknew->ip6_int = false;
+ looknew->comments = true;
+ looknew->stats = true;
+ looknew->section_question = true;
+ looknew->section_answer = true;
+ looknew->section_authority = true;
+ looknew->section_additional = true;
+ looknew->new_search = false;
+ looknew->done_as_is = false;
+ looknew->need_search = false;
+ looknew->ecs_addr = NULL;
+ looknew->cookie = NULL;
+ looknew->ednsopts = NULL;
+ looknew->ednsoptscnt = 0;
+ looknew->ednsneg = true;
+ looknew->mapped = true;
+ looknew->dscp = -1;
+ looknew->eoferr = 0;
+ dns_fixedname_init(&looknew->fdomain);
+ ISC_LINK_INIT(looknew, link);
+ ISC_LIST_INIT(looknew->q);
+ ISC_LIST_INIT(looknew->connecting);
+ ISC_LIST_INIT(looknew->my_server_list);
+ 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);
+ if (looknew->ednsopts == NULL)
+ fatal("out of memory");
+ 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);
+ if (looknew->ednsopts[i].value == NULL)
+ fatal("out of memory");
+ 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();
+ INSIST(looknew != NULL);
+ strlcpy(looknew->textname, lookold->textname, MXNAME);
+#if DIG_SIGCHASE_TD
+ strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
+#endif
+ 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->dnssec = lookold->dnssec;
+ looknew->ednsflags = lookold->ednsflags;
+ looknew->opcode = lookold->opcode;
+ looknew->expire = lookold->expire;
+ looknew->nsid = lookold->nsid;
+ looknew->header_only = lookold->header_only;
+ 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->mapped = lookold->mapped;
+ looknew->idnin = lookold->idnin;
+ looknew->idnout = lookold->idnout;
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = lookold->sigchase;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = lookold->do_topdown;
+ looknew->trace_root_sigchase = lookold->trace_root_sigchase;
+ looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
+ looknew->rdtype_sigchase = lookold->rdtype_sigchase;
+ looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
+ looknew->rdclass_sigchase = lookold->rdclass_sigchase;
+ looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
+#endif
+#endif
+ 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->print_unknown_format = lookold->print_unknown_format;
+ looknew->zflag = lookold->zflag;
+ looknew->ns_search_only = lookold->ns_search_only;
+ looknew->tcp_mode = lookold->tcp_mode;
+ looknew->tcp_mode_set = lookold->tcp_mode_set;
+ 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->dscp = lookold->dscp;
+ looknew->eoferr = lookold->eoferr;
+
+ if (lookold->ecs_addr != NULL) {
+ size_t len = sizeof(isc_sockaddr_t);
+ looknew->ecs_addr = isc_mem_allocate(mctx, len);
+ if (looknew->ecs_addr == NULL)
+ fatal("out of memory");
+ memmove(looknew->ecs_addr, lookold->ecs_addr, len);
+ }
+
+ dns_name_copy(dns_fixedname_name(&lookold->fdomain),
+ dns_fixedname_name(&looknew->fdomain), NULL);
+
+ if (servers)
+ clone_server_list(lookold->my_server_list,
+ &looknew->my_server_list);
+ 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;
+
+ 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()");
+ result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
+ check_result(result, "isc_buffer_allocate");
+ dns_name_init(&keyname, NULL);
+ check_result(result, "dns_name_init");
+ isc_buffer_putstr(namebuf, keynametext);
+ secretsize = (unsigned int) strlen(keysecret) * 3 / 4;
+ secretstore = isc_mem_allocate(mctx, secretsize);
+ if (secretstore == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ 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));
+ if (sa == NULL)
+ fatal("out of memory");
+ 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;
+
+#ifndef PK11_MD5_DISABLE
+ 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
+#endif
+ 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()");
+
+ /* 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)) {
+#ifndef PK11_MD5_DISABLE
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+#endif
+ 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;
+ default:
+ printf(";; Couldn't create key %s: bad algorithm\n",
+ keynametext);
+ goto failure;
+ }
+ 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;
+ }
+ 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));
+ if (search == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ 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(lwres_conf_t *confdata) {
+ int i;
+ dig_searchlist_t *search;
+
+ debug("create_search_list()");
+ clear_searchlist();
+
+ for (i = 0; i < confdata->searchnxt; i++) {
+ search = make_searchlist_entry(confdata->search[i]);
+ ISC_LIST_APPEND(search_list, search, link);
+ }
+}
+
+/*%
+ * Setup the system as a whole, reading key information and resolv.conf
+ * settings.
+ */
+void
+setup_system(bool ipv4only, bool ipv6only) {
+ dig_searchlist_t *domain = NULL;
+ lwres_result_t lwresult;
+ unsigned int lwresflags;
+ 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");
+ }
+ }
+
+ lwresflags = LWRES_CONTEXT_SERVERMODE;
+ if (have_ipv4)
+ lwresflags |= LWRES_CONTEXT_USEIPV4;
+ if (have_ipv6)
+ lwresflags |= LWRES_CONTEXT_USEIPV6;
+
+ lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
+ lwresflags);
+ if (lwresult != LWRES_R_SUCCESS)
+ fatal("lwres_context_create failed");
+
+ lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
+ if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
+ fatal("parse of %s failed", RESOLV_CONF);
+
+ lwconf = lwres_conf_get(lwctx);
+
+ /* Make the search list */
+ if (lwconf->searchnxt > 0)
+ create_search_list(lwconf);
+ else { /* No search list. Use the domain name if any */
+ if (lwconf->domainname != NULL) {
+ domain = make_searchlist_entry(lwconf->domainname);
+ ISC_LIST_APPEND(search_list, domain, link);
+ domain = NULL;
+ }
+ }
+
+ if (lwconf->resdebug) {
+ verbose = true;
+ debug("verbose is on");
+ }
+ if (ndots == -1) {
+ ndots = lwconf->ndots;
+ debug("ndots is %d.", ndots);
+ }
+ if (lwconf->attempts) {
+ tries = lwconf->attempts + 1;
+ if (tries < 2)
+ tries = 2;
+ debug("tries is %d.", tries);
+ }
+ if (lwconf->timeout) {
+ timeout = lwconf->timeout;
+ debug("timeout is %d.", timeout);
+ }
+
+ /* If user doesn't specify server use nameservers from resolv.conf. */
+ if (ISC_LIST_EMPTY(server_list))
+ copy_server_list(lwconf, &server_list);
+
+ /* If we don't find a nameserver fall back to localhost */
+ if (ISC_LIST_EMPTY(server_list)) {
+ if (have_ipv4) {
+ lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
+ if (lwresult != ISC_R_SUCCESS)
+ fatal("add_nameserver failed");
+ }
+ if (have_ipv6) {
+ lwresult = add_nameserver(lwconf, "::1", AF_INET6);
+ if (lwresult != ISC_R_SUCCESS)
+ fatal("add_nameserver failed");
+ }
+
+ copy_server_list(lwconf, &server_list);
+ }
+
+#ifdef HAVE_SETLOCALE
+ /* Set locale */
+ (void)setlocale(LC_ALL, "");
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+ idn_initialize();
+#endif
+
+#ifdef WITH_IDN_OUT_SUPPORT
+ /* Set domain name -> text post-conversion filter. */
+ result = dns_name_settotextfilter(output_filter);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+ setup_text_key();
+#ifdef DIG_SIGCHASE
+ /* Setup the list of messages for +sigchase */
+ ISC_LIST_INIT(chase_message_list);
+ ISC_LIST_INIT(chase_message_list2);
+ dns_name_init(&chase_name, NULL);
+#if DIG_SIGCHASE_TD
+ dns_name_init(&chase_current_name, NULL);
+ dns_name_init(&chase_authority_name, NULL);
+#endif
+#if DIG_SIGCHASE_BU
+ dns_name_init(&chase_signame, NULL);
+#endif
+
+#endif
+ result = isc_entropy_getdata(entp, cookie_secret,
+ sizeof(cookie_secret), NULL, 0);
+ if (result != ISC_R_SUCCESS)
+ fatal("unable to generate 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()");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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");
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create");
+ isc_mem_setname(mctx, "dig", NULL);
+
+ result = isc_log_create(mctx, &lctx, &logconfig);
+ check_result(result, "isc_log_create");
+
+ 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);
+
+ result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_create");
+
+ result = isc_task_create(taskmgr, 0, &global_task);
+ check_result(result, "isc_task_create");
+ isc_task_setname(global_task, "dig", NULL);
+
+ result = isc_timermgr_create(mctx, &timermgr);
+ check_result(result, "isc_timermgr_create");
+
+ result = isc_socketmgr_create(mctx, &socketmgr);
+ check_result(result, "isc_socketmgr_create");
+
+ result = isc_entropy_create(mctx, &entp);
+ check_result(result, "isc_entropy_create");
+
+ result = dst_lib_init(mctx, entp, 0);
+ check_result(result, "dst_lib_init");
+ is_dst_up = true;
+
+ result = isc_mempool_create(mctx, COMMSIZE, &commctx);
+ check_result(result, "isc_mempool_create");
+ isc_mempool_setname(commctx, "COMMPOOL");
+ /*
+ * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
+ * systems.
+ */
+ isc_mempool_setfreemax(commctx, 6);
+ isc_mempool_setfillcount(commctx, 2);
+
+ result = isc_mutex_init(&lookup_lock);
+ check_result(result, "isc_mutex_init");
+}
+
+typedef struct dig_ednsoptname {
+ uint32_t code;
+ const char *name;
+} dig_ednsoptname_t;
+
+dig_ednsoptname_t optnames[] = {
+ { 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 */
+ { 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);
+ }
+
+ 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);
+ if (buf == NULL)
+ fatal("out of memory");
+ 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) {
+ debug("check_if_done()");
+ debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
+ if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
+ sendcount == 0) {
+ INSIST(sockcount == 0);
+ INSIST(recvcount == 0);
+ debug("shutting down");
+ dighost_shutdown();
+ }
+}
+
+/*%
+ * Clear out a query when we're done with it. WARNING: This routine
+ * WILL invalidate the query pointer.
+ */
+static void
+clear_query(dig_query_t *query) {
+ dig_lookup_t *lookup;
+
+ REQUIRE(query != NULL);
+
+ debug("clear_query(%p)", query);
+
+ if (query->timer != NULL)
+ isc_timer_detach(&query->timer);
+ lookup = query->lookup;
+
+ if (lookup->current_query == query)
+ lookup->current_query = NULL;
+
+ if (ISC_LINK_LINKED(query, link))
+ ISC_LIST_UNLINK(lookup->q, query, link);
+ if (ISC_LINK_LINKED(query, clink))
+ ISC_LIST_UNLINK(lookup->connecting, query, clink);
+ if (ISC_LINK_LINKED(&query->recvbuf, link))
+ ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
+ link);
+ if (ISC_LINK_LINKED(&query->lengthbuf, link))
+ ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
+ link);
+ INSIST(query->recvspace != NULL);
+
+ if (query->sock != NULL) {
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ }
+ isc_mempool_put(commctx, query->recvspace);
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_invalidate(&query->lengthbuf);
+ if (query->waiting_senddone)
+ query->pending_free = true;
+ else
+ isc_mem_free(mctx, query);
+}
+
+/*%
+ * Try and clear out a lookup if we're done with it. Return true if
+ * the lookup was successfully cleared. If true is returned, the
+ * lookup pointer has been invalidated.
+ */
+static bool
+try_clear_lookup(dig_lookup_t *lookup) {
+ dig_query_t *q;
+
+ REQUIRE(lookup != NULL);
+
+ debug("try_clear_lookup(%p)", lookup);
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL ||
+ ISC_LIST_HEAD(lookup->connecting) != NULL)
+ {
+ if (debugging) {
+ q = ISC_LIST_HEAD(lookup->q);
+ while (q != NULL) {
+ debug("query to %s still pending", q->servname);
+ q = ISC_LIST_NEXT(q, link);
+ }
+
+ q = ISC_LIST_HEAD(lookup->connecting);
+ while (q != NULL) {
+ debug("query to %s still connecting",
+ q->servname);
+ q = ISC_LIST_NEXT(q, clink);
+ }
+ }
+ return (false);
+ }
+
+ /*
+ * At this point, we know there are no queries on the lookup,
+ * so can make it go away also.
+ */
+ destroy_lookup(lookup);
+ return (true);
+}
+
+void
+destroy_lookup(dig_lookup_t *lookup) {
+ dig_server_t *s;
+ void *ptr;
+
+ debug("destroy");
+ 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_destroy(&lookup->sendmsg);
+ if (lookup->querysig != NULL) {
+ debug("freeing buffer %p", lookup->querysig);
+ isc_buffer_free(&lookup->querysig);
+ }
+ if (lookup->sendspace != NULL)
+ isc_mempool_put(commctx, lookup->sendspace);
+
+ 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);
+ }
+
+ isc_mem_free(mctx, lookup);
+}
+
+/*%
+ * 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 (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) {
+ ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
+#if DIG_SIGCHASE_TD
+ if (current_lookup->do_topdown &&
+ !current_lookup->rdtype_sigchaseset) {
+ dst_key_t *dstkey = NULL;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ dns_name_t query_name;
+ dns_name_t *key_name;
+ int i;
+
+ result = get_trusted_key();
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No trusted key, "
+ "+sigchase option is disabled\n");
+ current_lookup->sigchase = false;
+ goto novalidation;
+ }
+ dns_name_init(&query_name, NULL);
+ nameFromString(current_lookup->textname, &query_name);
+
+ for (i = 0; i < tk_list.nb_tk; i++) {
+ key_name = dst_key_name(tk_list.key[i]);
+
+ if (dns_name_issubdomain(&query_name,
+ key_name) == true)
+ dstkey = tk_list.key[i];
+ /*
+ * Verify temp is really the lowest
+ * WARNING
+ */
+ }
+ if (dstkey == NULL) {
+ printf("\n;; The queried zone: ");
+ dns_name_print(&query_name, stdout);
+ printf(" isn't a subdomain of any Trusted Keys"
+ ": +sigchase option is disable\n");
+ current_lookup->sigchase = false;
+ free_name(&query_name);
+ goto novalidation;
+ }
+ free_name(&query_name);
+
+ current_lookup->rdtype_sigchase
+ = current_lookup->rdtype;
+ current_lookup->rdtype_sigchaseset
+ = current_lookup->rdtypeset;
+ current_lookup->rdtype = dns_rdatatype_ns;
+
+ current_lookup->qrdtype_sigchase
+ = current_lookup->qrdtype;
+ current_lookup->qrdtype = dns_rdatatype_ns;
+
+ current_lookup->rdclass_sigchase
+ = current_lookup->rdclass;
+ current_lookup->rdclass_sigchaseset
+ = current_lookup->rdclassset;
+ current_lookup->rdclass = dns_rdataclass_in;
+
+ strlcpy(current_lookup->textnamesigchase,
+ current_lookup->textname, MXNAME);
+
+ current_lookup->trace_root_sigchase = true;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(dst_key_name(dstkey),
+ false, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(current_lookup->textname, (char*)r.base,
+ MXNAME);
+ isc_buffer_free(&b);
+
+ nameFromString(current_lookup->textnamesigchase,
+ &chase_name);
+
+ dns_name_init(&chase_authority_name, NULL);
+ }
+ novalidation:
+#endif
+ if (setup_lookup(current_lookup))
+ do_lookup(current_lookup);
+ else if (next_origin(current_lookup))
+ check_next_lookup(current_lookup);
+ } else {
+ check_if_done();
+ }
+}
+
+/*%
+ * If we can, clear the current lookup and start the next one running.
+ * This calls try_clear_lookup, so may invalidate the lookup pointer.
+ */
+static void
+check_next_lookup(dig_lookup_t *lookup) {
+
+ INSIST(!free_now);
+
+ debug("check_next_lookup(%p)", lookup);
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL) {
+ debug("still have a worker");
+ return;
+ }
+ if (try_clear_lookup(lookup)) {
+ current_lookup = NULL;
+ start_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)
+ printf(";; BAD (HORIZONTAL) REFERRAL\n");
+ horizontal = true;
+ } else if (namereln != dns_namereln_subdomain) {
+ if (!bad)
+ printf(";; BAD REFERRAL\n");
+ 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, NULL);
+ }
+ 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);
+ isc_random_get(&j);
+ j %= 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_init(soaname, NULL);
+ 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);
+}
+
+/*%
+ * 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;
+ uint32_t id;
+ 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;
+#ifdef WITH_IDN_SUPPORT
+ char idn_origin[MXNAME], idn_textname[MXNAME];
+#endif
+
+#ifdef WITH_IDN_OUT_SUPPORT
+ result = dns_name_settotextfilter(lookup->idnout ?
+ output_filter : NULL);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+
+ REQUIRE(lookup != NULL);
+ INSIST(!free_now);
+
+ debug("setup_lookup(%p)", lookup);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
+ &lookup->sendmsg);
+ check_result(result, "dns_message_create");
+
+ 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");
+ dns_name_init(lookup->name, NULL);
+
+ 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 WITH_IDN_SUPPORT
+ if (lookup->idnin) {
+ result = idn_locale_to_ace(textname, idn_textname, sizeof(idn_textname));
+ check_result(result, "convert textname to IDN encoding");
+ debug("idn_textname: %s", idn_textname);
+ textname = idn_textname;
+ }
+#endif
+
+ /*
+ * 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");
+ dns_name_init(lookup->oname, NULL);
+ /* XXX Helper funct to conv char* to name? */
+ origin = lookup->origin->origin;
+#ifdef WITH_IDN_SUPPORT
+ if (lookup->idnin) {
+ result = idn_locale_to_ace(origin, idn_origin, sizeof(idn_origin));
+ check_result(result, "convert origin to IDN encoding");
+ debug("trying idn origin %s", idn_origin);
+ origin = idn_origin;
+ }
+#endif
+ 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 &&
+ !dns_name_isabsolute(name))
+ result = dns_name_concatenate(name,
+ lookup->oname,
+ lookup->name,
+ &lookup->namebuf);
+ else if (result == ISC_R_SUCCESS)
+ result = dns_name_copy(name, lookup->name,
+ &lookup->namebuf);
+ 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);
+ fatal("'%s' is not a legal name "
+ "(%s)", lookup->textname,
+ isc_result_totext(result));
+ }
+ }
+ dns_name_format(lookup->name, store, sizeof(store));
+ dighost_trying(store, lookup);
+ INSIST(dns_name_isabsolute(lookup->name));
+
+ isc_random_get(&id);
+ lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
+ lookup->sendmsg->opcode = lookup->opcode;
+ lookup->msgcounter = 0;
+ /*
+ * If this is a trace request, completely disallow recursion, 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->zflag) {
+ debug("Z query");
+ lookup->sendmsg->flags |= 0x0040U;
+ }
+
+ 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");
+ }
+
+ lookup->sendspace = isc_mempool_get(commctx);
+ if (lookup->sendspace == NULL)
+ fatal("memory allocation failure");
+
+ 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 > 0 || 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;
+
+ if (lookup->udpsize == 0)
+ lookup->udpsize = 4096;
+ if (lookup->edns < 0)
+ lookup->edns = 0;
+
+ 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;
+ 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 send_udp()
+ * or send_tcp_connect() 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:
+ INSIST(0);
+ }
+
+ 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->ednsoptscnt != 0) {
+ INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
+ memmove(&opts[i], lookup->ednsopts,
+ sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
+ i += lookup->ednsoptscnt;
+ }
+
+ 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 = isc_mem_allocate(mctx, sizeof(dig_query_t));
+ if (query == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ debug("create query %p linked to lookup %p",
+ query, lookup);
+ query->lookup = lookup;
+ query->timer = NULL;
+ query->waiting_connect = false;
+ query->waiting_senddone = false;
+ query->pending_free = false;
+ query->recv_made = false;
+ query->first_pass = true;
+ query->first_soa_rcvd = false;
+ query->second_rr_rcvd = false;
+ query->first_repeat_rcvd = false;
+ query->warn_id = true;
+ query->timedout = false;
+ query->first_rr_serial = 0;
+ query->second_rr_serial = 0;
+ query->servname = serv->servername;
+ query->userarg = serv->userarg;
+ query->rr_count = 0;
+ query->msg_count = 0;
+ query->byte_count = 0;
+ query->ixfr_axfr = false;
+ ISC_LIST_INIT(query->recvlist);
+ ISC_LIST_INIT(query->lengthlist);
+ query->sock = NULL;
+ query->recvspace = isc_mempool_get(commctx);
+ if (query->recvspace == NULL)
+ fatal("memory allocation failure");
+
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
+ isc_buffer_init(&query->slbuf, query->slspace, 2);
+ query->sendbuf = lookup->renderbuf;
+
+ ISC_LINK_INIT(query, clink);
+ ISC_LINK_INIT(query, link);
+ ISC_LIST_ENQUEUE(lookup->q, query, link);
+ }
+
+ /* XXX qrflag, print_query, etc... */
+ if (!ISC_LIST_EMPTY(lookup->q) && qr) {
+ extrabytes = 0;
+ dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
+ true);
+ if (lookup->stats)
+ printf(";; QUERY SIZE: %u\n\n",
+ isc_buffer_usedlength(&lookup->renderbuf));
+ }
+ return (true);
+}
+
+/*%
+ * Event handler for send completion. Track send counter, and clear out
+ * the query if the send was canceled.
+ */
+static void
+send_done(isc_task_t *_task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_buffer_t *b = NULL;
+ dig_query_t *query, *next;
+ dig_lookup_t *l;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ UNUSED(_task);
+
+ LOCK_LOOKUP;
+
+ debug("send_done()");
+ sendcount--;
+ debug("sendcount=%d", sendcount);
+ INSIST(sendcount >= 0);
+
+ for (b = ISC_LIST_HEAD(sevent->bufferlist);
+ b != NULL;
+ b = ISC_LIST_HEAD(sevent->bufferlist)) {
+ ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+ isc_mem_free(mctx, b);
+ }
+
+ query = event->ev_arg;
+ query->waiting_senddone = false;
+ l = query->lookup;
+
+ if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
+ debug("sending next, since searching");
+ next = ISC_LIST_NEXT(query, link);
+ if (next != NULL)
+ send_udp(next);
+ }
+
+ isc_event_free(&event);
+
+ if (query->pending_free)
+ isc_mem_free(mctx, query);
+
+ check_if_done();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
+ * IO sockets. The cancel handlers should take care of cleaning up the
+ * query and lookup structures
+ */
+static void
+cancel_lookup(dig_lookup_t *lookup) {
+ dig_query_t *query, *next;
+
+ debug("cancel_lookup()");
+ query = ISC_LIST_HEAD(lookup->q);
+ while (query != NULL) {
+ next = ISC_LIST_NEXT(query, link);
+ if (query->sock != NULL) {
+ isc_socket_cancel(query->sock, global_task,
+ ISC_SOCKCANCEL_ALL);
+ check_if_done();
+ } else {
+ clear_query(query);
+ }
+ query = next;
+ }
+ lookup->pending = false;
+ lookup->retries = 0;
+}
+
+static void
+bringup_timer(dig_query_t *query, unsigned int default_timeout) {
+ dig_lookup_t *l;
+ unsigned int local_timeout;
+ isc_result_t result;
+
+ debug("bringup_timer()");
+ /*
+ * If the timer already exists, that means we're calling this
+ * a second time (for a retry). Don't need to recreate it,
+ * just reset it.
+ */
+ l = query->lookup;
+ if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL)
+ local_timeout = SERVER_TIMEOUT;
+ else {
+ if (timeout == 0)
+ local_timeout = default_timeout;
+ else
+ local_timeout = timeout;
+ }
+ debug("have local timeout of %d", local_timeout);
+ isc_interval_set(&l->interval, local_timeout, 0);
+ if (query->timer != NULL)
+ isc_timer_detach(&query->timer);
+ result = isc_timer_create(timermgr, isc_timertype_once, NULL,
+ &l->interval, global_task, connect_timeout,
+ query, &query->timer);
+ check_result(result, "isc_timer_create");
+}
+
+static void
+force_timeout(dig_query_t *query) {
+ isc_event_t *event;
+
+ debug("force_timeout ()");
+ event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
+ connect_timeout, query,
+ sizeof(isc_event_t));
+ if (event == NULL) {
+ fatal("isc_event_allocate: %s",
+ isc_result_totext(ISC_R_NOMEMORY));
+ }
+ isc_task_send(global_task, &event);
+
+ /*
+ * The timer may have expired if, for example, get_address() takes
+ * long time and the timer was running on a different thread.
+ * We need to cancel the possible timeout event not to confuse
+ * ourselves due to the duplicate events.
+ */
+ if (query->timer != NULL)
+ isc_timer_detach(&query->timer);
+}
+
+
+static void
+connect_done(isc_task_t *task, isc_event_t *event);
+
+/*%
+ * Unlike send_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
+send_tcp_connect(dig_query_t *query) {
+ isc_result_t result;
+ dig_query_t *next;
+ dig_lookup_t *l;
+
+ debug("send_tcp_connect(%p)", query);
+
+ l = query->lookup;
+ query->waiting_connect = true;
+ query->lookup->current_query = query;
+ 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_timeout(query);
+ return;
+ }
+
+ if (!l->mapped && 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));
+ printf(";; Skipping mapped address '%s'\n", buf);
+
+ query->waiting_connect = false;
+ if (ISC_LINK_LINKED(query, link))
+ next = ISC_LIST_NEXT(query, link);
+ else
+ next = NULL;
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ return;
+ }
+ send_tcp_connect(next);
+ return;
+ }
+
+ if (specified_source &&
+ (isc_sockaddr_pf(&query->sockaddr) !=
+ isc_sockaddr_pf(&bind_address))) {
+ printf(";; Skipping server %s, incompatible "
+ "address family\n", query->servname);
+ query->waiting_connect = false;
+ if (ISC_LINK_LINKED(query, link))
+ next = ISC_LIST_NEXT(query, link);
+ else
+ next = NULL;
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ return;
+ }
+ send_tcp_connect(next);
+ return;
+ }
+
+ INSIST(query->sock == NULL);
+
+ if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
+ sockcount++;
+ isc_socket_attach(keep, &query->sock);
+ query->waiting_connect = false;
+ launch_next_query(query, true);
+ goto search;
+ }
+
+ result = isc_socket_create(socketmgr,
+ isc_sockaddr_pf(&query->sockaddr),
+ isc_sockettype_tcp, &query->sock);
+ check_result(result, "isc_socket_create");
+ sockcount++;
+ debug("sockcount=%d", sockcount);
+ if (query->lookup->dscp != -1)
+ isc_socket_dscp(query->sock, query->lookup->dscp);
+ isc_socket_ipv6only(query->sock, !query->lookup->mapped);
+ if (specified_source)
+ result = isc_socket_bind(query->sock, &bind_address,
+ ISC_SOCKET_REUSEADDRESS);
+ else {
+ if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
+ have_ipv4)
+ isc_sockaddr_any(&bind_any);
+ else
+ isc_sockaddr_any6(&bind_any);
+ result = isc_socket_bind(query->sock, &bind_any, 0);
+ }
+ check_result(result, "isc_socket_bind");
+ bringup_timer(query, TCP_TIMEOUT);
+ result = isc_socket_connect(query->sock, &query->sockaddr,
+ global_task, connect_done, query);
+ check_result(result, "isc_socket_connect");
+ search:
+ /*
+ * If we're at the endgame of a nameserver search, we need to
+ * immediately bring up all the queries. Do it here.
+ */
+ if (l->ns_search_only && !l->trace_root) {
+ debug("sending next, since searching");
+ if (ISC_LINK_LINKED(query, link)) {
+ next = ISC_LIST_NEXT(query, link);
+ ISC_LIST_DEQUEUE(l->q, query, link);
+ } else
+ next = NULL;
+ ISC_LIST_ENQUEUE(l->connecting, query, clink);
+ if (next != NULL)
+ send_tcp_connect(next);
+ }
+}
+
+static isc_buffer_t *
+clone_buffer(isc_buffer_t *source) {
+ isc_buffer_t *buffer;
+ buffer = isc_mem_allocate(mctx, sizeof(*buffer));
+ if (buffer == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ *buffer = *source;
+ return (buffer);
+}
+
+/*%
+ * 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
+send_udp(dig_query_t *query) {
+ dig_lookup_t *l = NULL;
+ isc_result_t result;
+ isc_buffer_t *sendbuf;
+ dig_query_t *next;
+
+ debug("send_udp(%p)", query);
+
+ l = query->lookup;
+ bringup_timer(query, UDP_TIMEOUT);
+ l->current_query = query;
+ debug("working on lookup %p, query %p", query->lookup, query);
+ if (!query->recv_made) {
+ /* XXX Check the sense of this, need assertion? */
+ query->waiting_connect = false;
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result != ISC_R_SUCCESS) {
+ /* This servname doesn't have an address. */
+ force_timeout(query);
+ return;
+ }
+
+ if (!l->mapped &&
+ 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));
+ printf(";; Skipping mapped address '%s'\n", buf);
+
+ next = ISC_LIST_NEXT(query, link);
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ } else {
+ send_udp(next);
+ }
+ return;
+ }
+
+ result = isc_socket_create(socketmgr,
+ isc_sockaddr_pf(&query->sockaddr),
+ isc_sockettype_udp, &query->sock);
+ check_result(result, "isc_socket_create");
+ sockcount++;
+ debug("sockcount=%d", sockcount);
+ if (query->lookup->dscp != -1)
+ isc_socket_dscp(query->sock, query->lookup->dscp);
+ isc_socket_ipv6only(query->sock,
+ !query->lookup->mapped);
+ if (specified_source) {
+ result = isc_socket_bind(query->sock, &bind_address,
+ ISC_SOCKET_REUSEADDRESS);
+ } else {
+ isc_sockaddr_anyofpf(&bind_any,
+ isc_sockaddr_pf(&query->sockaddr));
+ result = isc_socket_bind(query->sock, &bind_any, 0);
+ }
+ check_result(result, "isc_socket_bind");
+
+ query->recv_made = true;
+ ISC_LINK_INIT(&query->recvbuf, link);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
+ link);
+ debug("recving with lookup=%p, query=%p, sock=%p",
+ query->lookup, query, query->sock);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("recvcount=%d", recvcount);
+ }
+ ISC_LIST_INIT(query->sendlist);
+ sendbuf = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
+ debug("sending a request");
+ TIME_NOW(&query->time_sent);
+ INSIST(query->sock != NULL);
+ query->waiting_senddone = true;
+ result = isc_socket_sendtov2(query->sock, &query->sendlist,
+ global_task, send_done, query,
+ &query->sockaddr, NULL,
+ ISC_SOCKFLAG_NORETRY);
+ check_result(result, "isc_socket_sendtov");
+ sendcount++;
+}
+
+/*%
+ * IO timeout handler, used for both connect and recv timeouts. If
+ * retries are still allowed, either resend the UDP packet or queue a
+ * new TCP lookup. Otherwise, cancel the lookup.
+ */
+static void
+connect_timeout(isc_task_t *task, isc_event_t *event) {
+ dig_lookup_t *l = NULL;
+ dig_query_t *query = NULL, *cq;
+
+ UNUSED(task);
+ REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
+
+ debug("connect_timeout()");
+
+ LOCK_LOOKUP;
+ query = event->ev_arg;
+ l = query->lookup;
+ isc_event_free(&event);
+
+ INSIST(!free_now);
+
+ if ((query != NULL) && (query->lookup->current_query != NULL) &&
+ ISC_LINK_LINKED(query->lookup->current_query, link) &&
+ (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
+ debug("trying next server...");
+ cq = query->lookup->current_query;
+ if (!l->tcp_mode)
+ send_udp(ISC_LIST_NEXT(cq, link));
+ else {
+ if (query->sock != NULL)
+ isc_socket_cancel(query->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ send_tcp_connect(ISC_LIST_NEXT(cq, link));
+ }
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (l->tcp_mode && query->sock != NULL) {
+ query->timedout = true;
+ isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL);
+ }
+
+ if (l->retries > 1) {
+ if (!l->tcp_mode) {
+ l->retries--;
+ debug("resending UDP request to first server");
+ send_udp(ISC_LIST_HEAD(l->q));
+ } else {
+ debug("making new TCP request, %d tries left",
+ l->retries);
+ l->retries--;
+ requeue_lookup(l, true);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+ if (!l->ns_search_only) {
+ fputs(l->cmdline, stdout);
+ printf(";; connection timed out; no servers could be "
+ "reached\n");
+ }
+ cancel_lookup(l);
+ check_next_lookup(l);
+ if (exitcode < 9)
+ exitcode = 9;
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Event handler for the TCP recv which gets the length header of TCP
+ * packets. Start the next recv of length bytes.
+ */
+static void
+tcp_length_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent;
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ dig_query_t *query = NULL;
+ dig_lookup_t *l, *n;
+ uint16_t length;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ INSIST(!free_now);
+
+ UNUSED(task);
+
+ debug("tcp_length_done()");
+
+ LOCK_LOOKUP;
+ sevent = (isc_socketevent_t *)event;
+ query = event->ev_arg;
+
+ recvcount--;
+ INSIST(recvcount >= 0);
+
+ b = ISC_LIST_HEAD(sevent->bufferlist);
+ INSIST(b == &query->lengthbuf);
+ ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+
+ if (sevent->result == ISC_R_CANCELED) {
+ isc_event_free(&event);
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (sevent->result != ISC_R_SUCCESS) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+ printf(";; communications error to %s: %s\n",
+ sockstr, isc_result_totext(sevent->result));
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ l = query->lookup;
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
+ n = requeue_lookup(l, true);
+ n->eoferr++;
+ }
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ length = isc_buffer_getuint16(b);
+ if (length == 0) {
+ isc_event_free(&event);
+ launch_next_query(query, false);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ /*
+ * Even though the buffer was already init'ed, we need
+ * to redo it now, to force the length we want.
+ */
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, length);
+ ENSURE(ISC_LIST_EMPTY(query->recvlist));
+ ISC_LINK_INIT(&query->recvbuf, link);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ debug("recving with lookup=%p, query=%p", query->lookup, query);
+ result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
+ recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("resubmitted recv request with length %d, recvcount=%d",
+ length, recvcount);
+ isc_event_free(&event);
+ 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, bool include_question) {
+ isc_result_t result;
+ dig_lookup_t *l;
+ isc_buffer_t *buffer;
+
+ INSIST(!free_now);
+
+ debug("launch_next_query()");
+
+ if (!query->lookup->pending) {
+ debug("ignoring launch_next_query because !pending");
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ query->waiting_connect = false;
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ return;
+ }
+
+ isc_buffer_clear(&query->slbuf);
+ isc_buffer_clear(&query->lengthbuf);
+ isc_buffer_putuint16(&query->slbuf, (uint16_t) query->sendbuf.used);
+ ISC_LIST_INIT(query->sendlist);
+ ISC_LINK_INIT(&query->slbuf, link);
+ if (!query->first_soa_rcvd) {
+ buffer = clone_buffer(&query->slbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ if (include_question) {
+ buffer = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ }
+ }
+
+ ISC_LINK_INIT(&query->lengthbuf, link);
+ ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
+
+ result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
+ global_task, tcp_length_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("recvcount=%d", recvcount);
+ if (!query->first_soa_rcvd) {
+ debug("sending a request in launch_next_query");
+ TIME_NOW(&query->time_sent);
+ query->waiting_senddone = true;
+ result = isc_socket_sendv(query->sock, &query->sendlist,
+ global_task, send_done, query);
+ check_result(result, "isc_socket_sendv");
+ sendcount++;
+ debug("sendcount=%d", sendcount);
+ }
+ query->waiting_connect = false;
+#if 0
+ check_next_lookup(query->lookup);
+#endif
+ 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
+connect_done(isc_task_t *task, isc_event_t *event) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ isc_socketevent_t *sevent = NULL;
+ dig_query_t *query = NULL, *next;
+ dig_lookup_t *l;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+ INSIST(!free_now);
+
+ debug("connect_done()");
+
+ LOCK_LOOKUP;
+ sevent = (isc_socketevent_t *)event;
+ query = sevent->ev_arg;
+
+ INSIST(query->waiting_connect);
+
+ query->waiting_connect = false;
+
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in cancel handler");
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ if (query->timedout)
+ printf(";; Connection to %s(%s) for %s failed: %s.\n",
+ sockstr, query->servname,
+ query->lookup->textname,
+ isc_result_totext(ISC_R_TIMEDOUT));
+ isc_socket_detach(&query->sock);
+ INSIST(sockcount > 0);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = false;
+ isc_event_free(&event);
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (sevent->result != ISC_R_SUCCESS) {
+
+ debug("unsuccessful connection: %s",
+ isc_result_totext(sevent->result));
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ if (sevent->result != ISC_R_CANCELED)
+ printf(";; Connection to %s(%s) for %s failed: "
+ "%s.\n", sockstr,
+ query->servname, query->lookup->textname,
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&query->sock);
+ INSIST(sockcount > 0);
+ sockcount--;
+ /* XXX Clean up exitcodes */
+ if (exitcode < 9)
+ exitcode = 9;
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = false;
+ isc_event_free(&event);
+ l = query->lookup;
+ if ((l->current_query != NULL) &&
+ (ISC_LINK_LINKED(l->current_query, link)))
+ next = ISC_LIST_NEXT(l->current_query, link);
+ else
+ next = NULL;
+ clear_query(query);
+ if (next != NULL) {
+ bringup_timer(next, TCP_TIMEOUT);
+ send_tcp_connect(next);
+ } else
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ exitcode = 0;
+ if (keep_open) {
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ isc_socket_attach(query->sock, &keep);
+ keepaddr = query->sockaddr;
+ }
+ launch_next_query(query, true);
+ isc_event_free(&event);
+ 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_query_t *query, dns_message_t *msg,
+ isc_socketevent_t *sevent)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
+ isc_result_t result;
+ bool ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
+ bool axfr = query->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 += sevent->n;
+ 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);
+ launch_next_query(query, false);
+ return (false);
+ doexit:
+ dighost_received(sevent->n, &sevent->address, 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 (optlen >= len && optlen >= 8U) {
+ if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) {
+ msg->cc_ok = 1;
+ } else {
+ printf(";; Warning: Client COOKIE mismatch\n");
+ msg->cc_bad = 1;
+ copy = false;
+ }
+ } else {
+ printf(";; Warning: COOKIE bad token (too short)\n");
+ 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_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = NULL;
+ dig_query_t *query = NULL;
+ isc_buffer_t *b = NULL;
+ dns_message_t *msg = NULL;
+#ifdef DIG_SIGCHASE
+ dig_message_t *chase_msg = NULL;
+ dig_message_t *chase_msg2 = NULL;
+#endif
+ isc_result_t result;
+ dig_lookup_t *n, *l;
+ bool docancel = false;
+ bool match = true;
+ unsigned int parseflags;
+ dns_messageid_t id;
+ unsigned int msgflags;
+#ifdef DIG_SIGCHASE
+ isc_result_t do_sigchase = false;
+
+ dns_message_t *msg_temp = NULL;
+ isc_region_t r;
+ isc_buffer_t *buf = NULL;
+#endif
+ int newedns;
+
+ UNUSED(task);
+ INSIST(!free_now);
+
+ debug("recv_done()");
+
+ LOCK_LOOKUP;
+ recvcount--;
+ debug("recvcount=%d", recvcount);
+ INSIST(recvcount >= 0);
+
+ query = event->ev_arg;
+ TIME_NOW(&query->time_recv);
+ debug("lookup=%p, query=%p", query->lookup, query);
+
+ l = query->lookup;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ sevent = (isc_socketevent_t *)event;
+
+ b = ISC_LIST_HEAD(sevent->bufferlist);
+ INSIST(b == &query->recvbuf);
+ ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
+
+ if ((l->tcp_mode) && (query->timer != NULL))
+ isc_timer_touch(query->timer);
+ if ((!l->pending && !l->ns_search_only) || cancel_now) {
+ debug("no longer pending. Got %s",
+ isc_result_totext(sevent->result));
+ query->waiting_connect = false;
+
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (sevent->result != ISC_R_SUCCESS) {
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in recv cancel handler");
+ query->waiting_connect = false;
+ } else {
+ printf(";; communications error: %s\n",
+ isc_result_totext(sevent->result));
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ }
+ if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
+ n = requeue_lookup(l, true);
+ n->eoferr++;
+ }
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (!l->tcp_mode &&
+ !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
+ ISC_SOCKADDR_CMPADDR|
+ ISC_SOCKADDR_CMPPORT|
+ ISC_SOCKADDR_CMPSCOPE|
+ ISC_SOCKADDR_CMPSCOPEZERO)) {
+ char buf1[ISC_SOCKADDR_FORMATSIZE];
+ char buf2[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t any;
+
+ if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
+ isc_sockaddr_any(&any);
+ else
+ isc_sockaddr_any6(&any);
+
+ /*
+ * We don't expect a match when the packet is
+ * sent to 0.0.0.0, :: or to a multicast addresses.
+ * XXXMPA broadcast needs to be handled here as well.
+ */
+ if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
+ !isc_sockaddr_ismulticast(&query->sockaddr)) ||
+ isc_sockaddr_getport(&query->sockaddr) !=
+ isc_sockaddr_getport(&sevent->address)) {
+ isc_sockaddr_format(&sevent->address, buf1,
+ sizeof(buf1));
+ isc_sockaddr_format(&query->sockaddr, buf2,
+ sizeof(buf2));
+ printf(";; reply from unexpected source: %s,"
+ " expected %s\n", buf1, buf2);
+ match = false;
+ }
+ }
+
+ 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)
+ printf(";; %s: ID mismatch: "
+ "expected ID %u, got %u\n",
+ query->first_soa_rcvd ?
+ "WARNING" : "ERROR",
+ l->sendmsg->id, id);
+ if (query->first_soa_rcvd)
+ fail = false;
+ query->warn_id = false;
+ } else
+ printf(";; ERROR: short "
+ "(< header size) message\n");
+ if (fail) {
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ match = true;
+ } else if (result == ISC_R_SUCCESS)
+ printf(";; Warning: ID mismatch: "
+ "expected ID %u, got %u\n", l->sendmsg->id, id);
+ else
+ printf(";; Warning: short "
+ "(< header size) message received\n");
+ }
+
+ if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
+ printf(";; Warning: query response not set\n");
+
+ if (!match)
+ goto udp_mismatch;
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
+ check_result(result, "dns_message_create");
+
+ 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 = DNS_MESSAGEPARSE_PRESERVEORDER;
+#ifdef DIG_SIGCHASE
+ if (!l->sigchase) {
+ do_sigchase = false;
+ } else {
+ parseflags = 0;
+ do_sigchase = true;
+ }
+#endif
+ if (l->besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+ result = dns_message_parse(msg, b, parseflags);
+ if (result == DNS_R_RECOVERABLE) {
+ printf(";; Warning: Message parser reports malformed "
+ "message packet.\n");
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Got bad packet: %s\n", isc_result_totext(result));
+ hex_dump(b);
+ query->waiting_connect = false;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ 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));
+ printf(";; Question section mismatch: "
+ "got %s/%s/%s\n",
+ namestr, typebuf, classbuf);
+ match = false;
+ }
+ }
+ }
+ if (!match) {
+ dns_message_destroy(&msg);
+ if (l->tcp_mode) {
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ } else
+ goto udp_mismatch;
+ }
+ }
+ 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.
+ */
+ if (l->comments)
+ printf(";; BADVERS, retrying with EDNS version %u.\n",
+ (unsigned int)newedns);
+ l->edns = newedns;
+ n = requeue_lookup(l, true);
+ if (l->trace && l->trace_root)
+ n->rdtype = l->qrdtype;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ 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);
+ if (l->comments)
+ printf(";; Truncated, retrying in TCP mode.\n");
+ n = requeue_lookup(l, true);
+ n->tcp_mode = true;
+ if (l->trace && l->trace_root)
+ n->rdtype = l->qrdtype;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode &&
+ l->sendcookie && l->badcookie) {
+ process_opt(l, msg);
+ if (msg->cc_ok) {
+ if (l->comments)
+ printf(";; BADCOOKIE, retrying%s.\n",
+ 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;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ }
+ 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)
+ l->current_query = NULL;
+ if (next != NULL) {
+ debug("sending query %p\n", next);
+ if (l->tcp_mode)
+ send_tcp_connect(next);
+ else
+ send_udp(next);
+ }
+ /*
+ * If our query is at the head of the list and there
+ * is no next, we're the only one left, so fall
+ * through to print the message.
+ */
+ if ((ISC_LIST_HEAD(l->q) != query) ||
+ (ISC_LIST_NEXT(query, link) != NULL)) {
+ if (l->comments)
+ printf(";; Got %s from %s, "
+ "trying next server\n",
+ msg->rcode == dns_rcode_servfail ?
+ "SERVFAIL reply" :
+ "recursion not available",
+ query->servname);
+ clear_query(query);
+ check_next_lookup(l);
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ }
+
+ if (tsigkey != NULL) {
+ result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't verify signature: %s\n",
+ 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 * 4;
+ else
+ local_timeout = UDP_TIMEOUT * 4;
+ } else {
+ if (timeout < (INT_MAX / 4))
+ local_timeout = timeout * 4;
+ else
+ local_timeout = INT_MAX;
+ }
+ debug("have local timeout of %d", local_timeout);
+ isc_interval_set(&l->interval, local_timeout, 0);
+ result = isc_timer_reset(query->timer,
+ isc_timertype_once,
+ NULL,
+ &l->interval,
+ false);
+ check_result(result, "isc_timer_reset");
+ }
+ }
+
+ if (l->cookie != NULL) {
+ if (msg->opt == NULL)
+ printf(";; expected opt record in response\n");
+ 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(query->lookup) || showsearch) {
+ dighost_printmessage(query, msg, true);
+ dighost_received(b->used, &sevent->address, query);
+ }
+ } else if (!l->trace && !l->ns_search_only) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dighost_printmessage(query, 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, 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
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dighost_printmessage(query, msg, true);
+ }
+#ifdef DIG_SIGCHASE
+ if (do_sigchase) {
+ chase_msg = isc_mem_allocate(mctx,
+ sizeof(dig_message_t));
+ if (chase_msg == NULL) {
+ fatal("Memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ }
+ ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
+ link);
+ if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+ &msg_temp) != ISC_R_SUCCESS) {
+ fatal("dns_message_create in %s:%d",
+ __FILE__, __LINE__);
+ }
+
+ isc_buffer_usedregion(b, &r);
+ result = isc_buffer_allocate(mctx, &buf, r.length);
+
+ check_result(result, "isc_buffer_allocate");
+ result = isc_buffer_copyregion(buf, &r);
+ check_result(result, "isc_buffer_copyregion");
+
+ result = dns_message_parse(msg_temp, buf, 0);
+
+ isc_buffer_free(&buf);
+ chase_msg->msg = msg_temp;
+
+ chase_msg2 = isc_mem_allocate(mctx,
+ sizeof(dig_message_t));
+ if (chase_msg2 == NULL) {
+ fatal("Memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ }
+ ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
+ link);
+ chase_msg2->msg = msg;
+ }
+#endif
+ }
+
+#ifdef DIG_SIGCHASE
+ if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
+ sigchase(msg_temp);
+ }
+#endif
+
+ if (l->pending)
+ debug("still pending.");
+ if (l->doing_xfr) {
+ if (query != l->xfr_q) {
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ query->waiting_connect = false;
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (!docancel)
+ docancel = check_for_more_data(query, msg, sevent);
+ if (docancel) {
+ dns_message_destroy(&msg);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+
+ if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
+
+#ifdef DIG_SIGCHASE
+ if (!l->sigchase)
+#endif
+ dighost_received(b->used, &sevent->address, query);
+ }
+
+ if (!query->lookup->ns_search_only)
+ query->lookup->pending = false;
+ if (!query->lookup->ns_search_only ||
+ query->lookup->trace_root || docancel) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dns_message_destroy(&msg);
+
+ cancel_lookup(l);
+ }
+ clear_query(query);
+ check_next_lookup(l);
+ }
+ if (msg != NULL) {
+#ifdef DIG_SIGCHASE
+ if (do_sigchase)
+ msg = NULL;
+ else
+#endif
+ dns_message_destroy(&msg);
+ }
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+
+ udp_mismatch:
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+}
+
+/*%
+ * 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) {
+ if (lookup->tcp_mode)
+ send_tcp_connect(query);
+ else
+ send_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;
+ }
+ cancel_now = true;
+ if (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);
+ if (q->sock != NULL)
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ else
+ clear_query(q);
+ }
+ for (q = ISC_LIST_HEAD(current_lookup->connecting);
+ q != NULL;
+ q = nq)
+ {
+ nq = ISC_LIST_NEXT(q, clink);
+ debug("canceling connecting query %p, belonging to %p",
+ q, current_lookup);
+ if (q->sock != NULL)
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ else
+ clear_query(q);
+ }
+ }
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ n = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, l, link);
+ try_clear_lookup(l);
+ l = n;
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Destroy all of the libs we are using, and get everything ready for a
+ * clean shutdown.
+ */
+void
+destroy_libs(void) {
+#ifdef DIG_SIGCHASE
+ void * ptr;
+ dig_message_t *chase_msg;
+#endif
+#ifdef WITH_IDN_SUPPORT
+ isc_result_t result;
+#endif
+
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ debug("destroy_libs()");
+ if (global_task != NULL) {
+ debug("freeing task");
+ isc_task_detach(&global_task);
+ }
+ /*
+ * The taskmgr_destroy() call blocks until all events are cleared
+ * from the task.
+ */
+ if (taskmgr != NULL) {
+ debug("freeing taskmgr");
+ isc_taskmgr_destroy(&taskmgr);
+ }
+ LOCK_LOOKUP;
+ REQUIRE(sockcount == 0);
+ REQUIRE(recvcount == 0);
+ REQUIRE(sendcount == 0);
+
+ INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
+ INSIST(current_lookup == NULL);
+ INSIST(!free_now);
+
+ free_now = true;
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ flush_server_list();
+
+ clear_searchlist();
+
+#ifdef WITH_IDN_SUPPORT
+ result = dns_name_settotextfilter(NULL);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+ dns_name_destroy();
+
+ if (commctx != NULL) {
+ debug("freeing commctx");
+ isc_mempool_destroy(&commctx);
+ }
+ if (socketmgr != NULL) {
+ debug("freeing socketmgr");
+ isc_socketmgr_destroy(&socketmgr);
+ }
+ if (timermgr != NULL) {
+ debug("freeing timermgr");
+ isc_timermgr_destroy(&timermgr);
+ }
+ if (tsigkey != NULL) {
+ debug("freeing key %p", tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+ if (namebuf != NULL)
+ isc_buffer_free(&namebuf);
+
+ if (is_dst_up) {
+ debug("destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = false;
+ }
+ if (entp != NULL) {
+ debug("detach from entropy");
+ isc_entropy_detach(&entp);
+ }
+
+ UNLOCK_LOOKUP;
+ DESTROYLOCK(&lookup_lock);
+#ifdef DIG_SIGCHASE
+
+ debug("Destroy the messages kept for sigchase");
+ /* Destroy the messages kept for sigchase */
+ chase_msg = ISC_LIST_HEAD(chase_message_list);
+
+ while (chase_msg != NULL) {
+ INSIST(chase_msg->msg != NULL);
+ dns_message_destroy(&(chase_msg->msg));
+ ptr = chase_msg;
+ chase_msg = ISC_LIST_NEXT(chase_msg, link);
+ isc_mem_free(mctx, ptr);
+ }
+
+ chase_msg = ISC_LIST_HEAD(chase_message_list2);
+
+ while (chase_msg != NULL) {
+ INSIST(chase_msg->msg != NULL);
+ dns_message_destroy(&(chase_msg->msg));
+ ptr = chase_msg;
+ chase_msg = ISC_LIST_NEXT(chase_msg, link);
+ isc_mem_free(mctx, ptr);
+ }
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+#if DIG_SIGCHASE_TD
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name);
+#endif
+#if DIG_SIGCHASE_BU
+ if (dns_name_dynamic(&chase_signame))
+ free_name(&chase_signame);
+#endif
+
+#endif
+ 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 WITH_IDN_OUT_SUPPORT
+static isc_result_t
+output_filter(isc_buffer_t *buffer, unsigned int used_org,
+ bool absolute)
+{
+ char tmp1[MAXDLEN], tmp2[MAXDLEN];
+ size_t fromlen, tolen;
+ bool end_with_dot;
+ isc_result_t result;
+
+ /*
+ * Copy contents of 'buffer' to 'tmp1', supply trailing dot
+ * if 'absolute' is true, and terminate with NUL.
+ */
+ fromlen = isc_buffer_usedlength(buffer) - used_org;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+
+ memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
+ end_with_dot = (tmp1[fromlen - 1] == '.') ? true : false;
+ if (absolute && !end_with_dot) {
+ fromlen++;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+ tmp1[fromlen - 1] = '.';
+ }
+
+ tmp1[fromlen] = '\0';
+
+ /*
+ * Convert contents of 'tmp1' to local encoding.
+ */
+ result = idn_ace_to_locale(tmp1, tmp2, sizeof(tmp2));
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+ /*
+ * Copy the converted contents in 'tmp1' back to 'buffer'.
+ * If we have appended trailing dot, remove it.
+ */
+ tolen = strlen(tmp2);
+ if (absolute && !end_with_dot && tmp2[tolen - 1] == '.')
+ tolen--;
+
+ if (isc_buffer_length(buffer) < used_org + tolen)
+ return (ISC_R_NOSPACE);
+
+ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
+ memmove(isc_buffer_used(buffer), tmp2, tolen);
+ isc_buffer_add(buffer, (unsigned int)tolen);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+#ifdef WITH_IDNKIT
+static void
+idnkit_check_result(idn_result_t result, const char *msg) {
+ if (result != idn_success) {
+ fatal("%s: %s", msg, idn_result_tostring(result));
+ }
+}
+
+static void
+idn_initialize(void) {
+ idn_result_t result;
+
+ /* Create configuration context. */
+ result = idn_nameinit(1);
+ idnkit_check_result(result, "idnkit api initialization failed");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+idn_locale_to_ace(const char *from, char *to, size_t tolen) {
+ char utf8_textname[MXNAME];
+ idn_result_t result;
+
+ result = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, from,
+ utf8_textname, sizeof(utf8_textname));
+ idnkit_check_result(result, "idnkit idn_encodename to utf8 failed");
+
+ result = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
+ IDN_IDNCONV | IDN_LENCHECK,
+ utf8_textname, to, tolen);
+ idnkit_check_result(result, "idnkit idn_encodename to idn failed");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+idn_ace_to_locale(const char *from, char *to, size_t tolen) {
+ idn_result_t result;
+
+ result = idn_decodename(IDN_DECODE_APP, from, to, tolen);
+ if (result != idn_success) {
+ debug("idnkit idn_decodename failed: %s",
+ idn_result_tostring(result));
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+}
+#endif /* WITH_IDNKIT */
+
+#ifdef WITH_LIBIDN2
+static void
+idn_initialize(void) {
+}
+
+static isc_result_t
+idn_locale_to_ace(const char *from, char *to, size_t tolen) {
+ int res;
+ char *tmp_str = NULL;
+
+ res = idn2_to_ascii_lz(from, &tmp_str, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);
+ if (res == IDN2_DISALLOWED) {
+ res = idn2_to_ascii_lz(from, &tmp_str, IDN2_TRANSITIONAL|IDN2_NFC_INPUT);
+ }
+
+ if (res == IDN2_OK) {
+ /*
+ * idn2_to_ascii_lz() normalizes all strings to lowerl 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
+ */
+ if (!strcasecmp(from, tmp_str)) {
+ if (strlen(from) >= tolen) {
+ debug("from string is too long");
+ idn2_free(tmp_str);
+ return ISC_R_NOSPACE;
+ }
+ idn2_free(tmp_str);
+ (void) strlcpy(to, from, tolen);
+ return ISC_R_SUCCESS;
+ }
+ /* check the length */
+ if (strlen(tmp_str) >= tolen) {
+ debug("ACE string is too long");
+ idn2_free(tmp_str);
+ return ISC_R_NOSPACE;
+ }
+
+ (void) strlcpy(to, tmp_str, tolen);
+ idn2_free(tmp_str);
+ return ISC_R_SUCCESS;
+ }
+
+ fatal("'%s' is not a legal IDN name (%s), use +noidnin", from, idn2_strerror(res));
+ return ISC_R_FAILURE;
+}
+
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t
+idn_ace_to_locale(const char *from, char *to, size_t tolen) {
+ int res;
+ char *utf8_src, *tmp_str = NULL;
+
+ /*
+ * We need to:
+ *
+ * 1) check whether 'from' 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 'from', 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 'from' to UTF-8, ignoring the current locale.
+ */
+ res = idn2_to_unicode_8z8z(from, &utf8_src, 0);
+ if (res != IDN2_OK) {
+ fatal("Bad ACE string '%s' (%s), use +noidnout",
+ from, idn2_strerror(res));
+ }
+
+ /*
+ * Then, check whether decoded 'from' is a valid IDNA2008 name.
+ */
+ res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_NONTRANSITIONAL);
+ if (res != IDN2_OK) {
+ fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnout",
+ from, idn2_strerror(res));
+ }
+
+ /*
+ * Finally, try converting the decoded 'from' into the current locale's
+ * character encoding.
+ */
+ res = idn2_to_unicode_8zlz(utf8_src, &tmp_str, 0);
+ if (res != IDN2_OK) {
+ fatal("Cannot represent '%s' in the current locale (%s), "
+ "use +noidnout or a different locale",
+ from, idn2_strerror(res));
+ }
+
+ /*
+ * Free the interim conversion result.
+ */
+ idn2_free(utf8_src);
+
+ /* check the length */
+ if (strlen(tmp_str) >= tolen) {
+ debug("encoded ASC string is too long");
+ idn2_free(tmp_str);
+ return (ISC_R_FAILURE);
+ }
+
+ (void) strlcpy(to, tmp_str, tolen);
+ idn2_free(tmp_str);
+ return (ISC_R_SUCCESS);
+}
+#endif /* WITH_IDN_OUT_SUPPORT */
+#endif /* WITH_LIBIDN2 */
+#endif /* WITH_IDN_SUPPORT */
+
+#ifdef DIG_SIGCHASE
+void
+print_type(dns_rdatatype_t type)
+{
+ isc_buffer_t * b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ result = isc_buffer_allocate(mctx, &b, 4000);
+ check_result(result, "isc_buffer_allocate");
+
+ result = dns_rdatatype_totext(type, b);
+ check_result(result, "print_type");
+
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+
+ printf("%s", r.base);
+
+ isc_buffer_free(&b);
+}
+
+void
+dump_database_section(dns_message_t *msg, int section)
+{
+ dns_name_t *msg_name=NULL;
+
+ dns_rdataset_t *rdataset;
+
+ do {
+ dns_message_currentname(msg, section, &msg_name);
+
+ for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ dns_name_print(msg_name, stdout);
+ printf("\n");
+ print_rdataset(msg_name, rdataset);
+ printf("end\n");
+ }
+ msg_name = NULL;
+ } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+}
+
+void
+dump_database(void) {
+ dig_message_t * msg;
+
+ for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
+ msg = ISC_LIST_NEXT(msg, link)) {
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_ANSWER);
+
+ if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
+
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
+ }
+}
+
+
+dns_rdataset_t *
+search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
+ dns_rdataset_t *rdataset;
+ dns_rdata_sig_t siginfo;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ isc_result_t result;
+
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (type == dns_rdatatype_any) {
+ if (rdataset->type != dns_rdatatype_rrsig)
+ return (rdataset);
+ } else if ((type == dns_rdatatype_rrsig) &&
+ (rdataset->type == dns_rdatatype_rrsig)) {
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "empty rdataset");
+ dns_rdataset_current(rdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if ((siginfo.covered == covers) ||
+ (covers == dns_rdatatype_any)) {
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&siginfo);
+ return (rdataset);
+ }
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&siginfo);
+ } else if (rdataset->type == type)
+ return (rdataset);
+ }
+ return (NULL);
+}
+
+dns_rdataset_t *
+chase_scanname_section(dns_message_t *msg, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ int section)
+{
+ dns_rdataset_t *rdataset;
+ dns_name_t *msg_name = NULL;
+
+ if (msg->counts[section] == 0)
+ return (NULL);
+
+ do {
+ dns_message_currentname(msg, section, &msg_name);
+ if (dns_name_compare(msg_name, name) == 0) {
+ rdataset = search_type(msg_name, type, covers);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ msg_name = NULL;
+ } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+
+ return (NULL);
+}
+
+
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dig_message_t * msg;
+
+ for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
+ msg = ISC_LIST_NEXT(msg, link)) {
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+ == ISC_R_SUCCESS)
+ {
+ rdataset = chase_scanname_section(msg->msg, name,
+ type, covers,
+ DNS_SECTION_ANSWER);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS)
+ {
+ rdataset =
+ chase_scanname_section(msg->msg, name,
+ type, covers,
+ DNS_SECTION_AUTHORITY);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+ == ISC_R_SUCCESS)
+ {
+ rdataset =
+ chase_scanname_section(msg->msg, name, type,
+ covers,
+ DNS_SECTION_ADDITIONAL);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ }
+
+ return (NULL);
+}
+
+dns_rdataset_t *
+sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
+ bool * lookedup, dns_name_t *rdata_name)
+{
+ dig_lookup_t *lookup;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ dns_rdataset_t * temp;
+ dns_rdatatype_t querytype;
+
+ temp = chase_scanname(rdata_name, type, covers);
+ if (temp != NULL)
+ return (temp);
+
+ if (*lookedup == true)
+ return (NULL);
+
+ lookup = clone_lookup(current_lookup, true);
+ lookup->trace_root = false;
+ lookup->new_search = true;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(rdata_name, false, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
+ isc_buffer_free(&b);
+
+ if (type == dns_rdatatype_rrsig)
+ querytype = covers;
+ else
+ querytype = type;
+
+ if (querytype == 0 || querytype == 255) {
+ printf("Error in the queried type: %d\n", querytype);
+ return (NULL);
+ }
+
+ lookup->rdtype = querytype;
+ lookup->rdtypeset = true;
+ lookup->qrdtype = querytype;
+ *lookedup = true;
+
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ printf("\n\nLaunch a query to find a RRset of type ");
+ print_type(type);
+ printf(" for zone: %s\n", lookup->textname);
+ return (NULL);
+}
+
+isc_result_t
+insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ dst_key_t *dstkey;
+
+ UNUSED(arg);
+
+ if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
+ return (ISC_R_SUCCESS);
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+ if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
+ return (ISC_R_SUCCESS);
+ dstkey = NULL;
+ result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ tk_list.key[tk_list.nb_tk++] = dstkey;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+void
+clean_trustedkey()
+{
+ int i = 0;
+
+ for (i= 0; i < MAX_TRUSTED_KEY; i++) {
+ if (tk_list.key[i] != NULL) {
+ dst_key_free(&tk_list.key[i]);
+ tk_list.key[i] = NULL;
+ } else
+ break;
+ }
+ tk_list.nb_tk = 0;
+ return;
+}
+
+char alphnum[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+isc_result_t
+removetmpkey(const char *file)
+{
+ char *tempnamekey = NULL;
+ int tempnamekeylen;
+ isc_result_t result;
+
+ tempnamekeylen = strlen(file)+10;
+
+ tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+ if (tempnamekey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(tempnamekey, 0, tempnamekeylen);
+
+ strcat(tempnamekey, file);
+ strcat(tempnamekey,".key");
+ isc_file_remove(tempnamekey);
+
+ result = isc_file_remove(tempnamekey);
+ isc_mem_free(mctx, tempnamekey);
+ return (result);
+}
+
+isc_result_t
+get_trusted_key(void) {
+ isc_result_t result;
+ const char *filename = NULL;
+ dns_rdatacallbacks_t callbacks;
+
+ result = isc_file_exists(trustedkey);
+ if (result != true) {
+ result = isc_file_exists("/etc/trusted-key.key");
+ if (result != true) {
+ result = isc_file_exists("./trusted-key.key");
+ if (result != true)
+ return (ISC_R_FAILURE);
+ else
+ filename = "./trusted-key.key";
+ } else
+ filename = "/etc/trusted-key.key";
+ } else
+ filename = trustedkey;
+
+ if (filename == NULL) {
+ printf("No trusted key\n");
+ return (ISC_R_FAILURE);
+ }
+
+ dns_rdatacallbacks_init_stdio(&callbacks);
+ callbacks.add = insert_trustedkey;
+ return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
+ current_lookup->rdclass, DNS_MASTER_NOTTL,
+ &callbacks, mctx));
+}
+
+
+static void
+nameFromString(const char *str, dns_name_t *p_ret) {
+ size_t len = strlen(str);
+ isc_result_t result;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixedname;
+
+ REQUIRE(p_ret != NULL);
+ REQUIRE(str != NULL);
+
+ isc_buffer_constinit(&buffer, str, len);
+ isc_buffer_add(&buffer, len);
+
+ dns_fixedname_init(&fixedname);
+ result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
+ dns_rootname, DNS_NAME_DOWNCASE, NULL);
+ check_result(result, "nameFromString");
+
+ if (dns_name_dynamic(p_ret))
+ free_name(p_ret);
+
+ result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
+ check_result(result, "nameFromString");
+}
+
+
+#if DIG_SIGCHASE_TD
+isc_result_t
+prepare_lookup(dns_name_t *name)
+{
+ isc_result_t result;
+ dig_lookup_t *lookup = NULL;
+ dig_server_t *s;
+ void *ptr;
+
+ lookup = clone_lookup(current_lookup, true);
+ lookup->trace_root = false;
+ lookup->new_search = true;
+ lookup->trace_root_sigchase = false;
+
+ strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
+
+ lookup->rdtype = lookup->rdtype_sigchase;
+ lookup->rdtypeset = true;
+ lookup->qrdtype = lookup->qrdtype_sigchase;
+
+ 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);
+ }
+
+
+ for (result = dns_rdataset_first(chase_nsrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(chase_nsrdataset)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdata_ns_t ns;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dig_server_t * srv = NULL;
+#define __FOLLOW_GLUE__
+#ifdef __FOLLOW_GLUE__
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ dns_rdataset_t *rdataset = NULL;
+ bool t = true;
+#endif
+
+ memset(namestr, 0, DNS_NAME_FORMATSIZE);
+
+ dns_rdataset_current(chase_nsrdataset, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+#ifdef __FOLLOW_GLUE__
+
+ result = advanced_rrsearch(&rdataset, &ns.name,
+ dns_rdatatype_aaaa,
+ dns_rdatatype_any, &t);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t aaaa = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &aaaa);
+
+ result = isc_buffer_allocate(mctx, &b, 80);
+ check_result(result, "isc_buffer_allocate");
+
+ dns_rdata_totext(&aaaa, &ns.name, b);
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(namestr, (char*)r.base,
+ DNS_NAME_FORMATSIZE);
+ isc_buffer_free(&b);
+ dns_rdata_reset(&aaaa);
+
+
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list,
+ srv, link);
+ }
+ }
+
+ rdataset = NULL;
+ result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
+ dns_rdatatype_any, &t);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t a = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &a);
+
+ result = isc_buffer_allocate(mctx, &b, 80);
+ check_result(result, "isc_buffer_allocate");
+
+ dns_rdata_totext(&a, &ns.name, b);
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(namestr, (char*)r.base,
+ DNS_NAME_FORMATSIZE);
+ isc_buffer_free(&b);
+ dns_rdata_reset(&a);
+ printf("ns name: %s\n", namestr);
+
+
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list,
+ srv, link);
+ }
+ }
+#else
+
+ dns_name_format(&ns.name, namestr, sizeof(namestr));
+ printf("ns name: ");
+ dns_name_print(&ns.name, stdout);
+ printf("\n");
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+
+#endif
+ dns_rdata_freestruct(&ns);
+ dns_rdata_reset(&rdata);
+
+ }
+
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ printf("\nLaunch a query to find a RRset of type ");
+ print_type(lookup->rdtype);
+ printf(" for zone: %s", lookup->textname);
+ printf(" with nameservers:");
+ printf("\n");
+ print_rdataset(name, chase_nsrdataset);
+ return (ISC_R_SUCCESS);
+}
+
+
+isc_result_t
+child_of_zone(dns_name_t * name, dns_name_t * zone_name,
+ dns_name_t * child_name)
+{
+ dns_namereln_t name_reln;
+ int orderp;
+ unsigned int nlabelsp;
+
+ name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
+ if (name_reln != dns_namereln_subdomain ||
+ dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
+ printf("\n;; ERROR : ");
+ dns_name_print(name, stdout);
+ printf(" is not a subdomain of: ");
+ dns_name_print(zone_name, stdout);
+ printf(" FAILED\n\n");
+ return (ISC_R_FAILURE);
+ }
+
+ dns_name_getlabelsequence(name,
+ dns_name_countlabels(name) -
+ dns_name_countlabels(zone_name) -1,
+ dns_name_countlabels(zone_name) +1,
+ child_name);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) {
+ dns_rdata_sig_t siginfo;
+ dns_rdataset_t mysigrdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&mysigrdataset);
+ dns_rdataset_clone(sigrdataset, &mysigrdataset);
+
+ result = dns_rdataset_first(&mysigrdataset);
+ check_result(result, "empty RRSIG dataset");
+
+ do {
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mysigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+ } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_FAILURE;
+cleanup:
+ dns_rdataset_disassociate(&mysigrdataset);
+
+ return (result);
+}
+
+
+isc_result_t
+initialization(dns_name_t *name)
+{
+ isc_result_t result;
+ bool t = true;
+
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
+ dns_rdatatype_any, &t);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; NS RRset is missing to continue validation:"
+ " FAILED\n\n");
+ return (ISC_R_FAILURE);
+ }
+ INSIST(chase_nsrdataset != NULL);
+ prepare_lookup(name);
+
+ dup_name(name, &chase_current_name);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset)
+{
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ result = isc_buffer_allocate(mctx, &b, 9000);
+ check_result(result, "isc_buffer_allocate");
+
+ dighost_printrdataset(name, rdataset, b);
+
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+
+
+ printf("%s\n", r.base);
+
+ isc_buffer_free(&b);
+}
+
+
+void
+dup_name(dns_name_t *source, dns_name_t *target) {
+ isc_result_t result;
+
+ if (dns_name_dynamic(target))
+ free_name(target);
+ result = dns_name_dup(source, mctx, target);
+ check_result(result, "dns_name_dup");
+}
+
+void
+free_name(dns_name_t *name) {
+ dns_name_free(name, mctx);
+ dns_name_init(name, NULL);
+}
+
+/*
+ *
+ * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
+ * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
+ * and the RRset is valid
+ * return ISC_R_NOTFOUND if not contains trusted key
+ or if the RRset isn't valid
+ * return ISC_R_FAILURE if problem
+ *
+ */
+isc_result_t
+contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rdataset_t myrdataset;
+ dst_key_t *dnsseckey = NULL;
+ int i;
+ isc_result_t result;
+
+ if (name == NULL || rdataset == NULL)
+ return (ISC_R_FAILURE);
+
+ dns_rdataset_init(&myrdataset);
+ dns_rdataset_clone(rdataset, &myrdataset);
+
+ result = dns_rdataset_first(&myrdataset);
+ check_result(result, "empty rdataset");
+
+ do {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&myrdataset, &rdata);
+ INSIST(rdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &rdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ for (i = 0; i < tk_list.nb_tk; i++) {
+ if (dst_key_compare(tk_list.key[i], dnsseckey)
+ == true) {
+ dns_rdata_reset(&rdata);
+
+ printf(";; Ok, find a Trusted Key in the "
+ "DNSKEY RRset: %d\n",
+ dst_key_id(dnsseckey));
+ result = sigchase_verify_sig_key(name, rdataset,
+ dnsseckey,
+ sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ }
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+cleanup:
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ dns_rdataset_disassociate(&myrdataset);
+
+ return (result);
+}
+
+isc_result_t
+sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rdataset_t mykeyrdataset;
+ dst_key_t *dnsseckey = NULL;
+ isc_result_t result;
+
+ dns_rdataset_init(&mykeyrdataset);
+ dns_rdataset_clone(keyrdataset, &mykeyrdataset);
+
+ result = dns_rdataset_first(&mykeyrdataset);
+ check_result(result, "empty DNSKEY dataset");
+
+ do {
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mykeyrdataset, &keyrdata);
+ INSIST(keyrdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &keyrdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
+ sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ dns_rdataset_disassociate(&mykeyrdataset);
+
+ return (result);
+}
+
+isc_result_t
+sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset)
+{
+ dns_rdata_sig_t siginfo;
+ dns_rdataset_t myrdataset;
+ dns_rdataset_t mysigrdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&myrdataset);
+ dns_rdataset_clone(rdataset, &myrdataset);
+ dns_rdataset_init(&mysigrdataset);
+ dns_rdataset_clone(sigrdataset, &mysigrdataset);
+
+ result = dns_rdataset_first(&mysigrdataset);
+ check_result(result, "empty RRSIG dataset");
+
+ do {
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mysigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ /*
+ * Test if the id of the DNSKEY is
+ * the id of the DNSKEY signer's
+ */
+ if (siginfo.keyid == dst_key_id(dnsseckey)) {
+
+ result = dns_rdataset_first(&myrdataset);
+ check_result(result, "empty DS dataset");
+
+ result = dns_dnssec_verify(name, &myrdataset, dnsseckey,
+ false, mctx, &sigrdata);
+
+ printf(";; VERIFYING ");
+ print_type(rdataset->type);
+ printf(" RRset for ");
+ dns_name_print(name, stdout);
+ printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
+ isc_result_totext(result));
+
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ dns_rdataset_disassociate(&myrdataset);
+ dns_rdataset_disassociate(&mysigrdataset);
+
+ return (result);
+}
+
+
+isc_result_t
+sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset)
+{
+ dns_rdata_ds_t dsinfo;
+ dns_rdataset_t mydsrdataset;
+ dns_rdataset_t mykeyrdataset;
+ dst_key_t *dnsseckey = NULL;
+ isc_result_t result;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+ dns_rdataset_init(&mydsrdataset);
+ dns_rdataset_clone(dsrdataset, &mydsrdataset);
+ dns_rdataset_init(&mykeyrdataset);
+ dns_rdataset_clone(keyrdataset, &mykeyrdataset);
+
+ result = dns_rdataset_first(&mydsrdataset);
+ check_result(result, "empty DSset dataset");
+ do {
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mydsrdataset, &dsrdata);
+
+ result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
+ check_result(result, "dns_rdata_tostruct for DS");
+
+ result = dns_rdataset_first(&mykeyrdataset);
+ check_result(result, "empty KEY dataset");
+
+ do {
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mykeyrdataset, &keyrdata);
+ INSIST(keyrdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &keyrdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ /*
+ * Test if the id of the DNSKEY is the
+ * id of DNSKEY referenced by the DS
+ */
+ if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
+ dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+
+ result = dns_ds_buildrdata(name, &keyrdata,
+ dsinfo.digest_type,
+ dsbuf, &newdsrdata);
+ dns_rdata_freestruct(&dsinfo);
+
+ if (result != ISC_R_SUCCESS) {
+ printf("Oops: impossible to build"
+ " new DS rdata\n");
+ goto cleanup;
+ }
+
+
+ if (dns_rdata_compare(&dsrdata,
+ &newdsrdata) == 0) {
+ printf(";; OK a DS valids a DNSKEY"
+ " in the RRset\n");
+ printf(";; Now verify that this"
+ " DNSKEY validates the "
+ "DNSKEY RRset\n");
+
+ result = sigchase_verify_sig_key(name,
+ keyrdataset,
+ dnsseckey,
+ chase_sigkeyrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ } else {
+ printf(";; This DS is NOT the DS for"
+ " the chasing KEY: FAILED\n");
+ }
+ }
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
+ } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ dns_rdataset_disassociate(&mydsrdataset);
+ dns_rdataset_disassociate(&mykeyrdataset);
+
+ return (result);
+}
+
+/*
+ *
+ * take a pointer on a rdataset in parameter and try to resolv it.
+ * the searched rrset is a rrset on 'name' with type 'type'
+ * (and if the type is a rrsig the signature cover 'covers').
+ * the lookedup is to known if you have already done the query on the net.
+ * ISC_R_SUCCESS: if we found the rrset
+ * ISC_R_NOTFOUND: we do not found the rrset in cache
+ * and we do a query on the net
+ * ISC_R_FAILURE: rrset not found
+ */
+isc_result_t
+advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ bool *lookedup)
+{
+ bool tmplookedup;
+
+ INSIST(rdataset != NULL);
+
+ if (*rdataset != NULL)
+ return (ISC_R_SUCCESS);
+
+ tmplookedup = *lookedup;
+ if ((*rdataset = sigchase_scanname(type, covers,
+ lookedup, name)) == NULL) {
+ if (tmplookedup)
+ return (ISC_R_FAILURE);
+ return (ISC_R_NOTFOUND);
+ }
+ *lookedup = false;
+ return (ISC_R_SUCCESS);
+}
+
+
+
+#if DIG_SIGCHASE_TD
+void
+sigchase_td(dns_message_t *msg)
+{
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ bool have_answer = false;
+ bool t = true;
+
+ if (msg->rcode != dns_rcode_noerror &&
+ msg->rcode != dns_rcode_nxdomain) {
+ char buf[20];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ result = dns_rcode_totext(msg->rcode, &b);
+ check_result(result, "dns_rcode_totext failed");
+ printf("error response code %.*s\n",
+ (int)isc_buffer_usedlength(&b), buf);
+ error_message = msg;
+ return;
+ }
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+ == ISC_R_SUCCESS) {
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ if (current_lookup->trace_root_sigchase) {
+ initialization(name);
+ return;
+ }
+ have_answer = true;
+ } else {
+ if (!current_lookup->trace_root_sigchase) {
+ result = dns_message_firstname(msg,
+ DNS_SECTION_AUTHORITY);
+ if (result != ISC_R_SUCCESS) {
+ printf("no answer or authority section\n");
+ error_message = msg;
+ return;
+ }
+ dns_message_currentname(msg, DNS_SECTION_AUTHORITY,
+ &name);
+ chase_nsrdataset
+ = chase_scanname_section(msg, name,
+ dns_rdatatype_ns,
+ dns_rdatatype_any,
+ DNS_SECTION_AUTHORITY);
+ dup_name(name, &chase_authority_name);
+ if (chase_nsrdataset != NULL) {
+ have_delegation_ns = true;
+ printf("no response but there is a delegation"
+ " in authority section: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ } else {
+ printf("no response and no delegation in "
+ "authority section but a reference"
+ " to: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ error_message = msg;
+ }
+ } else {
+ printf(";; NO ANSWERS: %s\n",
+ isc_result_totext(result));
+ free_name(&chase_name);
+ clean_trustedkey();
+ return;
+ }
+ }
+
+
+ if (have_answer) {
+ chase_rdataset
+ = chase_scanname_section(msg, &chase_name,
+ current_lookup
+ ->rdtype_sigchase,
+ dns_rdatatype_any,
+ DNS_SECTION_ANSWER);
+ if (chase_rdataset != NULL)
+ have_response = true;
+ }
+
+ result = advanced_rrsearch(&chase_keyrdataset,
+ &chase_current_name,
+ dns_rdatatype_dnskey,
+ dns_rdatatype_any,
+ &chase_keylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_keyrdataset != NULL);
+ printf("\n;; DNSKEYset:\n");
+ print_rdataset(&chase_current_name , chase_keyrdataset);
+
+
+ result = advanced_rrsearch(&chase_sigkeyrdataset,
+ &chase_current_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey,
+ &chase_sigkeylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_sigkeyrdataset != NULL);
+ printf("\n;; RRSIG of the DNSKEYset:\n");
+ print_rdataset(&chase_current_name , chase_sigkeyrdataset);
+
+
+ if (!chase_dslookedup && !chase_nslookedup) {
+ if (!delegation_follow) {
+ result = contains_trusted_key(&chase_current_name,
+ chase_keyrdataset,
+ chase_sigkeyrdataset);
+ } else {
+ INSIST(chase_dsrdataset != NULL);
+ INSIST(chase_sigdsrdataset != NULL);
+ result = sigchase_verify_ds(&chase_current_name,
+ chase_keyrdataset,
+ chase_dsrdataset);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; chain of trust can't be validated:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ } else {
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ }
+ }
+
+ if (have_response || (!have_delegation_ns && !have_response)) {
+ /* test if it's a grand father case */
+
+ if (have_response) {
+ result = advanced_rrsearch(&chase_sigrdataset,
+ &chase_name,
+ dns_rdatatype_rrsig,
+ current_lookup
+ ->rdtype_sigchase,
+ &t);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRset is missing to continue"
+ " validation SHOULD NOT APPEND:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+
+ } else {
+ result = advanced_rrsearch(&chase_sigrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_any,
+ &t);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG is missing to continue"
+ " validation SHOULD NOT APPEND:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ }
+ result = grandfather_pb_test(&chase_current_name,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_t tmp_name;
+
+ printf("\n;; We are in a Grand Father Problem:"
+ " See 2.2.1 in RFC 3658\n");
+ chase_rdataset = NULL;
+ chase_sigrdataset = NULL;
+ have_response = false;
+ have_delegation_ns = false;
+
+ dns_name_init(&tmp_name, NULL);
+ result = child_of_zone(&chase_name, &chase_current_name,
+ &tmp_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name);
+ dup_name(&tmp_name, &chase_authority_name);
+ printf(";; and we try to continue chain of trust"
+ " validation of the zone: ");
+ dns_name_print(&chase_authority_name, stdout);
+ printf("\n");
+ have_delegation_ns = true;
+ } else {
+ if (have_response)
+ goto finalstep;
+ else
+ chase_sigrdataset = NULL;
+ }
+ }
+
+ if (have_delegation_ns) {
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_ns,
+ dns_rdatatype_any,
+ &chase_nslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;;NSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND) {
+ return;
+ }
+ INSIST(chase_nsrdataset != NULL);
+
+ result = advanced_rrsearch(&chase_dsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_ds,
+ dns_rdatatype_any,
+ &chase_dslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_dsrdataset != NULL);
+ printf("\n;; DSset:\n");
+ print_rdataset(&chase_authority_name , chase_dsrdataset);
+
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds,
+ &t);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; DSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ printf("\n;; RRSIGset of DSset\n");
+ print_rdataset(&chase_authority_name, chase_sigdsrdataset);
+ INSIST(chase_sigdsrdataset != NULL);
+
+ result = sigchase_verify_sig(&chase_authority_name,
+ chase_dsrdataset,
+ chase_keyrdataset,
+ chase_sigdsrdataset);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the DSset:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+
+
+ prepare_lookup(&chase_authority_name);
+
+ have_response = false;
+ have_delegation_ns = false;
+ delegation_follow = true;
+ error_message = NULL;
+ dup_name(&chase_authority_name, &chase_current_name);
+ free_name(&chase_authority_name);
+ return;
+ }
+
+
+ if (error_message != NULL) {
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_name_t rdata_name;
+ isc_result_t ret = ISC_R_FAILURE;
+
+ dns_name_init(&rdata_name, NULL);
+ result = prove_nx(error_message, &chase_name,
+ current_lookup->rdclass_sigchase,
+ current_lookup->rdtype_sigchase, &rdata_name,
+ &rdataset, &sigrdataset);
+ if (rdataset == NULL || sigrdataset == NULL ||
+ dns_name_countlabels(&rdata_name) == 0) {
+ printf("\n;; Impossible to verify the non-existence,"
+ " the NSEC RRset can't be validated:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ ret = sigchase_verify_sig(&rdata_name, rdataset,
+ chase_keyrdataset,
+ sigrdataset);
+ if (ret != ISC_R_SUCCESS) {
+ free_name(&rdata_name);
+ printf("\n;; Impossible to verify the NSEC RR to prove"
+ " the non-existence : FAILED\n\n");
+ goto cleanandgo;
+ }
+ free_name(&rdata_name);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the non-existence:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ } else {
+ printf("\n;; OK the query doesn't have response but"
+ " we have validate this fact : SUCCESS\n\n");
+ goto cleanandgo;
+ }
+ }
+
+ cleanandgo:
+ printf(";; cleanandgo \n");
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name);
+ clean_trustedkey();
+ return;
+
+ finalstep :
+ result = advanced_rrsearch(&chase_rdataset, &chase_name,
+ current_lookup->rdtype_sigchase,
+ dns_rdatatype_any ,
+ &t);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRsig of RRset is missing to continue validation"
+ " SHOULD NOT APPEND: FAILED\n\n");
+ goto cleanandgo;
+ }
+ result = sigchase_verify_sig(&chase_name, chase_rdataset,
+ chase_keyrdataset,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the RRset : FAILED\n\n");
+ /*
+ printf("RRset:\n");
+ print_rdataset(&chase_name , chase_rdataset);
+ printf("DNSKEYset:\n");
+ print_rdataset(&chase_name , chase_keyrdataset);
+ printf("RRSIG of RRset:\n");
+ print_rdataset(&chase_name , chase_sigrdataset);
+ printf("\n");
+ */
+ goto cleanandgo;
+ } else {
+ printf("\n;; The Answer:\n");
+ print_rdataset(&chase_name , chase_rdataset);
+
+ printf("\n;; FINISH : we have validate the DNSSEC chain"
+ " of trust: SUCCESS\n\n");
+ goto cleanandgo;
+ }
+}
+
+#endif
+
+
+#if DIG_SIGCHASE_BU
+
+isc_result_t
+getneededrr(dns_message_t *msg)
+{
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_sig_t siginfo;
+ bool t = true;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+ != ISC_R_SUCCESS) {
+ printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
+
+ if (chase_name.ndata == NULL)
+ return (ISC_R_ADDRNOTAVAIL);
+ } else {
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ }
+
+ /* What do we chase? */
+ if (chase_rdataset == NULL) {
+ result = advanced_rrsearch(&chase_rdataset, name,
+ dns_rdatatype_any,
+ dns_rdatatype_any, &t);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No Answers: Validation FAILED\n\n");
+ return (ISC_R_NOTFOUND);
+ }
+ dup_name(name, &chase_name);
+ printf(";; RRset to chase:\n");
+ print_rdataset(&chase_name, chase_rdataset);
+ }
+ INSIST(chase_rdataset != NULL);
+
+
+ if (chase_sigrdataset == NULL) {
+ result = advanced_rrsearch(&chase_sigrdataset, name,
+ dns_rdatatype_rrsig,
+ chase_rdataset->type,
+ &chase_siglookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG is missing for continue validation:"
+ " FAILED\n\n");
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the RRset to chase:\n");
+ print_rdataset(&chase_name, chase_sigrdataset);
+ }
+ INSIST(chase_sigrdataset != NULL);
+
+
+ /* first find the DNSKEY name */
+ result = dns_rdataset_first(chase_sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdataset_current(chase_sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+ dup_name(&siginfo.signer, &chase_signame);
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+
+ /* Do we have a key? */
+ if (chase_keyrdataset == NULL) {
+ result = advanced_rrsearch(&chase_keyrdataset,
+ &chase_signame,
+ dns_rdatatype_dnskey,
+ dns_rdatatype_any,
+ &chase_keylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ free_name(&chase_signame);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; DNSKEYset that signs the RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_keyrdataset);
+ }
+ INSIST(chase_keyrdataset != NULL);
+
+ if (chase_sigkeyrdataset == NULL) {
+ result = advanced_rrsearch(&chase_sigkeyrdataset,
+ &chase_signame,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey,
+ &chase_sigkeylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG for DNSKEY is missing to continue"
+ " validation : FAILED\n\n");
+ free_name(&chase_signame);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the DNSKEYset that signs the "
+ "RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_sigkeyrdataset);
+ }
+ INSIST(chase_sigkeyrdataset != NULL);
+
+
+ if (chase_dsrdataset == NULL) {
+ result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
+ dns_rdatatype_ds, dns_rdatatype_any,
+ &chase_dslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; WARNING There is no DS for the zone: ");
+ dns_name_print(&chase_signame, stdout);
+ printf("\n");
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame);
+ return (ISC_R_NOTFOUND);
+ }
+ if (chase_dsrdataset != NULL) {
+ printf("\n;; DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_dsrdataset);
+ }
+ }
+
+ if (chase_dsrdataset != NULL) {
+ /*
+ * if there is no RRSIG of DS,
+ * we don't want to search on the network
+ */
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_signame,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds, &t);
+ if (result == ISC_R_FAILURE) {
+ printf(";; WARNING : NO RRSIG DS : RRSIG DS"
+ " should come with DS\n");
+ /*
+ * We continue even the DS couldn't be validated,
+ * because the DNSKEY could be a Trusted Key.
+ */
+ chase_dsrdataset = NULL;
+ } else {
+ printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_sigdsrdataset);
+ }
+ }
+ return (1);
+}
+
+
+
+void
+sigchase_bu(dns_message_t *msg)
+{
+ isc_result_t result;
+ int ret;
+
+ if (tk_list.nb_tk == 0) {
+ result = get_trusted_key();
+ if (result != ISC_R_SUCCESS) {
+ printf("No trusted keys present\n");
+ return;
+ }
+ }
+
+
+ ret = getneededrr(msg);
+ if (ret == ISC_R_NOTFOUND)
+ return;
+
+ if (ret == ISC_R_ADDRNOTAVAIL) {
+ /* We have no response */
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_name_t rdata_name;
+ dns_name_t query_name;
+
+
+ dns_name_init(&query_name, NULL);
+ dns_name_init(&rdata_name, NULL);
+ nameFromString(current_lookup->textname, &query_name);
+
+ result = prove_nx(msg, &query_name, current_lookup->rdclass,
+ current_lookup->rdtype, &rdata_name,
+ &rdataset, &sigrdataset);
+ free_name(&query_name);
+ if (rdataset == NULL || sigrdataset == NULL ||
+ dns_name_countlabels(&rdata_name) == 0) {
+ printf("\n;; Impossible to verify the Non-existence,"
+ " the NSEC RRset can't be validated: "
+ "FAILED\n\n");
+ clean_trustedkey();
+ return;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("\n No Answers and impossible to prove the"
+ " unsecurity : Validation FAILED\n\n");
+ clean_trustedkey();
+ return;
+ }
+ printf(";; An NSEC prove the non-existence of a answers,"
+ " Now we want validate this NSEC\n");
+
+ dup_name(&rdata_name, &chase_name);
+ free_name(&rdata_name);
+ chase_rdataset = rdataset;
+ chase_sigrdataset = sigrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = false;
+ chase_keylookedup = false;
+ chase_dslookedup = false;
+ chase_sigdslookedup = false;
+ sigchase(msg);
+ clean_trustedkey();
+ return;
+ }
+
+
+ printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
+
+ result = sigchase_verify_sig(&chase_name, chase_rdataset,
+ chase_keyrdataset,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_name);
+ free_name(&chase_signame);
+ printf(";; No DNSKEY is valid to check the RRSIG"
+ " of the RRset: FAILED\n");
+ clean_trustedkey();
+ return;
+ }
+ printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
+
+ result = contains_trusted_key(&chase_signame, chase_keyrdataset,
+ chase_sigkeyrdataset);
+ if (result == ISC_R_SUCCESS) {
+ free_name(&chase_name);
+ free_name(&chase_signame);
+ printf("\n;; Ok this DNSKEY is a Trusted Key,"
+ " DNSSEC validation is ok: SUCCESS\n\n");
+ clean_trustedkey();
+ return;
+ }
+
+ printf(";; Now, we are going to validate this DNSKEY by the DS\n");
+
+ if (chase_dsrdataset == NULL) {
+ free_name(&chase_name);
+ free_name(&chase_signame);
+ printf(";; the DNSKEY isn't trusted-key and there isn't"
+ " DS to validate the DNSKEY: FAILED\n");
+ clean_trustedkey();
+ return;
+ }
+
+ result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
+ chase_dsrdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_signame);
+ free_name(&chase_name);
+ printf(";; ERROR no DS validates a DNSKEY in the"
+ " DNSKEY RRset: FAILED\n");
+ clean_trustedkey();
+ return;
+ } else
+ printf(";; OK this DNSKEY (validated by the DS) validates"
+ " the RRset of the DNSKEYs, thus the DNSKEY validates"
+ " the RRset\n");
+ INSIST(chase_sigdsrdataset != NULL);
+
+ dup_name(&chase_signame, &chase_name);
+ free_name(&chase_signame);
+ chase_rdataset = chase_dsrdataset;
+ chase_sigrdataset = chase_sigdsrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = chase_keylookedup = false;
+ chase_dslookedup = chase_sigdslookedup = false;
+
+ printf(";; Now, we want to validate the DS : recursive call\n");
+ sigchase(msg);
+ return;
+}
+#endif
+
+void
+sigchase(dns_message_t *msg) {
+#if DIG_SIGCHASE_TD
+ if (current_lookup->do_topdown) {
+ sigchase_td(msg);
+ return;
+ }
+#endif
+#if DIG_SIGCHASE_BU
+ sigchase_bu(msg);
+ return;
+#endif
+}
+
+
+/*
+ * return 1 if name1 < name2
+ * 0 if name1 == name2
+ * -1 if name1 > name2
+ * and -2 if problem
+ */
+int
+inf_name(dns_name_t *name1, dns_name_t *name2)
+{
+ dns_label_t label1;
+ dns_label_t label2;
+ unsigned int nblabel1;
+ unsigned int nblabel2;
+ int min_lum_label;
+ int i;
+ int ret = -2;
+
+ nblabel1 = dns_name_countlabels(name1);
+ nblabel2 = dns_name_countlabels(name2);
+
+ if (nblabel1 >= nblabel2)
+ min_lum_label = nblabel2;
+ else
+ min_lum_label = nblabel1;
+
+
+ for (i=1 ; i < min_lum_label; i++) {
+ dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
+ dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
+ if ((ret = isc_region_compare(&label1, &label2)) != 0) {
+ if (ret < 0)
+ return (-1);
+ else if (ret > 0)
+ return (1);
+ }
+ }
+ if (nblabel1 == nblabel2)
+ return (0);
+
+ if (nblabel1 < nblabel2)
+ return (-1);
+ else
+ return (1);
+}
+
+/**
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_domain(dns_message_t *msg,
+ dns_name_t *name,
+ dns_name_t *rdata_name,
+ dns_rdataset_t **rdataset,
+ dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret = ISC_R_FAILURE;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_rdataset_t *nsecset = NULL;
+ dns_rdataset_t *signsecset = NULL ;
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+ dns_name_t *nsecname;
+ dns_rdata_nsec_t nsecstruct;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+ != ISC_R_SUCCESS) {
+ printf(";; nothing in authority section : impossible to"
+ " validate the non-existence : FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ do {
+ nsecname = NULL;
+ dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
+ nsecset = search_type(nsecname, dns_rdatatype_nsec,
+ dns_rdatatype_any);
+ if (nsecset == NULL)
+ continue;
+
+ printf("There is a NSEC for this zone in the"
+ " AUTHORITY section:\n");
+ print_rdataset(nsecname, nsecset);
+
+ for (result = dns_rdataset_first(nsecset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(nsecset)) {
+ dns_rdataset_current(nsecset, &nsec);
+
+ signsecset
+ = chase_scanname_section(msg, nsecname,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec,
+ DNS_SECTION_AUTHORITY);
+ if (signsecset == NULL) {
+ printf(";; no RRSIG NSEC in authority section:"
+ " impossible to validate the "
+ "non-existence: FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
+ check_result(ret,"dns_rdata_tostruct");
+
+ if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
+ inf_name(name, &nsecstruct.next) == 1) ||
+ (inf_name(name, nsecname) == 1 &&
+ inf_name(&nsecstruct.next, name) == 1)) {
+ dns_rdata_freestruct(&nsecstruct);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+ dup_name(nsecname, rdata_name);
+
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_rdata_freestruct(&nsecstruct);
+ dns_rdata_reset(&nsec);
+ }
+ } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS);
+
+ *rdataset = NULL;
+ *sigrdataset = NULL;
+ rdata_name = NULL;
+ return (ISC_R_FAILURE);
+}
+
+/**
+ *
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ dns_name_t *rdata_name, dns_rdataset_t **rdataset,
+ dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret;
+ dns_rdataset_t *signsecset;
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+
+ UNUSED(rdclass);
+
+ ret = dns_rdataset_first(nsecset);
+ check_result(ret,"dns_rdataset_first");
+
+ dns_rdataset_current(nsecset, &nsec);
+
+ ret = dns_nsec_typepresent(&nsec, type);
+ if (ret == ISC_R_SUCCESS)
+ printf("OK the NSEC said that the type doesn't exist \n");
+
+ signsecset = chase_scanname_section(msg, name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec,
+ DNS_SECTION_AUTHORITY);
+ if (signsecset == NULL) {
+ printf("There isn't RRSIG NSEC for the zone \n");
+ return (ISC_R_FAILURE);
+ }
+ dup_name(name, rdata_name);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+
+ return (ret);
+}
+
+/**
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, dns_name_t *rdata_name,
+ dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret;
+ dns_rdataset_t *nsecset = NULL;
+
+ printf("We want to prove the non-existence of a type of rdata %d"
+ " or of the zone: \n", type);
+
+ if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+ != ISC_R_SUCCESS) {
+ printf(";; nothing in authority section : impossible to"
+ " validate the non-existence : FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
+ dns_rdatatype_any,
+ DNS_SECTION_AUTHORITY);
+ if (nsecset != NULL) {
+ printf("We have a NSEC for this zone :OK\n");
+ ret = prove_nx_type(msg, name, nsecset, rdclass,
+ type, rdata_name, rdataset,
+ sigrdataset);
+ if (ret != ISC_R_SUCCESS) {
+ printf("prove_nx: ERROR type exist\n");
+ return (ret);
+ } else {
+ printf("prove_nx: OK type does not exist\n");
+ return (ISC_R_SUCCESS);
+ }
+ } else {
+ printf("there is no NSEC for this zone: validating "
+ "that the zone doesn't exist\n");
+ ret = prove_nx_domain(msg, name, rdata_name,
+ rdataset, sigrdataset);
+ return (ret);
+ }
+ /* Never get here */
+}
+#endif
diff --git a/bin/dig/host.1 b/bin/dig/host.1
new file mode 100644
index 0000000..3e75fb7
--- /dev/null
+++ b/bin/dig/host.1
@@ -0,0 +1,269 @@
+.\" Copyright (C) 2000-2002, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: host
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-01-20
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "HOST" "1" "2009\-01\-20" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+host \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP \w'\fBhost\fR\ 'u
+\fBhost\fR [\fB\-aCdlnrsTUwv\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-N\ \fR\fB\fIndots\fR\fR] [\fB\-R\ \fR\fB\fInumber\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-W\ \fR\fB\fIwait\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-v\fR] [\fB\-V\fR] {name} [server]
+.SH "DESCRIPTION"
+.PP
+\fBhost\fR
+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,
+\fBhost\fR
+prints a short summary of its command line arguments and options\&.
+.PP
+\fIname\fR
+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
+\fBhost\fR
+will by default perform a reverse lookup for that address\&.
+\fIserver\fR
+is an optional argument which is either the name or IP address of the name server that
+\fBhost\fR
+should query instead of the server or servers listed in
+/etc/resolv\&.conf\&.
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only for query transport\&. See also the
+\fB\-6\fR
+option\&.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only for query transport\&. See also the
+\fB\-4\fR
+option\&.
+.RE
+.PP
+\-a
+.RS 4
+"All"\&. The
+\fB\-a\fR
+option is normally equivalent to
+\fB\-v \-t \fR\fBANY\fR\&. It also affects the behaviour of the
+\fB\-l\fR
+list zone option\&.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Query class: This can be used to lookup HS (Hesiod) or CH (Chaosnet) class resource records\&. The default class is IN (Internet)\&.
+.RE
+.PP
+\-C
+.RS 4
+Check consistency:
+\fBhost\fR
+will query the SOA records for zone
+\fIname\fR
+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\&.
+.RE
+.PP
+\-d
+.RS 4
+Print debugging traces\&. Equivalent to the
+\fB\-v\fR
+verbose option\&.
+.RE
+.PP
+\-i
+.RS 4
+Obsolete\&. Use the IP6\&.INT domain for reverse lookups of IPv6 addresses as defined in RFC1886 and deprecated in RFC4159\&. The default is to use IP6\&.ARPA as specified in RFC3596\&.
+.RE
+.PP
+\-l
+.RS 4
+List zone: The
+\fBhost\fR
+command performs a zone transfer of zone
+\fIname\fR
+and prints out the NS, PTR and address records (A/AAAA)\&.
+.sp
+Together, the
+\fB\-l \-a\fR
+options print all records in the zone\&.
+.RE
+.PP
+\-N \fIndots\fR
+.RS 4
+The number of dots that have to be in
+\fIname\fR
+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 will be searched for in the domains listed in the
+\fBsearch\fR
+or
+\fBdomain\fR
+directive in
+/etc/resolv\&.conf\&.
+.RE
+.PP
+\-r
+.RS 4
+Non\-recursive query: Setting this option clears the RD (recursion desired) bit in the query\&. This should mean that the name server receiving the query will not attempt to resolve
+\fIname\fR\&. The
+\fB\-r\fR
+option enables
+\fBhost\fR
+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\&.
+.RE
+.PP
+\-R \fInumber\fR
+.RS 4
+Number of retries for UDP queries: If
+\fInumber\fR
+is negative or zero, the number of retries will default to 1\&. The default value is 1, or the value of the
+\fIattempts\fR
+option in
+/etc/resolv\&.conf, if set\&.
+.RE
+.PP
+\-s
+.RS 4
+Do
+\fInot\fR
+send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Query type: The
+\fItype\fR
+argument can be any recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc\&.
+.sp
+When no query type is specified,
+\fBhost\fR
+automatically selects an appropriate query type\&. By default, it looks for A, AAAA, and MX records\&. If the
+\fB\-C\fR
+option is given, queries will be made for SOA records\&. If
+\fIname\fR
+is a dotted\-decimal IPv4 address or colon\-delimited IPv6 address,
+\fBhost\fR
+will query for PTR records\&.
+.sp
+If a query type of IXFR is chosen the starting serial number can be specified by appending an equal followed by the starting serial number (like
+\fB\-t \fR\fBIXFR=12345678\fR)\&.
+.RE
+.PP
+\-T, \-U
+.RS 4
+TCP/UDP: By default,
+\fBhost\fR
+uses UDP when making queries\&. The
+\fB\-T\fR
+option makes it use a TCP connection when querying the name server\&. TCP will be automatically selected for queries that require it, such as zone transfer (AXFR) requests\&. Type ANY queries default to TCP but can be forced to UDP initially using
+\fB\-U\fR\&.
+.RE
+.PP
+\-m \fIflag\fR
+.RS 4
+Memory usage debugging: the flag can be
+\fIrecord\fR,
+\fIusage\fR, or
+\fItrace\fR\&. You can specify the
+\fB\-m\fR
+option more than once to set multiple flags\&.
+.RE
+.PP
+\-v
+.RS 4
+Verbose output\&. Equivalent to the
+\fB\-d\fR
+debug option\&. Verbose output can also be enabled by setting the
+\fIdebug\fR
+option in
+/etc/resolv\&.conf\&.
+.RE
+.PP
+\-V
+.RS 4
+Print the version number and exit\&.
+.RE
+.PP
+\-w
+.RS 4
+Wait forever: The query timeout is set to the maximum possible\&. See also the
+\fB\-W\fR
+option\&.
+.RE
+.PP
+\-W \fIwait\fR
+.RS 4
+Timeout: Wait for up to
+\fIwait\fR
+seconds for a reply\&. If
+\fIwait\fR
+is less than one, the wait interval is set to one second\&.
+.sp
+By default,
+\fBhost\fR
+will wait for 5 seconds for UDP responses and 10 seconds for TCP connections\&. These defaults can be overridden by the
+\fItimeout\fR
+option in
+/etc/resolv\&.conf\&.
+.sp
+See also the
+\fB\-w\fR
+option\&.
+.RE
+.SH "IDN SUPPORT"
+.PP
+If
+\fBhost\fR
+has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names\&.
+\fBhost\fR
+appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server\&. If you\*(Aqd like to turn off the IDN support for some reason, defines the
+\fBIDN_DISABLE\fR
+environment variable\&. The IDN support is disabled if the variable is set when
+\fBhost\fR
+runs\&.
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBnamed\fR(8)\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2002, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/host.c b/bin/dig/host.c
new file mode 100644
index 0000000..d342b1e
--- /dev/null
+++ b/bin/dig/host.c
@@ -0,0 +1,921 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDNKIT
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+#include <isc/stdlib.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/rdatatype.h>
+#include <dns/rdatastruct.h>
+
+#include <dig/dig.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 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;
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+show_usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+show_usage(void) {
+ fputs(
+"Usage: host [-aCdilrTvVw] [-c class] [-N ndots] [-t type] [-W time]\n"
+" [-R number] [-m flag] hostname [server]\n"
+" -a is equivalent to -v -t ANY\n"
+" -c specifies query class for non-IN data\n"
+" -C compares SOA records on authoritative nameservers\n"
+" -d is equivalent to -v\n"
+" -i IP6.INT reverse lookups\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"
+" -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"
+" -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", stderr);
+ 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));
+ 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:
+ result = isc_buffer_allocate(mctx, &b, bufsize);
+ check_result(result, "isc_buffer_allocate");
+ 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);
+}
+#ifdef DIG_SIGCHASE
+/* Just for compatibility : not use in host program */
+static isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ UNUSED(owner_name);
+ UNUSED(rdataset);
+ UNUSED(target);
+ return(false);
+}
+#endif
+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];
+ bool first;
+ bool no_rdata;
+
+ if (sectionid == DNS_SECTION_QUESTION)
+ no_rdata = true;
+ else
+ no_rdata = false;
+
+ 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 (!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
+ UNUSED(first); /* Shut up compiler. */
+#endif
+ } 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, 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, NULL);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+static isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, bool headers) {
+ bool did_flag = false;
+ dns_rdataset_t *opt, *tsig = NULL;
+ dns_name_t *tsigname;
+ isc_result_t result = ISC_R_SUCCESS;
+ int force_error;
+
+ 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, NULL);
+ 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 = "46ac:dilnm:rst:vVwCDN:R:TUW:";
+
+/*% version */
+static void
+version(void) {
+ fputs("host " VERSION "\n", stderr);
+}
+
+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 'c': break;
+ case 'd': break;
+ case 'i': break;
+ case 'l': break;
+ case 'n': break;
+ case 'r': break;
+ case 's': break;
+ case 't': break;
+ case 'v': break;
+ case 'V':
+ version();
+ exit(0);
+ break;
+ case 'w': break;
+ case 'C': break;
+ case 'D':
+ if (debugging)
+ debugtiming = true;
+ debugging = true;
+ break;
+ case 'N': break;
+ case 'R': break;
+ case 'T': 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->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;
+#ifdef WITH_IDNKIT
+ idnoptions = 0;
+#endif
+ 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;
+#ifdef WITH_IDNKIT
+ } else if (rdtype == dns_rdatatype_a ||
+ rdtype == dns_rdatatype_aaaa ||
+ rdtype == dns_rdatatype_mx) {
+ idnoptions = IDN_ASCCHECK;
+ list_type = rdtype;
+#endif
+ } 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':
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ lookup->rdtype = dns_rdatatype_any;
+#ifdef WITH_IDNKIT
+ idnoptions = 0;
+#endif
+ list_type = dns_rdatatype_any;
+ list_addresses = false;
+ lookup->rdtypeset = true;
+ short_form = false;
+ default_lookups = false;
+ break;
+ case 'i':
+ lookup->ip6_int = true;
+ 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;
+ }
+ }
+
+ 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,
+ lookup->ip6_int, 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;
+#ifdef WITH_IDNKIT
+ idnoptions = IDN_ASCCHECK;
+#endif
+
+ /* setup dighost callbacks */
+#ifdef DIG_SIGCHASE
+ dighost_printrdataset = printrdataset;
+#endif
+ 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.docbook b/bin/dig/host.docbook
new file mode 100644
index 0000000..da0f8fb
--- /dev/null
+++ b/bin/dig/host.docbook
@@ -0,0 +1,406 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.host">
+ <info>
+ <date>2009-01-20</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>host</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>host</refname>
+ <refpurpose>DNS lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>host</command>
+ <arg choice="opt" rep="norepeat"><option>-aCdlnrsTUwv</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-N <replaceable class="parameter">ndots</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R <replaceable class="parameter">number</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-W <replaceable class="parameter">wait</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="req" rep="norepeat">name</arg>
+ <arg choice="opt" rep="norepeat">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+
+ <para><command>host</command>
+ 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,
+ <command>host</command>
+ prints a short summary of its command line arguments and options.
+ </para>
+
+ <para><parameter>name</parameter> 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 <command>host</command> will by
+ default
+ perform a reverse lookup for that address.
+ <parameter>server</parameter> is an optional argument which
+ is either
+ the name or IP address of the name server that <command>host</command>
+ should query instead of the server or servers listed in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only for query transport.
+ See also the <option>-6</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only for query transport.
+ See also the <option>-4</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ "All". The <option>-a</option> option is normally equivalent
+ to <option>-v -t <literal>ANY</literal></option>.
+ It also affects the behaviour of the <option>-l</option>
+ list zone option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Query class: This can be used to lookup HS (Hesiod) or CH
+ (Chaosnet) class resource records. The default class is IN
+ (Internet).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Check consistency: <command>host</command> will query the
+ SOA records for zone <parameter>name</parameter> 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d</term>
+ <listitem>
+ <para>
+ Print debugging traces.
+ Equivalent to the <option>-v</option> verbose option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i</term>
+ <listitem>
+ <para>
+ Obsolete.
+ Use the IP6.INT domain for reverse lookups of IPv6
+ addresses as defined in RFC1886 and deprecated in RFC4159.
+ The default is to use IP6.ARPA as specified in RFC3596.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l</term>
+ <listitem>
+ <para>
+ List zone:
+ The <command>host</command> command performs a zone transfer of
+ zone <parameter>name</parameter> and prints out the NS,
+ PTR and address records (A/AAAA).
+ </para>
+ <para>
+ Together, the <option>-l -a</option>
+ options print all records in the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-N <replaceable class="parameter">ndots</replaceable></term>
+ <listitem>
+ <para>
+ The number of dots that have to be
+ in <parameter>name</parameter> for it to be considered
+ absolute. The default value is that defined using the
+ ndots statement in <filename>/etc/resolv.conf</filename>,
+ or 1 if no ndots statement is present. Names with fewer
+ dots are interpreted as relative names and will be
+ searched for in the domains listed in
+ the <type>search</type> or <type>domain</type> directive
+ in <filename>/etc/resolv.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r</term>
+ <listitem>
+ <para>
+ Non-recursive query:
+ Setting this option clears the RD (recursion desired) bit
+ in the query. This should mean that the name server
+ receiving the query will not attempt to
+ resolve <parameter>name</parameter>.
+ The <option>-r</option> option
+ enables <command>host</command> 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">number</replaceable></term>
+ <listitem>
+ <para>
+ Number of retries for UDP queries:
+ If <parameter>number</parameter> is negative or zero, the
+ number of retries will default to 1. The default value is
+ 1, or the value of the <parameter>attempts</parameter>
+ option in <filename>/etc/resolv.conf</filename>, if set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Do <emphasis>not</emphasis> send the query to the next
+ nameserver if any server responds with a SERVFAIL
+ response, which is the reverse of normal stub resolver
+ behavior.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Query type:
+ The <parameter>type</parameter> argument can be any
+ recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc.
+ </para>
+ <para>
+ When no query type is specified, <command>host</command>
+ automatically selects an appropriate query type. By default, it
+ looks for A, AAAA, and MX records.
+ If the <option>-C</option> option is given, queries will
+ be made for SOA records.
+ If <parameter>name</parameter> is a dotted-decimal IPv4
+ address or colon-delimited IPv6
+ address, <command>host</command> will query for PTR
+ records.
+ </para>
+ <para>
+ If a query type of IXFR is chosen the starting serial
+ number can be specified by appending an equal followed by
+ the starting serial number
+ (like <option>-t <literal>IXFR=12345678</literal></option>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T</term>
+ <term>-U</term>
+ <listitem>
+ <para>
+ TCP/UDP:
+ By default, <command>host</command> uses UDP when making
+ queries. The <option>-T</option> option makes it use a TCP
+ connection when querying the name server. TCP will be
+ automatically selected for queries that require it, such
+ as zone transfer (AXFR) requests. Type ANY queries default
+ to TCP but can be forced to UDP initially using <option>-U</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Memory usage debugging: the flag can
+ be <parameter>record</parameter>, <parameter>usage</parameter>,
+ or <parameter>trace</parameter>. You can specify
+ the <option>-m</option> option more than once to set
+ multiple flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Verbose output.
+ Equivalent to the <option>-d</option> debug option.
+ Verbose output can also be enabled by setting
+ the <parameter>debug</parameter> option
+ in <filename>/etc/resolv.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Print the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-w</term>
+ <listitem>
+ <para>
+ Wait forever: The query timeout is set to the maximum possible.
+ See also the <option>-W</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-W <replaceable class="parameter">wait</replaceable></term>
+ <listitem>
+ <para>
+ Timeout: Wait for up to <parameter>wait</parameter>
+ seconds for a reply. If <parameter>wait</parameter> is
+ less than one, the wait interval is set to one second.
+ </para>
+ <para>
+ By default, <command>host</command> will wait for 5
+ seconds for UDP responses and 10 seconds for TCP
+ connections. These defaults can be overridden by
+ the <parameter>timeout</parameter> option
+ in <filename>/etc/resolv.conf</filename>.
+ </para>
+ <para>
+ See also the <option>-w</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>IDN SUPPORT</title></info>
+
+ <para>
+ If <command>host</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>host</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the variable is set when
+ <command>host</command> runs.
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dig/host.html b/bin/dig/host.html
new file mode 100644
index 0000000..665a5e6
--- /dev/null
+++ b/bin/dig/host.html
@@ -0,0 +1,333 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2002, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>host</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.host"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ host
+ &#8212; DNS lookup utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">host</code>
+ [<code class="option">-aCdlnrsTUwv</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-N <em class="replaceable"><code>ndots</code></em></code>]
+ [<code class="option">-R <em class="replaceable"><code>number</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-W <em class="replaceable"><code>wait</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [<code class="option">-v</code>]
+ [<code class="option">-V</code>]
+ {name}
+ [server]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+
+ <p><span class="command"><strong>host</strong></span>
+ 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,
+ <span class="command"><strong>host</strong></span>
+ prints a short summary of its command line arguments and options.
+ </p>
+
+ <p><em class="parameter"><code>name</code></em> 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 <span class="command"><strong>host</strong></span> will by
+ default
+ perform a reverse lookup for that address.
+ <em class="parameter"><code>server</code></em> is an optional argument which
+ is either
+ the name or IP address of the name server that <span class="command"><strong>host</strong></span>
+ should query instead of the server or servers listed in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Use IPv4 only for query transport.
+ See also the <code class="option">-6</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Use IPv6 only for query transport.
+ See also the <code class="option">-4</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-a</span></dt>
+<dd>
+ <p>
+ "All". The <code class="option">-a</code> option is normally equivalent
+ to <code class="option">-v -t <code class="literal">ANY</code></code>.
+ It also affects the behaviour of the <code class="option">-l</code>
+ list zone option.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Query class: This can be used to lookup HS (Hesiod) or CH
+ (Chaosnet) class resource records. The default class is IN
+ (Internet).
+ </p>
+ </dd>
+<dt><span class="term">-C</span></dt>
+<dd>
+ <p>
+ Check consistency: <span class="command"><strong>host</strong></span> will query the
+ SOA records for zone <em class="parameter"><code>name</code></em> 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.
+ </p>
+ </dd>
+<dt><span class="term">-d</span></dt>
+<dd>
+ <p>
+ Print debugging traces.
+ Equivalent to the <code class="option">-v</code> verbose option.
+ </p>
+ </dd>
+<dt><span class="term">-i</span></dt>
+<dd>
+ <p>
+ Obsolete.
+ Use the IP6.INT domain for reverse lookups of IPv6
+ addresses as defined in RFC1886 and deprecated in RFC4159.
+ The default is to use IP6.ARPA as specified in RFC3596.
+ </p>
+ </dd>
+<dt><span class="term">-l</span></dt>
+<dd>
+ <p>
+ List zone:
+ The <span class="command"><strong>host</strong></span> command performs a zone transfer of
+ zone <em class="parameter"><code>name</code></em> and prints out the NS,
+ PTR and address records (A/AAAA).
+ </p>
+ <p>
+ Together, the <code class="option">-l -a</code>
+ options print all records in the zone.
+ </p>
+ </dd>
+<dt><span class="term">-N <em class="replaceable"><code>ndots</code></em></span></dt>
+<dd>
+ <p>
+ The number of dots that have to be
+ in <em class="parameter"><code>name</code></em> for it to be considered
+ absolute. The default value is that defined using the
+ ndots statement in <code class="filename">/etc/resolv.conf</code>,
+ or 1 if no ndots statement is present. Names with fewer
+ dots are interpreted as relative names and will be
+ searched for in the domains listed in
+ the <span class="type">search</span> or <span class="type">domain</span> directive
+ in <code class="filename">/etc/resolv.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-r</span></dt>
+<dd>
+ <p>
+ Non-recursive query:
+ Setting this option clears the RD (recursion desired) bit
+ in the query. This should mean that the name server
+ receiving the query will not attempt to
+ resolve <em class="parameter"><code>name</code></em>.
+ The <code class="option">-r</code> option
+ enables <span class="command"><strong>host</strong></span> 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.
+ </p>
+ </dd>
+<dt><span class="term">-R <em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Number of retries for UDP queries:
+ If <em class="parameter"><code>number</code></em> is negative or zero, the
+ number of retries will default to 1. The default value is
+ 1, or the value of the <em class="parameter"><code>attempts</code></em>
+ option in <code class="filename">/etc/resolv.conf</code>, if set.
+ </p>
+ </dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+ <p>
+ Do <span class="emphasis"><em>not</em></span> send the query to the next
+ nameserver if any server responds with a SERVFAIL
+ response, which is the reverse of normal stub resolver
+ behavior.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ Query type:
+ The <em class="parameter"><code>type</code></em> argument can be any
+ recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc.
+ </p>
+ <p>
+ When no query type is specified, <span class="command"><strong>host</strong></span>
+ automatically selects an appropriate query type. By default, it
+ looks for A, AAAA, and MX records.
+ If the <code class="option">-C</code> option is given, queries will
+ be made for SOA records.
+ If <em class="parameter"><code>name</code></em> is a dotted-decimal IPv4
+ address or colon-delimited IPv6
+ address, <span class="command"><strong>host</strong></span> will query for PTR
+ records.
+ </p>
+ <p>
+ If a query type of IXFR is chosen the starting serial
+ number can be specified by appending an equal followed by
+ the starting serial number
+ (like <code class="option">-t <code class="literal">IXFR=12345678</code></code>).
+ </p>
+ </dd>
+<dt>
+<span class="term">-T, </span><span class="term">-U</span>
+</dt>
+<dd>
+ <p>
+ TCP/UDP:
+ By default, <span class="command"><strong>host</strong></span> uses UDP when making
+ queries. The <code class="option">-T</code> option makes it use a TCP
+ connection when querying the name server. TCP will be
+ automatically selected for queries that require it, such
+ as zone transfer (AXFR) requests. Type ANY queries default
+ to TCP but can be forced to UDP initially using <code class="option">-U</code>.
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd>
+ <p>
+ Memory usage debugging: the flag can
+ be <em class="parameter"><code>record</code></em>, <em class="parameter"><code>usage</code></em>,
+ or <em class="parameter"><code>trace</code></em>. You can specify
+ the <code class="option">-m</code> option more than once to set
+ multiple flags.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Verbose output.
+ Equivalent to the <code class="option">-d</code> debug option.
+ Verbose output can also be enabled by setting
+ the <em class="parameter"><code>debug</code></em> option
+ in <code class="filename">/etc/resolv.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Print the version number and exit.
+ </p>
+ </dd>
+<dt><span class="term">-w</span></dt>
+<dd>
+ <p>
+ Wait forever: The query timeout is set to the maximum possible.
+ See also the <code class="option">-W</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-W <em class="replaceable"><code>wait</code></em></span></dt>
+<dd>
+ <p>
+ Timeout: Wait for up to <em class="parameter"><code>wait</code></em>
+ seconds for a reply. If <em class="parameter"><code>wait</code></em> is
+ less than one, the wait interval is set to one second.
+ </p>
+ <p>
+ By default, <span class="command"><strong>host</strong></span> will wait for 5
+ seconds for UDP responses and 10 seconds for TCP
+ connections. These defaults can be overridden by
+ the <em class="parameter"><code>timeout</code></em> option
+ in <code class="filename">/etc/resolv.conf</code>.
+ </p>
+ <p>
+ See also the <code class="option">-w</code> option.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>IDN SUPPORT</h2>
+
+ <p>
+ If <span class="command"><strong>host</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span class="command"><strong>host</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span class="command"><strong>host</strong></span> runs.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/resolv.conf</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dig</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
new file mode 100644
index 0000000..cc37c55
--- /dev/null
+++ b/bin/dig/include/dig/dig.h
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef DIG_H
+#define DIG_H
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <dns/rdatalist.h>
+
+#include <dst/dst.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+
+#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
+/*% 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
+
+/*% Default TCP Timeout */
+#define TCP_TIMEOUT 10
+/*% Default UDP Timeout */
+#define UDP_TIMEOUT 5
+
+#define SERVER_TIMEOUT 1
+
+#define LOOKUP_LIMIT 64
+/*%
+ * 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.
+ */
+
+/*
+ * Defaults for the sigchase suboptions. Consolidated here because
+ * these control the layout of dig_lookup_t (among other things).
+ */
+#ifdef DIG_SIGCHASE
+#ifndef DIG_SIGCHASE_BU
+#define DIG_SIGCHASE_BU 1
+#endif
+#ifndef DIG_SIGCHASE_TD
+#define DIG_SIGCHASE_TD 1
+#endif
+#endif
+
+ISC_LANG_BEGINDECLS
+
+typedef struct dig_lookup dig_lookup_t;
+typedef struct dig_query dig_query_t;
+typedef struct dig_server dig_server_t;
+#ifdef DIG_SIGCHASE
+typedef struct dig_message dig_message_t;
+#endif
+typedef ISC_LIST(dig_server_t) dig_serverlist_t;
+typedef struct dig_searchlist dig_searchlist_t;
+
+/*% The dig_lookup structure */
+struct dig_lookup {
+ bool
+ pending, /*%< Pending a successful answer */
+ waiting_connect,
+ doing_xfr,
+ ns_search_only, /*%< dig +nssearch, host -C */
+ identify, /*%< Append an "on server <foo>" message */
+ identify_previous_line, /*% Prepend a "Nameserver <foo>:"
+ message, with newline and tab */
+ ignore,
+ recurse,
+ aaonly,
+ adflag,
+ cdflag,
+ zflag,
+ trace, /*% dig +trace */
+ trace_root, /*% initial query for either +trace or +nssearch */
+ tcp_mode,
+ tcp_mode_set,
+ ip6_int,
+ comments,
+ stats,
+ section_question,
+ section_answer,
+ section_authority,
+ section_additional,
+ servfail_stops,
+ new_search,
+ need_search,
+ done_as_is,
+ besteffort,
+ dnssec,
+ expire,
+ sendcookie,
+ seenbadcookie,
+ badcookie,
+ nsid, /*% Name Server ID (RFC 5001) */
+ header_only,
+ ednsneg,
+ mapped,
+ print_unknown_format,
+ idnin,
+ idnout;
+#ifdef DIG_SIGCHASE
+bool sigchase;
+#if DIG_SIGCHASE_TD
+ bool do_topdown,
+ trace_root_sigchase,
+ rdtype_sigchaseset,
+ rdclass_sigchaseset;
+ /* Name we are going to validate RRset */
+ char textnamesigchase[MXNAME];
+#endif
+#endif
+
+ char textname[MXNAME]; /*% Name we're going to be looking up */
+ char cmdline[MXNAME];
+ dns_rdatatype_t rdtype;
+ dns_rdatatype_t qrdtype;
+#if DIG_SIGCHASE_TD
+ dns_rdatatype_t rdtype_sigchase;
+ dns_rdatatype_t qrdtype_sigchase;
+ dns_rdataclass_t rdclass_sigchase;
+#endif
+ 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;
+ uint16_t udpsize;
+ int16_t edns;
+ 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;
+ isc_dscp_t dscp;
+ unsigned int ednsflags;
+ dns_opcode_t opcode;
+ unsigned int eoferr;
+};
+
+/*% The dig_query structure */
+struct dig_query {
+ dig_lookup_t *lookup;
+ bool waiting_connect,
+ pending_free,
+ waiting_senddone,
+ first_pass,
+ first_soa_rcvd,
+ second_rr_rcvd,
+ first_repeat_rcvd,
+ recv_made,
+ warn_id,
+ timedout;
+ 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_bufferlist_t sendlist,
+ recvlist,
+ lengthlist;
+ isc_buffer_t recvbuf,
+ lengthbuf,
+ slbuf;
+ char *recvspace,
+ lengthspace[4],
+ slspace[4];
+ isc_socket_t *sock;
+ 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_buffer_t sendbuf;
+ 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;
+};
+#ifdef DIG_SIGCHASE
+struct dig_message {
+ dns_message_t *msg;
+ ISC_LINK(dig_message_t) link;
+};
+#endif
+
+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, qr;
+extern in_port_t port;
+extern unsigned int timeout;
+extern isc_mem_t *mctx;
+extern int sendcount;
+extern int ndots;
+extern int lookup_counter;
+extern int exitcode;
+extern isc_sockaddr_t bind_address;
+extern char keynametext[MXNAME];
+extern char keyfile[MXNAME];
+extern char keysecret[MXNAME];
+extern dns_name_t *hmacname;
+extern unsigned int digestbits;
+#ifdef DIG_SIGCHASE
+extern char trustedkey[MXNAME];
+#endif
+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;
+#ifdef WITH_IDNKIT
+extern int idnoptions;
+#endif
+
+/*
+ * 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 ip6_int,
+ bool strict);
+
+ISC_PLATFORM_NORETURN_PRE void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+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);
+
+#ifdef DIG_SIGCHASE
+void
+clean_trustedkey(void);
+#endif
+
+char *
+next_token(char **stringp, const char *delim);
+
+/*
+ * Routines to be defined in dig.c, host.c, and nslookup.c. and
+ * then assigned to the appropriate function pointer
+ */
+#ifdef DIG_SIGCHASE
+extern isc_result_t
+(*dighost_printrdataset)(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target);
+#endif
+
+extern isc_result_t
+(*dighost_printmessage)(dig_query_t *query, dns_message_t *msg, bool headers);
+/*%<
+ * 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);
+
+#ifdef DIG_SIGCHASE
+/* Chasing functions */
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers);
+void
+chase_sig(dns_message_t *msg);
+#endif
+
+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);
+
+/*%<
+ * Cleans up the application
+ */
+void
+dig_shutdown(void);
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/dig/nslookup.1 b/bin/dig/nslookup.1
new file mode 100644
index 0000000..761b0d4
--- /dev/null
+++ b/bin/dig/nslookup.1
@@ -0,0 +1,294 @@
+.\" Copyright (C) 2004-2007, 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: nslookup
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-24
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NSLOOKUP" "1" "2014\-01\-24" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nslookup \- query Internet name servers interactively
+.SH "SYNOPSIS"
+.HP \w'\fBnslookup\fR\ 'u
+\fBnslookup\fR [\fB\-option\fR] [name\ |\ \-] [server]
+.SH "DESCRIPTION"
+.PP
+\fBNslookup\fR
+is a program to query Internet domain name servers\&.
+\fBNslookup\fR
+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 is used to print just the name and requested information for a host or domain\&.
+.SH "ARGUMENTS"
+.PP
+Interactive mode is entered in the following cases:
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 1.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 1." 4.2
+.\}
+when no arguments are given (the default name server will be used)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 2.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 2." 4.2
+.\}
+when the first argument is a hyphen (\-) and the second argument is the host name or Internet address of a name server\&.
+.RE
+.PP
+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\&.
+.PP
+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, and the initial timeout to 10 seconds, type:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+nslookup \-query=hinfo \-timeout=10
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+The
+\fB\-version\fR
+option causes
+\fBnslookup\fR
+to print the version number and immediately exits\&.
+.SH "INTERACTIVE COMMANDS"
+.PP
+\fBhost\fR [server]
+.RS 4
+Look up information for host using the current default server or using server, if specified\&. If host is an Internet address and the query type is A or PTR, the name of the host is returned\&. If host is a name and does not have a trailing period, the search list is used to qualify the name\&.
+.sp
+To look up a host not in the current domain, append a period to the name\&.
+.RE
+.PP
+\fBserver\fR \fIdomain\fR
+.RS 4
+.RE
+.PP
+\fBlserver\fR \fIdomain\fR
+.RS 4
+Change the default server to
+\fIdomain\fR;
+\fBlserver\fR
+uses the initial server to look up information about
+\fIdomain\fR, while
+\fBserver\fR
+uses the current default server\&. If an authoritative answer can\*(Aqt be found, the names of servers that might have the answer are returned\&.
+.RE
+.PP
+\fBroot\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBfinger\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBls\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBview\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBhelp\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fB?\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBexit\fR
+.RS 4
+Exits the program\&.
+.RE
+.PP
+\fBset\fR \fIkeyword\fR\fI[=value]\fR
+.RS 4
+This command is used to change state information that affects the lookups\&. Valid keywords are:
+.PP
+\fBall\fR
+.RS 4
+Prints the current values of the frequently used options to
+\fBset\fR\&. Information about the current default server and host is also printed\&.
+.RE
+.PP
+\fBclass=\fR\fIvalue\fR
+.RS 4
+Change the query class to one of:
+.PP
+\fBIN\fR
+.RS 4
+the Internet class
+.RE
+.PP
+\fBCH\fR
+.RS 4
+the Chaos class
+.RE
+.PP
+\fBHS\fR
+.RS 4
+the Hesiod class
+.RE
+.PP
+\fBANY\fR
+.RS 4
+wildcard
+.RE
+.sp
+The class specifies the protocol group of the information\&.
+.sp
+(Default = IN; abbreviation = cl)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBdebug\fR
+.RS 4
+Turn on or off the display of the full response packet and any intermediate response packets when searching\&.
+.sp
+(Default = nodebug; abbreviation =
+[no]deb)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBd2\fR
+.RS 4
+Turn debugging mode on or off\&. This displays more about what nslookup is doing\&.
+.sp
+(Default = nod2)
+.RE
+.PP
+\fBdomain=\fR\fIname\fR
+.RS 4
+Sets the search list to
+\fIname\fR\&.
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBsearch\fR
+.RS 4
+If the lookup request contains at least one period but doesn\*(Aqt end with a trailing period, append the domain names in the domain search list to the request until an answer is received\&.
+.sp
+(Default = search)
+.RE
+.PP
+\fBport=\fR\fIvalue\fR
+.RS 4
+Change the default TCP/UDP name server port to
+\fIvalue\fR\&.
+.sp
+(Default = 53; abbreviation = po)
+.RE
+.PP
+\fBquerytype=\fR\fIvalue\fR
+.RS 4
+.RE
+.PP
+\fBtype=\fR\fIvalue\fR
+.RS 4
+Change the type of the information query\&.
+.sp
+(Default = A; abbreviations = q, ty)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBrecurse\fR
+.RS 4
+Tell the name server to query other servers if it does not have the information\&.
+.sp
+(Default = recurse; abbreviation = [no]rec)
+.RE
+.PP
+\fBndots=\fR\fInumber\fR
+.RS 4
+Set the number of dots (label separators) in a domain that will disable searching\&. Absolute names always stop searching\&.
+.RE
+.PP
+\fBretry=\fR\fInumber\fR
+.RS 4
+Set the number of retries to number\&.
+.RE
+.PP
+\fBtimeout=\fR\fInumber\fR
+.RS 4
+Change the initial timeout interval for waiting for a reply to number seconds\&.
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBvc\fR
+.RS 4
+Always use a virtual circuit when sending requests to the server\&.
+.sp
+(Default = novc)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBfail\fR
+.RS 4
+Try the next nameserver if a nameserver responds with SERVFAIL or a referral (nofail) or terminate query (fail) on such a response\&.
+.sp
+(Default = nofail)
+.RE
+.sp
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBnslookup\fR
+returns with an exit status of 1 if any query failed, and 0 otherwise\&.
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBhost\fR(1),
+\fBnamed\fR(8)\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2004-2007, 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c
new file mode 100644
index 0000000..59bd01b
--- /dev/null
+++ b/bin/dig/nslookup.c
@@ -0,0 +1,1037 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+#include <isc/netaddr.h>
+
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/fixedname.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/byaddr.h>
+
+#include <dig/dig.h>
+
+#if defined(HAVE_READLINE)
+#if defined(HAVE_EDIT_READLINE_READLINE_H)
+#include <edit/readline/readline.h>
+#if defined(HAVE_EDIT_READLINE_HISTORY_H)
+#include <edit/readline/history.h>
+#endif
+#elif defined(HAVE_EDITLINE_READLINE_H)
+#include <editline/readline.h>
+#elif defined(HAVE_READLINE_READLINE_H)
+#include <readline/readline.h>
+#if defined (HAVE_READLINE_HISTORY_H)
+#include <readline/history.h>
+#endif
+#endif
+#endif
+
+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 flush_lookup_list(void);
+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;
+
+ flush_lookup_list();
+ 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));
+}
+
+#ifdef DIG_SIGCHASE
+/* Just for compatibility : not use in host program */
+static isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ UNUSED(owner_name);
+ UNUSED(rdataset);
+ UNUSED(target);
+ return(false);
+}
+#endif
+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) {
+ result = isc_buffer_allocate(mctx, &b, size);
+ if (result != ISC_R_SUCCESS)
+ check_result(result, "isc_buffer_allocate");
+ 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, NULL);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+static isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, bool headers) {
+ char servtext[ISC_SOCKADDR_FORMATSIZE];
+
+ /* 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, NULL);
+ 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;
+}
+
+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) {
+ fputs("nslookup " VERSION "\n", stderr);
+}
+
+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, lookup->ip6_int, 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->udpsize = 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;
+ 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;
+
+ ptr = next_token(&input, " \t\r\n");
+ if (ptr == NULL)
+ return;
+ arg = next_token(&input, " \t\r\n");
+ 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 *buf;
+ char *ptr;
+
+ fflush(stdout);
+ buf = isc_mem_allocate(mctx, COMMSIZE);
+ if (buf == NULL)
+ fatal("memory allocation failure");
+ isc_app_block();
+ if (interactive) {
+#ifdef HAVE_READLINE
+ ptr = readline("> ");
+ if (ptr != NULL)
+ add_history(ptr);
+#else
+ fputs("> ", stderr);
+ fflush(stderr);
+ ptr = fgets(buf, COMMSIZE, stdin);
+#endif
+ } else
+ ptr = fgets(buf, COMMSIZE, stdin);
+ isc_app_unblock();
+ if (ptr == NULL) {
+ in_use = false;
+ } else
+ do_next_command(ptr);
+#ifdef HAVE_READLINE
+ if (interactive)
+ free(ptr);
+#endif
+ isc_mem_free(mctx, buf);
+}
+
+static void
+parse_args(int argc, char **argv) {
+ bool have_lookup = false;
+
+ usesearch = true;
+ for (argc--, argv++; argc > 0; 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 {
+ set_nameserver(argv[0]);
+ check_ra = false;
+ }
+ }
+ }
+}
+
+static void
+flush_lookup_list(void) {
+ dig_lookup_t *l, *lp;
+ dig_query_t *q, *qp;
+ dig_server_t *s, *sp;
+
+ lookup_counter = 0;
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ q = ISC_LIST_HEAD(l->q);
+ while (q != NULL) {
+ if (q->sock != NULL) {
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ isc_socket_detach(&q->sock);
+ }
+ if (ISC_LINK_LINKED(&q->recvbuf, link))
+ ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
+ link);
+ if (ISC_LINK_LINKED(&q->lengthbuf, link))
+ ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
+ link);
+ isc_buffer_invalidate(&q->recvbuf);
+ isc_buffer_invalidate(&q->lengthbuf);
+ qp = q;
+ q = ISC_LIST_NEXT(q, link);
+ ISC_LIST_DEQUEUE(l->q, qp, link);
+ isc_mem_free(mctx, qp);
+ }
+ s = ISC_LIST_HEAD(l->my_server_list);
+ while (s != NULL) {
+ sp = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
+ isc_mem_free(mctx, sp);
+
+ }
+ if (l->sendmsg != NULL)
+ dns_message_destroy(&l->sendmsg);
+ lp = l;
+ l = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, lp, link);
+ isc_mem_free(mctx, lp);
+ }
+}
+
+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 */
+#ifdef DIG_SIGCHASE
+ dighost_printrdataset = printrdataset;
+#endif
+ 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.docbook b/bin/dig/nslookup.docbook
new file mode 100644
index 0000000..cc47aab
--- /dev/null
+++ b/bin/dig/nslookup.docbook
@@ -0,0 +1,501 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!--
+ - Copyright (c) 1985, 1989
+ - The Regents of the University of California. All rights reserved.
+ -
+ - Redistribution and use in source and binary forms, with or without
+ - modification, are permitted provided that the following conditions
+ - are met:
+ - 1. Redistributions of source code must retain the above copyright
+ - notice, this list of conditions and the following disclaimer.
+ - 2. Redistributions in binary form must reproduce the above copyright
+ - notice, this list of conditions and the following disclaimer in the
+ - documentation and/or other materials provided with the distribution.
+ - 3. Neither the name of the University nor the names of its contributors
+ - may be used to endorse or promote products derived from this software
+ - without specific prior written permission.
+ -
+ - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ - SUCH DAMAGE.
+-->
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.nslookup">
+ <info>
+ <date>2014-01-24</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>nslookup</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>nslookup</refname>
+ <refpurpose>query Internet name servers interactively</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2010</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>nslookup</command>
+ <arg choice="opt" rep="norepeat"><option>-option</option></arg>
+ <arg choice="opt" rep="norepeat">name | -</arg>
+ <arg choice="opt" rep="norepeat">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>Nslookup</command>
+ is a program to query Internet domain name servers. <command>Nslookup</command>
+ 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
+ is
+ used to print just the name and requested information for a host or
+ domain.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <para>
+ Interactive mode is entered in the following cases:
+ <orderedlist numeration="loweralpha" inheritnum="ignore" continuation="restarts">
+ <listitem>
+ <para>
+ when no arguments are given (the default name server will be used)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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, and the initial
+ timeout to 10 seconds, type:
+ <!-- <informalexample> produces bad nroff. -->
+ <programlisting>
+nslookup -query=hinfo -timeout=10
+</programlisting>
+ <!-- </informalexample> -->
+ </para>
+ <para>
+ The <option>-version</option> option causes
+ <command>nslookup</command> to print the version
+ number and immediately exits.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>INTERACTIVE COMMANDS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>host</constant> <optional>server</optional></term>
+ <listitem>
+ <para>
+ Look up information for host using the current default server or
+ using server, if specified. If host is an Internet address and
+ the query type is A or PTR, the name of the host is returned.
+ If host is a name and does not have a trailing period, the
+ search list is used to qualify the name.
+ </para>
+
+ <para>
+ To look up a host not in the current domain, append a period to
+ the name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>server</constant> <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para/>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>lserver</constant> <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Change the default server to <replaceable>domain</replaceable>; <constant>lserver</constant> uses the initial
+ server to look up information about <replaceable>domain</replaceable>, while <constant>server</constant> uses
+ the current default server. If an authoritative answer can't be
+ found, the names of servers that might have the answer are
+ returned.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>root</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>finger</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ls</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>view</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>help</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>?</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>exit</constant></term>
+ <listitem>
+ <para>
+ Exits the program.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>set</constant>
+ <replaceable>keyword<optional>=value</optional></replaceable></term>
+ <listitem>
+ <para>
+ This command is used to change state information that affects
+ the lookups. Valid keywords are:
+ <variablelist>
+ <varlistentry>
+ <term><constant>all</constant></term>
+ <listitem>
+ <para>
+ Prints the current values of the frequently used
+ options to <command>set</command>.
+ Information about the current default
+ server and host is also printed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>class=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the query class to one of:
+ <variablelist>
+ <varlistentry>
+ <term><constant>IN</constant></term>
+ <listitem>
+ <para>
+ the Internet class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>CH</constant></term>
+ <listitem>
+ <para>
+ the Chaos class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>HS</constant></term>
+ <listitem>
+ <para>
+ the Hesiod class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>ANY</constant></term>
+ <listitem>
+ <para>
+ wildcard
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ The class specifies the protocol group of the information.
+
+ </para>
+ <para>
+ (Default = IN; abbreviation = cl)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>debug</constant></term>
+ <listitem>
+ <para>
+ Turn on or off the display of the full response packet and
+ any intermediate response packets when searching.
+ </para>
+ <para>
+ (Default = nodebug; abbreviation = <optional>no</optional>deb)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>d2</constant></term>
+ <listitem>
+ <para>
+ Turn debugging mode on or off. This displays more about
+ what nslookup is doing.
+ </para>
+ <para>
+ (Default = nod2)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>domain=</constant><replaceable>name</replaceable></term>
+ <listitem>
+ <para>
+ Sets the search list to <replaceable>name</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>search</constant></term>
+ <listitem>
+ <para>
+ If the lookup request contains at least one period but
+ doesn't end with a trailing period, append the domain
+ names in the domain search list to the request until an
+ answer is received.
+ </para>
+ <para>
+ (Default = search)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>port=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the default TCP/UDP name server port to <replaceable>value</replaceable>.
+ </para>
+ <para>
+ (Default = 53; abbreviation = po)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>querytype=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the type of the information query.
+ </para>
+ <para>
+ (Default = A; abbreviations = q, ty)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>recurse</constant></term>
+ <listitem>
+ <para>
+ Tell the name server to query other servers if it does not
+ have the
+ information.
+ </para>
+ <para>
+ (Default = recurse; abbreviation = [no]rec)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ndots=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Set the number of dots (label separators) in a domain
+ that will disable searching. Absolute names always
+ stop searching.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>retry=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Set the number of retries to number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>timeout=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Change the initial timeout interval for waiting for a
+ reply to number seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>vc</constant></term>
+ <listitem>
+ <para>
+ Always use a virtual circuit when sending requests to the
+ server.
+ </para>
+ <para>
+ (Default = novc)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>fail</constant></term>
+ <listitem>
+ <para>
+ Try the next nameserver if a nameserver responds with
+ SERVFAIL or a referral (nofail) or terminate query
+ (fail) on such a response.
+ </para>
+ <para>
+ (Default = nofail)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>RETURN VALUES</title></info>
+ <para>
+ <command>nslookup</command> returns with an exit status of 1
+ if any query failed, and 0 otherwise.
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>host</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsection>
+</refentry>
diff --git a/bin/dig/nslookup.html b/bin/dig/nslookup.html
new file mode 100644
index 0000000..d5b038b
--- /dev/null
+++ b/bin/dig/nslookup.html
@@ -0,0 +1,386 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2004-2007, 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nslookup</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.nslookup"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ nslookup
+ &#8212; query Internet name servers interactively
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">nslookup</code>
+ [<code class="option">-option</code>]
+ [name | -]
+ [server]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>Nslookup</strong></span>
+ is a program to query Internet domain name servers. <span class="command"><strong>Nslookup</strong></span>
+ 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
+ is
+ used to print just the name and requested information for a host or
+ domain.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <p>
+ Interactive mode is entered in the following cases:
+ </p>
+<div class="orderedlist"><ol class="orderedlist" type="a">
+<li class="listitem">
+ <p>
+ when no arguments are given (the default name server will be used)
+ </p>
+ </li>
+<li class="listitem">
+ <p>
+ when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+ </p>
+ </li>
+</ol></div>
+<p>
+ </p>
+
+ <p>
+ 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.
+ </p>
+
+ <p>
+ 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, and the initial
+ timeout to 10 seconds, type:
+
+ </p>
+<pre class="programlisting">
+nslookup -query=hinfo -timeout=10
+</pre>
+<p>
+
+ </p>
+ <p>
+ The <code class="option">-version</code> option causes
+ <span class="command"><strong>nslookup</strong></span> to print the version
+ number and immediately exits.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>INTERACTIVE COMMANDS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">host</code> [<span class="optional">server</span>]</span></dt>
+<dd>
+ <p>
+ Look up information for host using the current default server or
+ using server, if specified. If host is an Internet address and
+ the query type is A or PTR, the name of the host is returned.
+ If host is a name and does not have a trailing period, the
+ search list is used to qualify the name.
+ </p>
+
+ <p>
+ To look up a host not in the current domain, append a period to
+ the name.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">server</code> <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p></p>
+ </dd>
+<dt><span class="term"><code class="constant">lserver</code> <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p>
+ Change the default server to <em class="replaceable"><code>domain</code></em>; <code class="constant">lserver</code> uses the initial
+ server to look up information about <em class="replaceable"><code>domain</code></em>, while <code class="constant">server</code> uses
+ the current default server. If an authoritative answer can't be
+ found, the names of servers that might have the answer are
+ returned.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">root</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">finger</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">ls</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">view</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">help</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">?</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">exit</code></span></dt>
+<dd>
+ <p>
+ Exits the program.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">set</code>
+ <em class="replaceable"><code>keyword[<span class="optional">=value</span>]</code></em></span></dt>
+<dd>
+ <p>
+ This command is used to change state information that affects
+ the lookups. Valid keywords are:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">all</code></span></dt>
+<dd>
+ <p>
+ Prints the current values of the frequently used
+ options to <span class="command"><strong>set</strong></span>.
+ Information about the current default
+ server and host is also printed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">class=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p>
+ Change the query class to one of:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">IN</code></span></dt>
+<dd>
+ <p>
+ the Internet class
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">CH</code></span></dt>
+<dd>
+ <p>
+ the Chaos class
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">HS</code></span></dt>
+<dd>
+ <p>
+ the Hesiod class
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">ANY</code></span></dt>
+<dd>
+ <p>
+ wildcard
+ </p>
+ </dd>
+</dl></div>
+<p>
+ The class specifies the protocol group of the information.
+
+ </p>
+ <p>
+ (Default = IN; abbreviation = cl)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>debug</code></span></dt>
+<dd>
+ <p>
+ Turn on or off the display of the full response packet and
+ any intermediate response packets when searching.
+ </p>
+ <p>
+ (Default = nodebug; abbreviation = [<span class="optional">no</span>]deb)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>d2</code></span></dt>
+<dd>
+ <p>
+ Turn debugging mode on or off. This displays more about
+ what nslookup is doing.
+ </p>
+ <p>
+ (Default = nod2)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">domain=</code><em class="replaceable"><code>name</code></em></span></dt>
+<dd>
+ <p>
+ Sets the search list to <em class="replaceable"><code>name</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>search</code></span></dt>
+<dd>
+ <p>
+ If the lookup request contains at least one period but
+ doesn't end with a trailing period, append the domain
+ names in the domain search list to the request until an
+ answer is received.
+ </p>
+ <p>
+ (Default = search)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">port=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p>
+ Change the default TCP/UDP name server port to <em class="replaceable"><code>value</code></em>.
+ </p>
+ <p>
+ (Default = 53; abbreviation = po)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">querytype=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p></p>
+ </dd>
+<dt><span class="term"><code class="constant">type=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p>
+ Change the type of the information query.
+ </p>
+ <p>
+ (Default = A; abbreviations = q, ty)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>recurse</code></span></dt>
+<dd>
+ <p>
+ Tell the name server to query other servers if it does not
+ have the
+ information.
+ </p>
+ <p>
+ (Default = recurse; abbreviation = [no]rec)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">ndots=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Set the number of dots (label separators) in a domain
+ that will disable searching. Absolute names always
+ stop searching.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">retry=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Set the number of retries to number.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">timeout=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Change the initial timeout interval for waiting for a
+ reply to number seconds.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>vc</code></span></dt>
+<dd>
+ <p>
+ Always use a virtual circuit when sending requests to the
+ server.
+ </p>
+ <p>
+ (Default = novc)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>fail</code></span></dt>
+<dd>
+ <p>
+ Try the next nameserver if a nameserver responds with
+ SERVFAIL or a referral (nofail) or terminate query
+ (fail) on such a response.
+ </p>
+ <p>
+ (Default = nofail)
+ </p>
+ </dd>
+</dl></div>
+<p>
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>RETURN VALUES</h2>
+ <p>
+ <span class="command"><strong>nslookup</strong></span> returns with an exit status of 1
+ if any query failed, and 0 otherwise.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/resolv.conf</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dig</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">host</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>.
+ </p>
+ </div>
+</div></body>
+</html>
diff --git a/bin/dig/win32/dig.dsp.in b/bin/dig/win32/dig.dsp.in
new file mode 100644
index 0000000..8e57707
--- /dev/null
+++ b/bin/dig/win32/dig.dsp.in
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="dig" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=dig - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak" CFG="dig - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "dig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dig.exe"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "dig - @PLATFORM@ Release"
+# Name "dig - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\dig.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\dig\dig.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/dig.dsw b/bin/dig/win32/dig.dsw
new file mode 100644
index 0000000..ae9c548
--- /dev/null
+++ b/bin/dig/win32/dig.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dig"=".\dig.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/dig.mak.in b/bin/dig/win32/dig.mak.in
new file mode 100644
index 0000000..10cdf75
--- /dev/null
+++ b/bin/dig/win32/dig.mak.in
@@ -0,0 +1,427 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on dig.dsp
+!IF "$(CFG)" == ""
+CFG=dig - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to dig - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "dig - @PLATFORM@ Release" && "$(CFG)" != "dig - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak" CFG="dig - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "dig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\dig.exe"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\dig.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dig.obj"
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dig.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dig.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dig.pdb" @MACHINE@ /out:"../../../Build/Release/dig.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dig.obj" \
+ "$(INTDIR)\dighost.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dig.obj"
+ -@erase "$(INTDIR)\dig.sbr"
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dig.bsc"
+ -@erase "$(OUTDIR)\dig.pdb"
+ -@erase "..\..\..\Build\Debug\dig.exe"
+ -@erase "..\..\..\Build\Debug\dig.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dig.sbr" \
+ "$(INTDIR)\dighost.sbr"
+
+"$(OUTDIR)\dig.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dig.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dig.obj" \
+ "$(INTDIR)\dighost.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("dig.dep")
+!INCLUDE "dig.dep"
+!ELSE
+!MESSAGE Warning: cannot find "dig.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release" || "$(CFG)" == "dig - @PLATFORM@ Debug"
+SOURCE=..\dig.c
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dig.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dig.obj" "$(INTDIR)\dig.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/dig.vcxproj.filters.in b/bin/dig/win32/dig.vcxproj.filters.in
new file mode 100644
index 0000000..1d92732
--- /dev/null
+++ b/bin/dig/win32/dig.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\dig\dig.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dig.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/dig.vcxproj.in b/bin/dig/win32/dig.vcxproj.in
new file mode 100644
index 0000000..2214a51
--- /dev/null
+++ b/bin/dig/win32/dig.vcxproj.in
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F938F9B8-D395-4A40-BEC7-0122D289C692}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dig</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;@IDN_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;@IDN_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\dig\dig.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dig.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/dig.vcxproj.user b/bin/dig/win32/dig.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/dig.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/dighost.dsp.in b/bin/dig/win32/dighost.dsp.in
new file mode 100644
index 0000000..33b7c8d
--- /dev/null
+++ b/bin/dig/win32/dighost.dsp.in
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="dighost" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104
+
+CFG=dighost - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dighost.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dighost.mak" CFG="dighost - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dighost - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE "dighost - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dighost - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "NDEBUG" @CRYPTO@ /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fddighost
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/dighost.lib"
+
+!ELSEIF "$(CFG)" == "dighost - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fddighost
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/dighost.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dighost - @PLATFORM@ Release"
+# Name "dighost - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dighost.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/dighost.dsw b/bin/dig/win32/dighost.dsw
new file mode 100644
index 0000000..fdae6d4
--- /dev/null
+++ b/bin/dig/win32/dighost.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dighost"=".\dighost.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/dighost.vcxproj.filters.in b/bin/dig/win32/dighost.vcxproj.filters.in
new file mode 100644
index 0000000..d108bfb
--- /dev/null
+++ b/bin/dig/win32/dighost.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dighost.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/dighost.vcxproj.in b/bin/dig/win32/dighost.vcxproj.in
new file mode 100644
index 0000000..2380506
--- /dev/null
+++ b/bin/dig/win32/dighost.vcxproj.in
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{140DE800-E552-43CC-B0C7-A33A92E368CA}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dighost</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dighost.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/dighost.vcxproj.user b/bin/dig/win32/dighost.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/dighost.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/host.dsp.in b/bin/dig/win32/host.dsp.in
new file mode 100644
index 0000000..adb48d5
--- /dev/null
+++ b/bin/dig/win32/host.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="host" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=host - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak" CFG="host - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "host - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/host.exe"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "host - @PLATFORM@ Release"
+# Name "host - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\host.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/host.dsw b/bin/dig/win32/host.dsw
new file mode 100644
index 0000000..e566e78
--- /dev/null
+++ b/bin/dig/win32/host.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "host"=".\host.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/host.mak.in b/bin/dig/win32/host.mak.in
new file mode 100644
index 0000000..2653ef0
--- /dev/null
+++ b/bin/dig/win32/host.mak.in
@@ -0,0 +1,427 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on host.dsp
+!IF "$(CFG)" == ""
+CFG=host - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to host - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "host - @PLATFORM@ Release" && "$(CFG)" != "host - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak" CFG="host - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "host - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\host.exe"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\host.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\host.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\host.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\host.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\host.pdb" @MACHINE@ /out:"../../../Build/Release/host.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\host.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\host.obj"
+ -@erase "$(INTDIR)\host.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\host.bsc"
+ -@erase "$(OUTDIR)\host.pdb"
+ -@erase "..\..\..\Build\Debug\host.exe"
+ -@erase "..\..\..\Build\Debug\host.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dighost.sbr" \
+ "$(INTDIR)\host.sbr"
+
+"$(OUTDIR)\host.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\host.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\host.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("host.dep")
+!INCLUDE "host.dep"
+!ELSE
+!MESSAGE Warning: cannot find "host.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release" || "$(CFG)" == "host - @PLATFORM@ Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\host.c
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+
+"$(INTDIR)\host.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\host.obj" "$(INTDIR)\host.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/host.vcxproj.filters.in b/bin/dig/win32/host.vcxproj.filters.in
new file mode 100644
index 0000000..56e7818
--- /dev/null
+++ b/bin/dig/win32/host.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\host.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/host.vcxproj.in b/bin/dig/win32/host.vcxproj.in
new file mode 100644
index 0000000..e909608
--- /dev/null
+++ b/bin/dig/win32/host.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BA1048A8-6961-4A20-BE12-08BE20611C9D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>host</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\host.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/host.vcxproj.user b/bin/dig/win32/host.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/host.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/nslookup.dsp.in b/bin/dig/win32/nslookup.dsp.in
new file mode 100644
index 0000000..9c4800a
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsp.in
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="nslookup" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=nslookup - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nslookup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @READLINE_LIB@ @IDN_LIB@ user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/nslookup.exe"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @READLINE_LIBD@ @IDN_LIB@ user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nslookup - @PLATFORM@ Release"
+# Name "nslookup - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\dighost.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nslookup.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/nslookup.dsw b/bin/dig/win32/nslookup.dsw
new file mode 100644
index 0000000..0ff8c66
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nslookup"=".\nslookup.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/nslookup.mak.in b/bin/dig/win32/nslookup.mak.in
new file mode 100644
index 0000000..233231e
--- /dev/null
+++ b/bin/dig/win32/nslookup.mak.in
@@ -0,0 +1,427 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nslookup.dsp
+!IF "$(CFG)" == ""
+CFG=nslookup - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to nslookup - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nslookup - @PLATFORM@ Release" && "$(CFG)" != "nslookup - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nslookup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\nslookup.exe"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\nslookup.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\nslookup.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\nslookup.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nslookup.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @READLINE_LIB@ @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nslookup.pdb" @MACHINE@ /out:"../../../Build/Release/nslookup.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\nslookup.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\nslookup.obj"
+ -@erase "$(INTDIR)\nslookup.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\nslookup.bsc"
+ -@erase "$(OUTDIR)\nslookup.pdb"
+ -@erase "..\..\..\Build\Debug\nslookup.exe"
+ -@erase "..\..\..\Build\Debug\nslookup.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dighost.sbr" \
+ "$(INTDIR)\nslookup.sbr"
+
+"$(OUTDIR)\nslookup.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @READLINE_LIBD@ @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nslookup.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\nslookup.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("nslookup.dep")
+!INCLUDE "nslookup.dep"
+!ELSE
+!MESSAGE Warning: cannot find "nslookup.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release" || "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nslookup.c
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+
+"$(INTDIR)\nslookup.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\nslookup.obj" "$(INTDIR)\nslookup.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/nslookup.vcxproj.filters.in b/bin/dig/win32/nslookup.vcxproj.filters.in
new file mode 100644
index 0000000..7f4756e
--- /dev/null
+++ b/bin/dig/win32/nslookup.vcxproj.filters.in
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dighost.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\nslookup.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/nslookup.vcxproj.in b/bin/dig/win32/nslookup.vcxproj.in
new file mode 100644
index 0000000..5c338ae
--- /dev/null
+++ b/bin/dig/win32/nslookup.vcxproj.in
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C15A6E1A-94CE-4686-99F9-6BC5FD623EB5}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>nslookup</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@USE_READLINE_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@READLINE_LIBD@@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@USE_READLINE_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@READLINE_LIB@@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dighost.c" />
+ <ClCompile Include="..\nslookup.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/nslookup.vcxproj.user b/bin/dig/win32/nslookup.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/nslookup.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in
new file mode 100644
index 0000000..2239ad1
--- /dev/null
+++ b/bin/dnssec/Makefile.in
@@ -0,0 +1,123 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.42.332.1 2011/03/16 06:37:51 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \
+ @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@
+
+# Alphabetically
+TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
+ dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
+ dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \
+ dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@
+
+OBJS = dnssectool.@O@
+
+SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
+ dnssec-revoke.c dnssec-settime.c dnssec-signzone.c \
+ dnssec-verify.c dnssec-importkey.c dnssectool.c
+
+MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \
+ dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8 \
+ dnssec-verify.8 dnssec-importkey.8
+
+HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \
+ dnssec-keygen.html dnssec-revoke.html \
+ dnssec-settime.html dnssec-signzone.html \
+ dnssec-verify.html dnssec-importkey.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+dnssec-signzone.@O@: dnssec-signzone.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/dnssec-signzone.c
+
+dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+dnssec-verify.@O@: dnssec-verify.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/dnssec-verify.c
+
+dnssec-verify@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-verify.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-revoke.@O@ ${OBJS} ${LIBS}
+
+dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-settime.@O@ ${OBJS} ${LIBS}
+
+dnssec-importkey@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-importkey.@O@ ${OBJS} ${LIBS}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: ${TARGETS} installdirs
+ for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir} || exit 1; done
+ for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8 || exit 1; done
+
+uninstall::
+ for m in ${MANPAGES}; do rm -f ${DESTDIR}${mandir}/man8/$$m || exit 1; done
+ for t in ${TARGETS}; do ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/$$t || exit 1; done
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/dnssec/dnssec-dsfromkey.8 b/bin/dnssec/dnssec-dsfromkey.8
new file mode 100644
index 0000000..0a0600c
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.8
@@ -0,0 +1,182 @@
+.\" Copyright (C) 2008-2012, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-dsfromkey
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2012-05-02
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-DSFROMKEY" "8" "2012\-05\-02" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-dsfromkey \- DNSSEC DS RR generation tool
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-dsfromkey\fR\ 'u
+\fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-C\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-T\ \fR\fB\fITTL\fR\fR] {keyfile}
+.HP \w'\fBdnssec\-dsfromkey\fR\ 'u
+\fBdnssec\-dsfromkey\fR {\-s} [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-s\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-T\ \fR\fB\fITTL\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-A\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {dnsname}
+.HP \w'\fBdnssec\-dsfromkey\fR\ 'u
+\fBdnssec\-dsfromkey\fR [\fB\-h\fR] [\fB\-V\fR]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-dsfromkey\fR
+outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s)\&.
+.SH "OPTIONS"
+.PP
+\-1
+.RS 4
+Use SHA\-1 as the digest algorithm (the default is to use both SHA\-1 and SHA\-256)\&.
+.RE
+.PP
+\-2
+.RS 4
+Use SHA\-256 as the digest algorithm\&.
+.RE
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Select the digest algorithm\&. The value of
+\fBalgorithm\fR
+must be one of SHA\-1 (SHA1), SHA\-256 (SHA256), GOST or SHA\-384 (SHA384)\&. These values are case insensitive\&.
+.RE
+.PP
+\-C
+.RS 4
+Generate CDS records rather than DS records\&. This is mutually exclusive with generating lookaside records\&.
+.RE
+.PP
+\-T \fITTL\fR
+.RS 4
+Specifies the TTL of the DS records\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Look for key files (or, in keyset mode,
+keyset\-
+files) in
+\fBdirectory\fR\&.
+.RE
+.PP
+\-f \fIfile\fR
+.RS 4
+Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from
+\fBfile\fR\&. If the zone name is the same as
+\fBfile\fR, then it may be omitted\&.
+.sp
+If
+\fBfile\fR
+is set to
+"\-", then the zone data is read from the standard input\&. This makes it possible to use the output of the
+\fBdig\fR
+command as input, as in:
+.sp
+\fBdig dnskey example\&.com | dnssec\-dsfromkey \-f \- example\&.com\fR
+.RE
+.PP
+\-A
+.RS 4
+Include ZSKs when generating DS records\&. Without this option, only keys which have the KSK flag set will be converted to DS records and printed\&. Useful only in zone file mode\&.
+.RE
+.PP
+\-l \fIdomain\fR
+.RS 4
+Generate a DLV set instead of a DS set\&. The specified
+\fBdomain\fR
+is appended to the name for each record in the set\&. The DNSSEC Lookaside Validation (DLV) RR is described in RFC 4431\&. This is mutually exclusive with generating CDS records\&.
+.RE
+.PP
+\-s
+.RS 4
+Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file\&.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specifies the DNS class (default is IN)\&. Useful only in keyset or zone file mode\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-h
+.RS 4
+Prints usage information\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.SH "EXAMPLE"
+.PP
+To build the SHA\-256 DS RR from the
+\fBKexample\&.com\&.+003+26160\fR
+keyfile name, the following command would be issued:
+.PP
+\fBdnssec\-dsfromkey \-2 Kexample\&.com\&.+003+26160\fR
+.PP
+The command would print something like:
+.PP
+\fBexample\&.com\&. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94\fR
+.SH "FILES"
+.PP
+The keyfile can be designed by the key identification
+Knnnn\&.+aaa+iiiii
+or the full file name
+Knnnn\&.+aaa+iiiii\&.key
+as generated by
+dnssec\-keygen(8)\&.
+.PP
+The keyset file name is built from the
+\fBdirectory\fR, the string
+keyset\-
+and the
+\fBdnsname\fR\&.
+.SH "CAVEAT"
+.PP
+A keyfile error can give a "file not found" even if the file exists\&.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 3658,
+RFC 4431\&.
+RFC 4509\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2008-2012, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c
new file mode 100644
index 0000000..65fdaaa
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.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 <dns/result.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
+#endif
+
+const char *program = "dnssec-dsfromkey";
+int verbose;
+
+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);
+ 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);
+ result = dns_name_copy(dst_key_name(key), name, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't copy 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(unsigned int dtype, bool showall, char *lookaside,
+ 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_KSK) == 0 && !showall)
+ return;
+
+ result = dns_ds_buildrdata(name, rdata, dtype, 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");
+
+ /* Add lookaside origin, if set */
+ if (lookaside != NULL) {
+ if (isc_buffer_availablelength(&nameb) < strlen(lookaside))
+ fatal("DLV origin '%s' is too long", lookaside);
+ isc_buffer_putstr(&nameb, lookaside);
+ if (lookaside[strlen(lookaside) - 1] != '.') {
+ if (isc_buffer_availablelength(&nameb) < 1)
+ fatal("DLV origin '%s' is too long", lookaside);
+ isc_buffer_putstr(&nameb, ".");
+ }
+ }
+
+ 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 (lookaside == NULL) {
+ if (cds)
+ printf(" CDS ");
+ else
+ printf(" DS ");
+ } else
+ printf(" DLV ");
+
+ isc_buffer_usedregion(&textb, &r);
+ printf("%.*s\n", (int)r.length, r.base);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s options [-K dir] keyfile\n\n", program);
+ fprintf(stderr, " %s options [-K dir] [-c class] -s dnsname\n\n",
+ program);
+ fprintf(stderr, " %s options -f zonefile (as zone name)\n\n", program);
+ fprintf(stderr, " %s options -f zonefile zonename\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -V: print version information\n");
+ fprintf(stderr, " -K <directory>: directory in which to find "
+ "key file or keyset file\n");
+ fprintf(stderr, " -a algorithm: digest algorithm "
+ "(SHA-1, SHA-256, GOST or SHA-384)\n");
+ fprintf(stderr, " -1: use SHA-1\n");
+ fprintf(stderr, " -2: use SHA-256\n");
+ fprintf(stderr, " -C: print CDS record\n");
+ fprintf(stderr, " -l: add lookaside zone and print DLV records\n");
+ fprintf(stderr, " -s: read keyset from keyset-<dnsname> file\n");
+ fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n");
+ fprintf(stderr, " -T TTL\n");
+ fprintf(stderr, " -f file: read keyset from zone file\n");
+ fprintf(stderr, " -A: when used with -f, "
+ "include all keys in DS set, not just KSKs\n");
+ fprintf(stderr, "Output: DS or DLV RRs\n");
+
+ exit (-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *classname = NULL;
+ char *filename = NULL, *dir = NULL, *namestr;
+ char *lookaside = NULL;
+ char *endp;
+ int ch;
+ unsigned int dtype = DNS_DSDIGEST_SHA1;
+ bool cds = false;
+ bool both = true;
+ bool usekeyset = false;
+ bool showall = false;
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata;
+
+ dns_rdata_init(&rdata);
+
+ if (argc == 1)
+ usage();
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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':
+ dtype = DNS_DSDIGEST_SHA1;
+ both = false;
+ break;
+ case '2':
+ dtype = DNS_DSDIGEST_SHA256;
+ both = false;
+ break;
+ case 'A':
+ showall = true;
+ break;
+ case 'a':
+ algname = isc_commandline_argument;
+ both = false;
+ break;
+ case 'C':
+ if (lookaside != NULL)
+ fatal("lookaside and CDS are mutually"
+ " exclusive");
+ 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':
+ if (cds)
+ fatal("lookaside and CDS are mutually"
+ " exclusive");
+ lookaside = isc_commandline_argument;
+ if (strlen(lookaside) == 0U)
+ fatal("lookaside must be a non-empty string");
+ break;
+ case 's':
+ usekeyset = true;
+ break;
+ case 'T':
+ emitttl = true;
+ ttl = atol(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);
+ }
+ }
+
+ if (algname != NULL) {
+ if (strcasecmp(algname, "SHA1") == 0 ||
+ strcasecmp(algname, "SHA-1") == 0)
+ dtype = DNS_DSDIGEST_SHA1;
+ else if (strcasecmp(algname, "SHA256") == 0 ||
+ strcasecmp(algname, "SHA-256") == 0)
+ dtype = DNS_DSDIGEST_SHA256;
+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
+ else if (strcasecmp(algname, "GOST") == 0)
+ dtype = DNS_DSDIGEST_GOST;
+#endif
+ else if (strcasecmp(algname, "SHA384") == 0 ||
+ strcasecmp(algname, "SHA-384") == 0)
+ dtype = DNS_DSDIGEST_SHA384;
+ else
+ fatal("unknown algorithm %s", algname);
+ }
+
+ 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;
+
+ 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");
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize hash");
+ result = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ isc_entropy_stopcallbacksources(ectx);
+
+ setup_logging(mctx, &log);
+
+ dns_rdataset_init(&rdataset);
+
+ if (usekeyset || filename != NULL) {
+ if (argc < isc_commandline_index + 1 && filename != NULL) {
+ /* using zone name as the zone file name */
+ namestr = filename;
+ } else
+ namestr = argv[isc_commandline_index];
+
+ result = initname(namestr);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize name %s", namestr);
+
+ if (usekeyset)
+ result = loadkeyset(dir, &rdataset);
+ else
+ 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);
+
+ if (both) {
+ emit(DNS_DSDIGEST_SHA1, showall, lookaside,
+ cds, &rdata);
+ emit(DNS_DSDIGEST_SHA256, showall, lookaside,
+ cds, &rdata);
+ } else
+ emit(dtype, showall, lookaside, cds, &rdata);
+ }
+ } else {
+ unsigned char key_buf[DST_KEY_MAXSIZE];
+
+ loadkey(argv[isc_commandline_index], key_buf,
+ DST_KEY_MAXSIZE, &rdata);
+
+ if (both) {
+ emit(DNS_DSDIGEST_SHA1, showall, lookaside, cds,
+ &rdata);
+ emit(DNS_DSDIGEST_SHA256, showall, lookaside, cds,
+ &rdata);
+ } else
+ emit(dtype, showall, lookaside, cds, &rdata);
+ }
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_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.docbook b/bin/dnssec/dnssec-dsfromkey.docbook
new file mode 100644
index 0000000..4fdc507
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.docbook
@@ -0,0 +1,305 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-dsfromkey">
+ <info>
+ <date>2012-05-02</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-dsfromkey</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-dsfromkey</application></refname>
+ <refpurpose>DNSSEC DS RR generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-dsfromkey</command>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-1</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-2</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-C</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T <replaceable class="parameter">TTL</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">keyfile</arg>
+ </cmdsynopsis>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-dsfromkey</command>
+ <arg choice="req" rep="norepeat">-s</arg>
+ <arg choice="opt" rep="norepeat"><option>-1</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-2</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T <replaceable class="parameter">TTL</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-A</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">dnsname</arg>
+ </cmdsynopsis>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-dsfromkey</command>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-dsfromkey</command>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-1</term>
+ <listitem>
+ <para>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-2</term>
+ <listitem>
+ <para>
+ Use SHA-256 as the digest algorithm.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Select the digest algorithm. The value of
+ <option>algorithm</option> must be one of SHA-1 (SHA1),
+ SHA-256 (SHA256), GOST or SHA-384 (SHA384).
+ These values are case insensitive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Generate CDS records rather than DS records. This is mutually
+ exclusive with generating lookaside records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T <replaceable class="parameter">TTL</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the TTL of the DS records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Look for key files (or, in keyset mode,
+ <filename>keyset-</filename> files) in
+ <option>directory</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ Zone file mode: in place of the keyfile name, the argument is
+ the DNS domain name of a zone master file, which can be read
+ from <option>file</option>. If the zone name is the same as
+ <option>file</option>, then it may be omitted.
+ </para>
+ <para>
+ If <option>file</option> is set to <literal>"-"</literal>, then
+ the zone data is read from the standard input. This makes it
+ possible to use the output of the <command>dig</command>
+ command as input, as in:
+ </para>
+ <para>
+ <userinput>dig dnskey example.com | dnssec-dsfromkey -f - example.com</userinput>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A</term>
+ <listitem>
+ <para>
+ Include ZSKs when generating DS records. Without this option,
+ only keys which have the KSK flag set will be converted to DS
+ records and printed. Useful only in zone file mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Generate a DLV set instead of a DS set. The specified
+ <option>domain</option> is appended to the name for each
+ record in the set.
+ The DNSSEC Lookaside Validation (DLV) RR is described
+ in RFC 4431. This is mutually exclusive with generating
+ CDS records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Keyset mode: in place of the keyfile name, the argument is
+ the DNS domain name of a keyset file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class (default is IN). Useful only
+ in keyset or zone file mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints usage information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>EXAMPLE</title></info>
+
+ <para>
+ To build the SHA-256 DS RR from the
+ <userinput>Kexample.com.+003+26160</userinput>
+ keyfile name, the following command would be issued:
+ </para>
+ <para><userinput>dnssec-dsfromkey -2 Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ The command would print something like:
+ </para>
+ <para><userinput>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</userinput>
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para>
+ The keyfile can be designed by the key identification
+ <filename>Knnnn.+aaa+iiiii</filename> or the full file name
+ <filename>Knnnn.+aaa+iiiii.key</filename> as generated by
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>.
+ </para>
+ <para>
+ The keyset file name is built from the <option>directory</option>,
+ the string <filename>keyset-</filename> and the
+ <option>dnsname</option>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>CAVEAT</title></info>
+
+ <para>
+ A keyfile error can give a "file not found" even if the file exists.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 3658</citetitle>,
+ <citetitle>RFC 4431</citetitle>.
+ <citetitle>RFC 4509</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-dsfromkey.html b/bin/dnssec/dnssec-dsfromkey.html
new file mode 100644
index 0000000..031ccc6
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.html
@@ -0,0 +1,255 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2008-2012, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-dsfromkey</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-dsfromkey"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-dsfromkey</span>
+ &#8212; DNSSEC DS RR generation tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-dsfromkey</code>
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-1</code>]
+ [<code class="option">-2</code>]
+ [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>]
+ [<code class="option">-C</code>]
+ [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>]
+ [<code class="option">-T <em class="replaceable"><code>TTL</code></em></code>]
+ {keyfile}
+ </p></div>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-dsfromkey</code>
+ {-s}
+ [<code class="option">-1</code>]
+ [<code class="option">-2</code>]
+ [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>]
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>]
+ [<code class="option">-s</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-T <em class="replaceable"><code>TTL</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>file</code></em></code>]
+ [<code class="option">-A</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ {dnsname}
+ </p></div>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-dsfromkey</code>
+ [<code class="option">-h</code>]
+ [<code class="option">-V</code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-dsfromkey</strong></span>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-1</span></dt>
+<dd>
+ <p>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </p>
+ </dd>
+<dt><span class="term">-2</span></dt>
+<dd>
+ <p>
+ Use SHA-256 as the digest algorithm.
+ </p>
+ </dd>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+ <p>
+ Select the digest algorithm. The value of
+ <code class="option">algorithm</code> must be one of SHA-1 (SHA1),
+ SHA-256 (SHA256), GOST or SHA-384 (SHA384).
+ These values are case insensitive.
+ </p>
+ </dd>
+<dt><span class="term">-C</span></dt>
+<dd>
+ <p>
+ Generate CDS records rather than DS records. This is mutually
+ exclusive with generating lookaside records.
+ </p>
+ </dd>
+<dt><span class="term">-T <em class="replaceable"><code>TTL</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the TTL of the DS records.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Look for key files (or, in keyset mode,
+ <code class="filename">keyset-</code> files) in
+ <code class="option">directory</code>.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt>
+<dd>
+ <p>
+ Zone file mode: in place of the keyfile name, the argument is
+ the DNS domain name of a zone master file, which can be read
+ from <code class="option">file</code>. If the zone name is the same as
+ <code class="option">file</code>, then it may be omitted.
+ </p>
+ <p>
+ If <code class="option">file</code> is set to <code class="literal">"-"</code>, then
+ the zone data is read from the standard input. This makes it
+ possible to use the output of the <span class="command"><strong>dig</strong></span>
+ command as input, as in:
+ </p>
+ <p>
+ <strong class="userinput"><code>dig dnskey example.com | dnssec-dsfromkey -f - example.com</code></strong>
+ </p>
+ </dd>
+<dt><span class="term">-A</span></dt>
+<dd>
+ <p>
+ Include ZSKs when generating DS records. Without this option,
+ only keys which have the KSK flag set will be converted to DS
+ records and printed. Useful only in zone file mode.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p>
+ Generate a DLV set instead of a DS set. The specified
+ <code class="option">domain</code> is appended to the name for each
+ record in the set.
+ The DNSSEC Lookaside Validation (DLV) RR is described
+ in RFC 4431. This is mutually exclusive with generating
+ CDS records.
+ </p>
+ </dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+ <p>
+ Keyset mode: in place of the keyfile name, the argument is
+ the DNS domain name of a keyset file.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the DNS class (default is IN). Useful only
+ in keyset or zone file mode.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Prints usage information.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>EXAMPLE</h2>
+
+ <p>
+ To build the SHA-256 DS RR from the
+ <strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ keyfile name, the following command would be issued:
+ </p>
+ <p><strong class="userinput"><code>dnssec-dsfromkey -2 Kexample.com.+003+26160</code></strong>
+ </p>
+ <p>
+ The command would print something like:
+ </p>
+ <p><strong class="userinput"><code>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</code></strong>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>FILES</h2>
+
+ <p>
+ The keyfile can be designed by the key identification
+ <code class="filename">Knnnn.+aaa+iiiii</code> or the full file name
+ <code class="filename">Knnnn.+aaa+iiiii.key</code> as generated by
+ <span class="refentrytitle">dnssec-keygen</span>(8).
+ </p>
+ <p>
+ The keyset file name is built from the <code class="option">directory</code>,
+ the string <code class="filename">keyset-</code> and the
+ <code class="option">dnsname</code>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>CAVEAT</h2>
+
+ <p>
+ A keyfile error can give a "file not found" even if the file exists.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 3658</em>,
+ <em class="citetitle">RFC 4431</em>.
+ <em class="citetitle">RFC 4509</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-importkey.8 b/bin/dnssec/dnssec-importkey.8
new file mode 100644
index 0000000..8552948
--- /dev/null
+++ b/bin/dnssec/dnssec-importkey.8
@@ -0,0 +1,138 @@
+.\" Copyright (C) 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-importkey
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: August 21, 2015
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-IMPORTKEY" "8" "August 21, 2015" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-importkey \- import DNSKEY records from external systems so they can be managed
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-importkey\fR\ 'u
+\fBdnssec\-importkey\fR [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] {\fBkeyfile\fR}
+.HP \w'\fBdnssec\-importkey\fR\ 'u
+\fBdnssec\-importkey\fR {\fB\-f\ \fR\fB\fIfilename\fR\fR} [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fBdnsname\fR]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-importkey\fR
+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 will be generated, or it may be read from any other file or from the standard input, in which case both \&.key and \&.private files will be generated\&.
+.PP
+The newly\-created \&.private file does
+\fInot\fR
+contain private key data, and cannot be used for signing\&. However, having a \&.private file makes it possible to set publication (\fB\-P\fR) and deletion (\fB\-D\fR) 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\&.
+.SH "OPTIONS"
+.PP
+\-f \fIfilename\fR
+.RS 4
+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
+\fBfile\fR\&. If the domain name is the same as
+\fBfile\fR, then it may be omitted\&.
+.sp
+If
+\fBfile\fR
+is set to
+"\-", then the zone data is read from the standard input\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which the key files are to reside\&.
+.RE
+.PP
+\-L \fIttl\fR
+.RS 4
+Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, 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\&.
+.RE
+.PP
+\-h
+.RS 4
+Emit usage message and exit\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.SH "TIMING OPTIONS"
+.PP
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset 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 \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&.
+.PP
+\-P \fIdate/offset\fR
+.RS 4
+Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&.
+.RE
+.PP
+\-P sync \fIdate/offset\fR
+.RS 4
+Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone\&.
+.RE
+.PP
+\-D \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.)
+.RE
+.PP
+\-D sync \fIdate/offset\fR
+.RS 4
+Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted\&.
+.RE
+.SH "FILES"
+.PP
+A keyfile can be designed by the key identification
+Knnnn\&.+aaa+iiiii
+or the full file name
+Knnnn\&.+aaa+iiiii\&.key
+as generated by
+dnssec\-keygen(8)\&.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 5011\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-importkey.c b/bin/dnssec/dnssec-importkey.c
new file mode 100644
index 0000000..0d1e7f8
--- /dev/null
+++ b/bin/dnssec/dnssec-importkey.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.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 <dns/result.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
+#endif
+
+const char *program = "dnssec-importkey";
+int verbose;
+
+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_load3(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);
+ result = dns_name_copy(dst_key_name(key), name, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't copy 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);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+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", 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;
+ isc_entropy_t *ectx = 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();
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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");
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize hash");
+ result = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ isc_entropy_stopcallbacksources(ectx);
+
+ 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();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_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.docbook b/bin/dnssec/dnssec-importkey.docbook
new file mode 100644
index 0000000..c80fb24
--- /dev/null
+++ b/bin/dnssec/dnssec-importkey.docbook
@@ -0,0 +1,253 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-importkey">
+ <info>
+ <date>2014-02-20</date>
+ </info>
+ <refentryinfo>
+ <date>August 21, 2015</date>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-importkey</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-importkey</application></refname>
+ <refpurpose>import DNSKEY records from external systems so they can be managed</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-importkey</command>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="req" rep="norepeat"><option>keyfile</option></arg>
+ </cmdsynopsis>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-importkey</command>
+ <arg choice="req" rep="norepeat"><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>dnsname</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-importkey</command>
+ 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
+ will be generated, or it may be read from any other file or
+ from the standard input, in which case both .key and .private
+ files will be generated.
+ </para>
+ <para>
+ The newly-created .private file does <emphasis>not</emphasis>
+ contain private key data, and cannot be used for signing.
+ However, having a .private file makes it possible to set
+ publication (<option>-P</option>) and deletion
+ (<option>-D</option>) 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.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-f <replaceable class="parameter">filename</replaceable></term>
+ <listitem>
+ <para>
+ 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 <option>file</option>. If the domain name is the same as
+ <option>file</option>, then it may be omitted.
+ </para>
+ <para>
+ If <option>file</option> is set to <literal>"-"</literal>, then
+ the zone data is read from the standard input.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to reside.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. Setting the default TTL to
+ <literal>0</literal> or <literal>none</literal> removes it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Emit usage message and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>TIMING OPTIONS</title></info>
+
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which CDS and CDNSKEY records that match this
+ key are to be published to the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the CDS and CDNSKEY records that match
+ this key are to be deleted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para>
+ A keyfile can be designed by the key identification
+ <filename>Knnnn.+aaa+iiiii</filename> or the full file name
+ <filename>Knnnn.+aaa+iiiii.key</filename> as generated by
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 5011</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-importkey.html b/bin/dnssec/dnssec-importkey.html
new file mode 100644
index 0000000..036113c
--- /dev/null
+++ b/bin/dnssec/dnssec-importkey.html
@@ -0,0 +1,216 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-importkey</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-importkey"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-importkey</span>
+ &#8212; import DNSKEY records from external systems so they can be managed
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-importkey</code>
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-P sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-V</code>]
+ {<code class="option">keyfile</code>}
+ </p></div>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-importkey</code>
+ {<code class="option">-f <em class="replaceable"><code>filename</code></em></code>}
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-P sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-V</code>]
+ [<code class="option">dnsname</code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-importkey</strong></span>
+ 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
+ will be generated, or it may be read from any other file or
+ from the standard input, in which case both .key and .private
+ files will be generated.
+ </p>
+ <p>
+ The newly-created .private file does <span class="emphasis"><em>not</em></span>
+ contain private key data, and cannot be used for signing.
+ However, having a .private file makes it possible to set
+ publication (<code class="option">-P</code>) and deletion
+ (<code class="option">-D</code>) 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.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-f <em class="replaceable"><code>filename</code></em></span></dt>
+<dd>
+ <p>
+ 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 <code class="option">file</code>. If the domain name is the same as
+ <code class="option">file</code>, then it may be omitted.
+ </p>
+ <p>
+ If <code class="option">file</code> is set to <code class="literal">"-"</code>, then
+ the zone data is read from the standard input.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which the key files are to reside.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>ttl</code></em></span></dt>
+<dd>
+ <p>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. Setting the default TTL to
+ <code class="literal">0</code> or <code class="literal">none</code> removes it.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Emit usage message and exit.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>TIMING OPTIONS</h2>
+
+ <p>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-P sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which CDS and CDNSKEY records that match this
+ key are to be published to the zone.
+ </p>
+ </dd>
+<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </p>
+ </dd>
+<dt><span class="term">-D sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the CDS and CDNSKEY records that match
+ this key are to be deleted.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>FILES</h2>
+
+ <p>
+ A keyfile can be designed by the key identification
+ <code class="filename">Knnnn.+aaa+iiiii</code> or the full file name
+ <code class="filename">Knnnn.+aaa+iiiii.key</code> as generated by
+ <span class="refentrytitle">dnssec-keygen</span>(8).
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 5011</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-keyfromlabel.8 b/bin/dnssec/dnssec-keyfromlabel.8
new file mode 100644
index 0000000..05ba2b6
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.8
@@ -0,0 +1,305 @@
+.\" Copyright (C) 2008-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-keyfromlabel
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: August 27, 2015
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-KEYFROMLABEL" "8" "August 27, 2015" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-keyfromlabel \- DNSSEC key generation tool
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-keyfromlabel\fR\ 'u
+\fBdnssec\-keyfromlabel\fR {\-l\ \fIlabel\fR} [\fB\-3\fR] [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-k\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-y\fR] {name}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-keyfromlabel\fR
+generates a key pair of files that referencing 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
+\fBdnssec\-keygen\fR, but the key material is stored within the HSM, and the actual signing takes place there\&.
+.PP
+The
+\fBname\fR
+of the key is specified on the command line\&. This must match the name of the zone for which the key is being generated\&.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Selects the cryptographic algorithm\&. The value of
+\fBalgorithm\fR
+must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448\&. These values are case insensitive\&.
+.sp
+If no algorithm is specified, then RSASHA1 will be used by default, unless the
+\fB\-3\fR
+option is specified, in which case NSEC3RSASHA1 will be used instead\&. (If
+\fB\-3\fR
+is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3\&.)
+.sp
+Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended\&.
+.sp
+Note 2: DH automatically sets the \-k flag\&.
+.RE
+.PP
+\-3
+.RS 4
+Use an NSEC3\-capable algorithm to generate a DNSSEC key\&. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default\&.
+.RE
+.PP
+\-E \fIengine\fR
+.RS 4
+Specifies the cryptographic hardware to use\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.PP
+\-l \fIlabel\fR
+.RS 4
+Specifies the label for a key pair in the crypto hardware\&.
+.sp
+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:\fIkeylabel\fR"\&.
+.sp
+When
+BIND
+9 is built with native PKCS#11 support, the label is a PKCS#11 URI string in the format "pkcs11:\fBkeyword\fR=\fIvalue\fR[;\fBkeyword\fR=\fIvalue\fR;\&.\&.\&.]" Keywords include "token", which identifies the HSM; "object", which identifies the key; and "pin\-source", which identifies a file from which the HSM\*(Aqs PIN code can be obtained\&. The label will be stored in the on\-disk "private" file\&.
+.sp
+If the label contains a
+\fBpin\-source\fR
+field, tools using the generated key files will be able to use the HSM for signing and other operations without any need for an operator to manually enter a PIN\&. Note: Making the HSM\*(Aqs PIN accessible in this manner may reduce the security advantage of using an HSM; be sure this is what you want to do before making use of this feature\&.
+.RE
+.PP
+\-n \fInametype\fR
+.RS 4
+Specifies the owner type of the key\&. The value of
+\fBnametype\fR
+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\&.
+.RE
+.PP
+\-C
+.RS 4
+Compatibility mode: generates an old\-style key, without any metadata\&. By default,
+\fBdnssec\-keyfromlabel\fR
+will include the key\*(Aqs creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc)\&. Keys that include this data may be incompatible with older versions of BIND; the
+\fB\-C\fR
+option suppresses them\&.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Indicates that the DNS record containing the key should have the specified class\&. If not specified, class IN is used\&.
+.RE
+.PP
+\-f \fIflag\fR
+.RS 4
+Set the specified flag in the flag field of the KEY/DNSKEY record\&. The only recognized flags are KSK (Key Signing Key) and REVOKE\&.
+.RE
+.PP
+\-G
+.RS 4
+Generate a key, but do not publish it or sign with it\&. This option is incompatible with \-P and \-A\&.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-keyfromlabel\fR\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which the key files are to be written\&.
+.RE
+.PP
+\-k
+.RS 4
+Generate KEY records rather than DNSKEY records\&.
+.RE
+.PP
+\-L \fIttl\fR
+.RS 4
+Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, 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\&.
+.RE
+.PP
+\-p \fIprotocol\fR
+.RS 4
+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\&.
+.RE
+.PP
+\-S \fIkey\fR
+.RS 4
+Generate a key as an explicit successor to an existing key\&. The name, algorithm, size, and type of the key will be set to match the predecessor\&. The activation date of the new key will be set to the inactivation date of the existing one\&. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Indicates the use of the key\&.
+\fBtype\fR
+must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF\&. The default is AUTHCONF\&. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.PP
+\-y
+.RS 4
+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 use if you are sure you won\*(Aqt be using RFC 5011 trust anchor maintenance with either of the keys involved\&.)
+.RE
+.SH "TIMING OPTIONS"
+.PP
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset 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 \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&.
+.PP
+\-P \fIdate/offset\fR
+.RS 4
+Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&.
+.RE
+.PP
+\-P sync \fIdate/offset\fR
+.RS 4
+Sets the date on which the CDS and CDNSKEY records which match this key are to be published to the zone\&.
+.RE
+.PP
+\-A \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be activated\&. After that date, the key will be included in the zone and used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&.
+.RE
+.PP
+\-R \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&.
+.RE
+.PP
+\-I \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be retired\&. After that date, the key will still be included in the zone, but it will not be used to sign it\&.
+.RE
+.PP
+\-D \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.)
+.RE
+.PP
+\-D sync \fIdate/offset\fR
+.RS 4
+Sets the date on which the CDS and CDNSKEY records which match this key are to be deleted\&.
+.RE
+.PP
+\-i \fIinterval\fR
+.RS 4
+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 isn\*(Aqt, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn\*(Aqt, then activation will be set to this much time after publication\&.
+.sp
+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\&.
+.sp
+As with date offsets, if the argument is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the interval is measured in years, months, weeks, days, hours, or minutes, respectively\&. Without a suffix, the interval is measured in seconds\&.
+.RE
+.SH "GENERATED KEY FILES"
+.PP
+When
+\fBdnssec\-keyfromlabel\fR
+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\&.
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+nnnn
+is the key name\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+aaa
+is the numeric representation of the algorithm\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+iiiii
+is the key identifier (or footprint)\&.
+.RE
+.PP
+\fBdnssec\-keyfromlabel\fR
+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\&.
+.PP
+The
+\&.key
+file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement)\&.
+.PP
+The
+\&.private
+file contains algorithm\-specific fields\&. For obvious security reasons, this file does not have general read permission\&.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 4034,
+The PKCS#11 URI Scheme (draft\-pechanec\-pkcs11uri\-13)\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2008-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c
new file mode 100644
index 0000000..f65afd3
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.c
@@ -0,0 +1,756 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <pk11/site.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/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keyfromlabel";
+int verbose;
+
+#define DEFAULT_ALGORITHM "RSASHA1"
+#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1"
+
+static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |"
+ " NSEC3DSA | NSEC3RSASHA1 |"
+ " RSASHA256 | RSASHA512 | ECCGOST |"
+ " ECDSAP256SHA256 | ECDSAP384SHA384 |"
+ " ED25519 | ED448";
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -l label [options] name\n\n",
+ program);
+ fprintf(stderr, "Version: %s\n", 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: %s\n", algs);
+ fprintf(stderr, " (default: RSASHA1, or "
+ "NSEC3RSASHA1 if using -3)\n");
+ fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
+ fprintf(stderr, " -c class (default: IN)\n");
+ fprintf(stderr, " -E <engine>:\n");
+#if defined(PKCS11CRYPTO)
+ fprintf(stderr, " path to PKCS#11 provider library "
+ "(default is %s)\n", PK11_LIB_LOCATION);
+#elif defined(USE_PKCS11)
+ fprintf(stderr, " name of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+#else
+ fprintf(stderr, " name of an OpenSSL engine to use\n");
+#endif
+ 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;
+#ifdef USE_PKCS11
+ const char *engine = PKCS11_ENGINE;
+#else
+ const char *engine = NULL;
+#endif
+ 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;
+ isc_entropy_t *ectx = 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();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ ret = dst_lib_init2(mctx, ectx, engine,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ 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);
+ if (l == NULL)
+ fatal("cannot allocate memory");
+ snprintf(l, len, "pkcs11:%s", label);
+ isc_mem_free(mctx, label);
+ label = l;
+ }
+
+ if (algname == NULL) {
+ if (use_nsec3)
+ algname = strdup(DEFAULT_NSEC3_ALGORITHM);
+ else
+ algname = strdup(DEFAULT_ALGORITHM);
+ if (algname == NULL)
+ fatal("strdup failed");
+ freeit = algname;
+ if (verbose > 0)
+ fprintf(stderr, "no algorithm specified; "
+ "defaulting to %s\n", algname);
+ }
+
+ if (strcasecmp(algname, "RSA") == 0) {
+#ifndef PK11_MD5_DISABLE
+ fprintf(stderr, "The use of RSA (RSAMD5) is not "
+ "recommended.\nIf you still wish to "
+ "use RSA (RSAMD5) please specify "
+ "\"-a RSAMD5\"\n");
+#else
+ fprintf(stderr,
+ "The use of RSA (RSAMD5) was disabled\n");
+ if (freeit != NULL)
+ free(freeit);
+ return (1);
+ } else if (strcasecmp(algname, "RSAMD5") == 0) {
+ fprintf(stderr, "The use of RSAMD5 was disabled\n");
+#endif
+ if (freeit != NULL)
+ free(freeit);
+ return (1);
+ } else {
+ 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 &&
+ alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 &&
+ alg != DST_ALG_RSASHA256 && alg != DST_ALG_RSASHA512 &&
+ alg != DST_ALG_ECCGOST &&
+ alg != DST_ALG_ECDSA256 && alg != DST_ALG_ECDSA384 &&
+ alg != DST_ALG_ED25519 && alg != DST_ALG_ED448) {
+ 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);
+
+#ifdef PK11_MD5_DISABLE
+ if (alg == DST_ALG_RSAMD5)
+ fatal("Key %s uses disabled RSAMD5", predecessor);
+#endif
+
+ 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,
+#ifdef PKCS11CRYPTO
+ "pkcs11",
+#else
+ engine,
+#endif
+ label, NULL, mctx, &key);
+ isc_entropy_stopcallbacksources(ectx);
+
+ 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));
+ /* NOTREACHED */
+ 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);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ dns_name_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.docbook b/bin/dnssec/dnssec-keyfromlabel.docbook
new file mode 100644
index 0000000..4aaf474
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.docbook
@@ -0,0 +1,551 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-keyfromlabel">
+ <info>
+ <date>2014-02-27</date>
+ </info>
+ <refentryinfo>
+ <date>August 27, 2015</date>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keyfromlabel</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keyfromlabel</application></refname>
+ <refpurpose>DNSSEC key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-keyfromlabel</command>
+ <arg choice="req" rep="norepeat">-l <replaceable class="parameter">label</replaceable></arg>
+ <arg choice="opt" rep="norepeat"><option>-3</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-G</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S <replaceable class="parameter">key</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-y</option></arg>
+ <arg choice="req" rep="norepeat">name</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-keyfromlabel</command>
+ generates a key pair of files that referencing 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 <command>dnssec-keygen</command>,
+ but the key material is stored within the HSM, and the actual signing
+ takes place there.
+ </para>
+ <para>
+ The <option>name</option> of the key is specified on the command
+ line. This must match the name of the zone for which the key is
+ being generated.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Selects the cryptographic algorithm. The value of
+ <option>algorithm</option> must be one of RSAMD5, RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448.
+ These values are case insensitive.
+ </para>
+ <para>
+ If no algorithm is specified, then RSASHA1 will be used by
+ default, unless the <option>-3</option> option is specified,
+ in which case NSEC3RSASHA1 will be used instead. (If
+ <option>-3</option> is used and an algorithm is specified,
+ that algorithm will be checked for compatibility with NSEC3.)
+ </para>
+ <para>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </para>
+ <para>
+ Note 2: DH automatically sets the -k flag.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-3</term>
+ <listitem>
+ <para>
+ Use an NSEC3-capable algorithm to generate a DNSSEC key.
+ If this option is used and no algorithm is explicitly
+ set on the command line, NSEC3RSASHA1 will be used by
+ default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the cryptographic hardware to use.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">label</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the label for a key pair in the crypto hardware.
+ </para>
+ <para>
+ When <acronym>BIND</acronym> 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:<replaceable>keylabel</replaceable>".
+ </para>
+ <para>
+ When <acronym>BIND</acronym> 9 is built with native PKCS#11
+ support, the label is a PKCS#11 URI string in the format
+ "pkcs11:<option>keyword</option>=<replaceable>value</replaceable><optional>;<option>keyword</option>=<replaceable>value</replaceable>;...</optional>"
+ Keywords include "token", which identifies the HSM; "object", which
+ identifies the key; and "pin-source", which identifies a file from
+ which the HSM's PIN code can be obtained. The label will be
+ stored in the on-disk "private" file.
+ </para>
+ <para>
+ If the label contains a
+ <option>pin-source</option> field, tools using the generated
+ key files will be able to use the HSM for signing and other
+ operations without any need for an operator to manually enter
+ a PIN. Note: Making the HSM's PIN accessible in this manner
+ may reduce the security advantage of using an HSM; be sure
+ this is what you want to do before making use of this feature.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">nametype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the owner type of the key. The value of
+ <option>nametype</option> 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Compatibility mode: generates an old-style key, without
+ any metadata. By default, <command>dnssec-keyfromlabel</command>
+ will include the key's creation date in the metadata stored
+ with the private key, and other dates may be set there as well
+ (publication date, activation date, etc). Keys that include
+ this data may be incompatible with older versions of BIND; the
+ <option>-C</option> option suppresses them.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flags are KSK (Key Signing Key) and REVOKE.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-G</term>
+ <listitem>
+ <para>
+ Generate a key, but do not publish it or sign with it. This
+ option is incompatible with -P and -A.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-keyfromlabel</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to be written.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Generate KEY records rather than DNSKEY records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. Setting the default TTL to
+ <literal>0</literal> or <literal>none</literal> removes it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">key</replaceable></term>
+ <listitem>
+ <para>
+ Generate a key as an explicit successor to an existing key.
+ The name, algorithm, size, and type of the key will be set
+ to match the predecessor. The activation date of the new
+ key will be set to the inactivation date of the existing
+ one. The publication date will be set to the activation
+ date minus the prepublication interval, which defaults to
+ 30 days.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Indicates the use of the key. <option>type</option> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y</term>
+ <listitem>
+ <para>
+ 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 use if you
+ are sure you won't be using RFC 5011 trust anchor maintenance
+ with either of the keys involved.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>TIMING OPTIONS</title></info>
+
+
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it. If not set, and if the -G option has
+ not been used, the default is "now".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the CDS and CDNSKEY records which match
+ this key are to be published to the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included in the zone and used to sign
+ it. If not set, and if the -G option has not been used, the
+ default is "now".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be retired. After that
+ date, the key will still be included in the zone, but it
+ will not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the CDS and CDNSKEY records which match
+ this key are to be deleted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">interval</replaceable></term>
+ <listitem>
+ <para>
+ 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 isn't, then the publication date will default
+ to this much time before the activation date; conversely, if
+ the publication date is specified but activation date isn't,
+ then activation will be set to this much time after publication.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ As with date offsets, if the argument is followed by one of
+ the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
+ interval is measured in years, months, weeks, days, hours,
+ or minutes, respectively. Without a suffix, the interval is
+ measured in seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>GENERATED KEY FILES</title></info>
+
+ <para>
+ When <command>dnssec-keyfromlabel</command> completes
+ successfully,
+ it prints a string of the form <filename>Knnnn.+aaa+iiiii</filename>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><filename>nnnn</filename> is the key name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>aaa</filename> is the numeric representation
+ of the algorithm.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>iiiii</filename> is the key identifier (or
+ footprint).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para><command>dnssec-keyfromlabel</command>
+ creates two files, with names based
+ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
+ contains the public key, and
+ <filename>Knnnn.+aaa+iiiii.private</filename> contains the
+ private key.
+ </para>
+ <para>
+ The <filename>.key</filename> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </para>
+ <para>
+ The <filename>.private</filename> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 4034</citetitle>,
+ <citetitle>The PKCS#11 URI Scheme (draft-pechanec-pkcs11uri-13)</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-keyfromlabel.html b/bin/dnssec/dnssec-keyfromlabel.html
new file mode 100644
index 0000000..c96b658
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.html
@@ -0,0 +1,458 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2008-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keyfromlabel</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-keyfromlabel"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-keyfromlabel</span>
+ &#8212; DNSSEC key generation tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-keyfromlabel</code>
+ {-l <em class="replaceable"><code>label</code></em>}
+ [<code class="option">-3</code>]
+ [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>]
+ [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>]
+ [<code class="option">-G</code>]
+ [<code class="option">-I <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>]
+ [<code class="option">-k</code>]
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>]
+ [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-P sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>]
+ [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-S <em class="replaceable"><code>key</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-y</code>]
+ {name}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-keyfromlabel</strong></span>
+ generates a key pair of files that referencing 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 <span class="command"><strong>dnssec-keygen</strong></span>,
+ but the key material is stored within the HSM, and the actual signing
+ takes place there.
+ </p>
+ <p>
+ The <code class="option">name</code> of the key is specified on the command
+ line. This must match the name of the zone for which the key is
+ being generated.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+ <p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5, RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448.
+ These values are case insensitive.
+ </p>
+ <p>
+ If no algorithm is specified, then RSASHA1 will be used by
+ default, unless the <code class="option">-3</code> option is specified,
+ in which case NSEC3RSASHA1 will be used instead. (If
+ <code class="option">-3</code> is used and an algorithm is specified,
+ that algorithm will be checked for compatibility with NSEC3.)
+ </p>
+ <p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </p>
+ <p>
+ Note 2: DH automatically sets the -k flag.
+ </p>
+ </dd>
+<dt><span class="term">-3</span></dt>
+<dd>
+ <p>
+ Use an NSEC3-capable algorithm to generate a DNSSEC key.
+ If this option is used and no algorithm is explicitly
+ set on the command line, NSEC3RSASHA1 will be used by
+ default.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the cryptographic hardware to use.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the label for a key pair in the crypto hardware.
+ </p>
+ <p>
+ When <acronym class="acronym">BIND</acronym> 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:<em class="replaceable"><code>keylabel</code></em>".
+ </p>
+ <p>
+ When <acronym class="acronym">BIND</acronym> 9 is built with native PKCS#11
+ support, the label is a PKCS#11 URI string in the format
+ "pkcs11:<code class="option">keyword</code>=<em class="replaceable"><code>value</code></em>[<span class="optional">;<code class="option">keyword</code>=<em class="replaceable"><code>value</code></em>;...</span>]"
+ Keywords include "token", which identifies the HSM; "object", which
+ identifies the key; and "pin-source", which identifies a file from
+ which the HSM's PIN code can be obtained. The label will be
+ stored in the on-disk "private" file.
+ </p>
+ <p>
+ If the label contains a
+ <code class="option">pin-source</code> field, tools using the generated
+ key files will be able to use the HSM for signing and other
+ operations without any need for an operator to manually enter
+ a PIN. Note: Making the HSM's PIN accessible in this manner
+ may reduce the security advantage of using an HSM; be sure
+ this is what you want to do before making use of this feature.
+ </p>
+ </dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> 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.
+ </p>
+ </dd>
+<dt><span class="term">-C</span></dt>
+<dd>
+ <p>
+ Compatibility mode: generates an old-style key, without
+ any metadata. By default, <span class="command"><strong>dnssec-keyfromlabel</strong></span>
+ will include the key's creation date in the metadata stored
+ with the private key, and other dates may be set there as well
+ (publication date, activation date, etc). Keys that include
+ this data may be incompatible with older versions of BIND; the
+ <code class="option">-C</code> option suppresses them.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd>
+ <p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flags are KSK (Key Signing Key) and REVOKE.
+ </p>
+ </dd>
+<dt><span class="term">-G</span></dt>
+<dd>
+ <p>
+ Generate a key, but do not publish it or sign with it. This
+ option is incompatible with -P and -A.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Prints a short summary of the options and arguments to
+ <span class="command"><strong>dnssec-keyfromlabel</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which the key files are to be written.
+ </p>
+ </dd>
+<dt><span class="term">-k</span></dt>
+<dd>
+ <p>
+ Generate KEY records rather than DNSKEY records.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>ttl</code></em></span></dt>
+<dd>
+ <p>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. Setting the default TTL to
+ <code class="literal">0</code> or <code class="literal">none</code> removes it.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd>
+ <p>
+ 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.
+ </p>
+ </dd>
+<dt><span class="term">-S <em class="replaceable"><code>key</code></em></span></dt>
+<dd>
+ <p>
+ Generate a key as an explicit successor to an existing key.
+ The name, algorithm, size, and type of the key will be set
+ to match the predecessor. The activation date of the new
+ key will be set to the inactivation date of the existing
+ one. The publication date will be set to the activation
+ date minus the prepublication interval, which defaults to
+ 30 days.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+<dt><span class="term">-y</span></dt>
+<dd>
+ <p>
+ 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 use if you
+ are sure you won't be using RFC 5011 trust anchor maintenance
+ with either of the keys involved.)
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>TIMING OPTIONS</h2>
+
+
+ <p>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it. If not set, and if the -G option has
+ not been used, the default is "now".
+ </p>
+ </dd>
+<dt><span class="term">-P sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the CDS and CDNSKEY records which match
+ this key are to be published to the zone.
+ </p>
+ </dd>
+<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included in the zone and used to sign
+ it. If not set, and if the -G option has not been used, the
+ default is "now".
+ </p>
+ </dd>
+<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-I <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be retired. After that
+ date, the key will still be included in the zone, but it
+ will not be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </p>
+ </dd>
+<dt><span class="term">-D sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the CDS and CDNSKEY records which match
+ this key are to be deleted.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+ <p>
+ 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 isn't, then the publication date will default
+ to this much time before the activation date; conversely, if
+ the publication date is specified but activation date isn't,
+ then activation will be set to this much time after publication.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ As with date offsets, if the argument is followed by one of
+ the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
+ interval is measured in years, months, weeks, days, hours,
+ or minutes, respectively. Without a suffix, the interval is
+ measured in seconds.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>GENERATED KEY FILES</h2>
+
+ <p>
+ When <span class="command"><strong>dnssec-keyfromlabel</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </p>
+ <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ <p><code class="filename">nnnn</code> is the key name.
+ </p>
+ </li>
+<li class="listitem">
+ <p><code class="filename">aaa</code> is the numeric representation
+ of the algorithm.
+ </p>
+ </li>
+<li class="listitem">
+ <p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p>
+ </li>
+</ul></div>
+ <p><span class="command"><strong>dnssec-keyfromlabel</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private key.
+ </p>
+ <p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+ <p>
+ The <code class="filename">.private</code> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 4034</em>,
+ <em class="citetitle">The PKCS#11 URI Scheme (draft-pechanec-pkcs11uri-13)</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-keygen.8 b/bin/dnssec/dnssec-keygen.8
new file mode 100644
index 0000000..6f8eedb
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.8
@@ -0,0 +1,354 @@
+.\" Copyright (C) 2000-2005, 2007-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-keygen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: August 21, 2015
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-KEYGEN" "8" "August 21, 2015" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-keygen \- DNSSEC key generation tool
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-keygen\fR\ 'u
+\fBdnssec\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-3\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-C\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-q\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-V\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] {name}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-keygen\fR
+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\&.
+.PP
+The
+\fBname\fR
+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\&.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Selects the cryptographic algorithm\&. For DNSSEC keys, the value of
+\fBalgorithm\fR
+must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448\&. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC\-MD5, HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256, HMAC\-SHA384, or HMAC\-SHA512\&. These values are case insensitive\&.
+.sp
+If no algorithm is specified, then RSASHA1 will be used by default, unless the
+\fB\-3\fR
+option is specified, in which case NSEC3RSASHA1 will be used instead\&. (If
+\fB\-3\fR
+is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3\&.)
+.sp
+Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended\&. For TSIG, HMAC\-MD5 is mandatory\&.
+.sp
+Note 2: DH, HMAC\-MD5, and HMAC\-SHA1 through HMAC\-SHA512 automatically set the \-T KEY option\&.
+.RE
+.PP
+\-b \fIkeysize\fR
+.RS 4
+Specifies the number of bits in the key\&. The choice of key size depends on the algorithm used\&. RSA keys must be between 512 and 2048 bits\&. Diffie Hellman keys must be between 128 and 4096 bits\&. DSA keys must be between 512 and 1024 bits and an exact multiple of 64\&. HMAC keys must be between 1 and 512 bits\&. Elliptic curve algorithms don\*(Aqt need this parameter\&.
+.sp
+The key size does not need to be specified if using a default algorithm\&. The default key size is 1024 bits for zone signing keys (ZSKs) and 2048 bits for key signing keys (KSKs, generated with
+\fB\-f KSK\fR)\&. However, if an algorithm is explicitly specified with the
+\fB\-a\fR, then there is no default key size, and the
+\fB\-b\fR
+must be used\&.
+.RE
+.PP
+\-n \fInametype\fR
+.RS 4
+Specifies the owner type of the key\&. The value of
+\fBnametype\fR
+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\&. Defaults to ZONE for DNSKEY generation\&.
+.RE
+.PP
+\-3
+.RS 4
+Use an NSEC3\-capable algorithm to generate a DNSSEC key\&. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default\&. Note that RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 and ED448 algorithms are NSEC3\-capable\&.
+.RE
+.PP
+\-C
+.RS 4
+Compatibility mode: generates an old\-style key, without any metadata\&. By default,
+\fBdnssec\-keygen\fR
+will include the key\*(Aqs creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc)\&. Keys that include this data may be incompatible with older versions of BIND; the
+\fB\-C\fR
+option suppresses them\&.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Indicates that the DNS record containing the key should have the specified class\&. If not specified, class IN is used\&.
+.RE
+.PP
+\-E \fIengine\fR
+.RS 4
+Specifies the cryptographic hardware to use, when applicable\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.PP
+\-f \fIflag\fR
+.RS 4
+Set the specified flag in the flag field of the KEY/DNSKEY record\&. The only recognized flags are KSK (Key Signing Key) and REVOKE\&.
+.RE
+.PP
+\-G
+.RS 4
+Generate a key, but do not publish it or sign with it\&. This option is incompatible with \-P and \-A\&.
+.RE
+.PP
+\-g \fIgenerator\fR
+.RS 4
+If generating a Diffie Hellman key, use this generator\&. Allowed values are 2 and 5\&. If no generator is specified, a known prime from RFC 2539 will be used if possible; otherwise the default is 2\&.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-keygen\fR\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which the key files are to be written\&.
+.RE
+.PP
+\-k
+.RS 4
+Deprecated in favor of \-T KEY\&.
+.RE
+.PP
+\-L \fIttl\fR
+.RS 4
+Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL\&. Setting the default TTL to
+0
+or
+none
+is the same as leaving it unset\&.
+.RE
+.PP
+\-p \fIprotocol\fR
+.RS 4
+Sets the protocol value for the generated 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\&.
+.RE
+.PP
+\-q
+.RS 4
+Quiet mode: Suppresses unnecessary output, including progress indication\&. Without this option, when
+\fBdnssec\-keygen\fR
+is run interactively to generate an RSA or DSA key pair, it will print a string of symbols to
+stderr
+indicating the progress of the key generation\&. A \*(Aq\&.\*(Aq indicates that a random number has been found which passed an initial sieve test; \*(Aq+\*(Aq means a number has passed a single round of the Miller\-Rabin primality test; a space means that the number has passed all the tests and is a satisfactory key\&.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies the source of randomness\&. If the operating system does not provide a
+/dev/random
+or equivalent device, the default source of randomness is keyboard input\&.
+randomdev
+specifies the name of a character device or file containing random data to be used instead of the default\&. The special value
+keyboard
+indicates that keyboard input should be used\&.
+.RE
+.PP
+\-S \fIkey\fR
+.RS 4
+Create a new key which is an explicit successor to an existing key\&. The name, algorithm, size, and type of the key will be set to match the existing key\&. The activation date of the new key will be set to the inactivation date of the existing one\&. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days\&.
+.RE
+.PP
+\-s \fIstrength\fR
+.RS 4
+Specifies the strength value of the key\&. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC\&.
+.RE
+.PP
+\-T \fIrrtype\fR
+.RS 4
+Specifies the resource record type to use for the key\&.
+\fBrrtype\fR
+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)\&.
+Using any TSIG algorithm (HMAC\-* or DH) forces this option to KEY\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Indicates the use of the key\&.
+\fBtype\fR
+must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF\&. The default is AUTHCONF\&. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.SH "TIMING OPTIONS"
+.PP
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset 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 \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&.
+.PP
+\-P \fIdate/offset\fR
+.RS 4
+Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&.
+.RE
+.PP
+\-P sync \fIdate/offset\fR
+.RS 4
+Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone\&.
+.RE
+.PP
+\-A \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be activated\&. After that date, the key will be included in the zone and used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&. If set, if and \-P is not set, then the publication date will be set to the activation date minus the prepublication interval\&.
+.RE
+.PP
+\-R \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&.
+.RE
+.PP
+\-I \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be retired\&. After that date, the key will still be included in the zone, but it will not be used to sign it\&.
+.RE
+.PP
+\-D \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.)
+.RE
+.PP
+\-D sync \fIdate/offset\fR
+.RS 4
+Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted\&.
+.RE
+.PP
+\-i \fIinterval\fR
+.RS 4
+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 isn\*(Aqt, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn\*(Aqt, then activation will be set to this much time after publication\&.
+.sp
+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\&.
+.sp
+As with date offsets, if the argument is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the interval is measured in years, months, weeks, days, hours, or minutes, respectively\&. Without a suffix, the interval is measured in seconds\&.
+.RE
+.SH "GENERATED KEYS"
+.PP
+When
+\fBdnssec\-keygen\fR
+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\&.
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+nnnn
+is the key name\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+aaa
+is the numeric representation of the algorithm\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+iiiii
+is the key identifier (or footprint)\&.
+.RE
+.PP
+\fBdnssec\-keygen\fR
+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\&.
+.PP
+The
+\&.key
+file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement)\&.
+.PP
+The
+\&.private
+file contains algorithm\-specific fields\&. For obvious security reasons, this file does not have general read permission\&.
+.PP
+Both
+\&.key
+and
+\&.private
+files are generated for symmetric cryptography algorithms such as HMAC\-MD5, even though the public and private key are equivalent\&.
+.SH "EXAMPLE"
+.PP
+To generate a 768\-bit DSA key for the domain
+\fBexample\&.com\fR, the following command would be issued:
+.PP
+\fBdnssec\-keygen \-a DSA \-b 768 \-n ZONE example\&.com\fR
+.PP
+The command would print a string of the form:
+.PP
+\fBKexample\&.com\&.+003+26160\fR
+.PP
+In this example,
+\fBdnssec\-keygen\fR
+creates the files
+Kexample\&.com\&.+003+26160\&.key
+and
+Kexample\&.com\&.+003+26160\&.private\&.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 2539,
+RFC 2845,
+RFC 4034\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2005, 2007-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c
new file mode 100644
index 0000000..1476d0d
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.c
@@ -0,0 +1,1126 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * 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 <config.h>
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <pk11/site.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/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keygen";
+int verbose;
+
+#define DEFAULT_ALGORITHM "RSASHA1"
+#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1"
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void progress(int p);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] name\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, " name: owner of the key\n");
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -K <directory>: write keys into directory\n");
+ fprintf(stderr, " -a <algorithm>:\n");
+ fprintf(stderr, " RSA | RSAMD5 | DSA | RSASHA1 | NSEC3RSASHA1"
+ " | NSEC3DSA |\n");
+ fprintf(stderr, " RSASHA256 | RSASHA512 | ECCGOST |\n");
+ fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
+ fprintf(stderr, " ED25519 | ED448 | DH |\n");
+ fprintf(stderr, " HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | "
+ "HMAC-SHA256 | \n");
+ fprintf(stderr, " HMAC-SHA384 | HMAC-SHA512\n");
+ fprintf(stderr, " (default: RSASHA1, or "
+ "NSEC3RSASHA1 if using -3)\n");
+ fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
+ fprintf(stderr, " -b <key size in bits>:\n");
+ fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
+ fprintf(stderr, " DH:\t\t[128..4096]\n");
+ fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
+ fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible "
+ "by 64\n");
+ fprintf(stderr, " ECCGOST:\tignored\n");
+ fprintf(stderr, " ECDSAP256SHA256:\tignored\n");
+ fprintf(stderr, " ECDSAP384SHA384:\tignored\n");
+ fprintf(stderr, " ED25519:\tignored\n");
+ fprintf(stderr, " ED448:\tignored\n");
+ fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
+ fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
+ fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
+ fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
+ fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
+ fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
+ fprintf(stderr, " (if using the default algorithm, key size\n"
+ " defaults to 2048 for KSK, or 1024 for all "
+ "others)\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");
+#if defined(PKCS11CRYPTO)
+ fprintf(stderr, " path to PKCS#11 provider library "
+ "(default is %s)\n", PK11_LIB_LOCATION);
+#elif defined(USE_PKCS11)
+ fprintf(stderr, " name of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+#else
+ fprintf(stderr, " name of an OpenSSL engine to use\n");
+#endif
+ 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, " -r <randomdev>: a file containing random data\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 bool
+dsa_size_ok(int size) {
+ return (size >= 512 && size <= 1024 && size % 64 == 0);
+}
+
+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);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *freeit = NULL;
+ char *nametype = NULL, *type = 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 conflict = false, null_key = false;
+ bool oldstyle = false;
+ isc_mem_t *mctx = NULL;
+ int ch, generator = 0, param = 0;
+ int protocol = -1, size = -1, signatory = 0;
+ isc_result_t ret;
+ isc_textregion_t r;
+ char filename[255];
+ const char *directory = NULL;
+ const char *predecessor = NULL;
+ dst_key_t *prevkey = NULL;
+ isc_buffer_t buf;
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+#ifdef USE_PKCS11
+ const char *engine = PKCS11_ENGINE;
+#else
+ const char *engine = NULL;
+#endif
+ dns_rdataclass_t rdclass;
+ int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
+ int dbits = 0;
+ dns_ttl_t ttl = 0;
+ bool use_default = false, use_nsec3 = false;
+ isc_stdtime_t publish = 0, activate = 0, revokekey = 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 quiet = false;
+ bool show_progress = false;
+ unsigned char c;
+ isc_stdtime_t syncadd = 0, syncdel = 0;
+ bool setsyncadd = false;
+ bool setsyncdel = false;
+
+ if (argc == 1)
+ usage();
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ isc_commandline_errprint = false;
+
+ /*
+ * Process memory debugging argument first.
+ */
+#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:kL: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;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ isc_stdtime_get(&now);
+
+ 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 'b':
+ size = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || size < 0)
+ fatal("-b requires a non-negative number");
+ break;
+ case 'C':
+ oldstyle = true;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ dbits = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || 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')
+ kskflag = DNS_KEYFLAG_KSK;
+ else if (toupper(c) == 'R')
+ revflag = DNS_KEYFLAG_REVOKE;
+ else
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ break;
+ case 'g':
+ generator = strtol(isc_commandline_argument,
+ &endp, 10);
+ if (*endp != '\0' || generator <= 0)
+ fatal("-g requires a positive number");
+ 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':
+ fatal("The -k option has been deprecated.\n"
+ "To generate a key-signing key, use -f KSK.\n"
+ "To generate a key with TYPE=KEY, use -T KEY.\n");
+ break;
+ case 'L':
+ ttl = strtottl(isc_commandline_argument);
+ setttl = true;
+ break;
+ case 'n':
+ nametype = isc_commandline_argument;
+ break;
+ case 'm':
+ 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 'q':
+ quiet = true;
+ break;
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ break;
+ case 's':
+ signatory = strtol(isc_commandline_argument,
+ &endp, 10);
+ if (*endp != '\0' || signatory < 0 || signatory > 15)
+ fatal("-s must be followed by a number "
+ "[0..15]");
+ break;
+ case 'T':
+ if (strcasecmp(isc_commandline_argument, "KEY") == 0)
+ options |= DST_TYPE_KEY;
+ else if (strcasecmp(isc_commandline_argument,
+ "DNSKEY") == 0)
+ /* default behavior */
+ ;
+ else
+ fatal("unknown type '%s'",
+ isc_commandline_argument);
+ break;
+ case 't':
+ 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 'z':
+ /* already the default */
+ break;
+ case 'G':
+ genonly = 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;
+ }
+ (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");
+
+ revokekey = 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 (setsyncdel)
+ fatal("-D sync specified more than "
+ "once");
+
+ syncdel = strtotime(isc_commandline_argument,
+ now, now, &setsyncdel);
+ break;
+ }
+ (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);
+ }
+ }
+
+ if (!isatty(0))
+ quiet = true;
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ ret = dst_lib_init2(mctx, ectx, engine,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (ret != ISC_R_SUCCESS)
+ fatal("could not initialize dst: %s",
+ isc_result_totext(ret));
+
+ setup_logging(mctx, &log);
+
+ if (predecessor == NULL) {
+ if (prepub == -1)
+ prepub = 0;
+
+ 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 (algname == NULL) {
+ use_default = true;
+ if (use_nsec3)
+ algname = strdup(DEFAULT_NSEC3_ALGORITHM);
+ else
+ algname = strdup(DEFAULT_ALGORITHM);
+ if (algname == NULL)
+ fatal("strdup failed");
+ freeit = algname;
+ if (verbose > 0)
+ fprintf(stderr, "no algorithm specified; "
+ "defaulting to %s\n", algname);
+ }
+
+ if (strcasecmp(algname, "RSA") == 0) {
+#ifndef PK11_MD5_DISABLE
+ fprintf(stderr, "The use of RSA (RSAMD5) is not "
+ "recommended.\nIf you still wish to "
+ "use RSA (RSAMD5) please specify "
+ "\"-a RSAMD5\"\n");
+ INSIST(freeit == NULL);
+ return (1);
+ } else if (strcasecmp(algname, "HMAC-MD5") == 0) {
+ alg = DST_ALG_HMACMD5;
+#else
+ fprintf(stderr,
+ "The use of RSA (RSAMD5) was disabled\n");
+ INSIST(freeit == NULL);
+ return (1);
+ } else if (strcasecmp(algname, "RSAMD5") == 0) {
+ fprintf(stderr, "The use of RSAMD5 was disabled\n");
+ INSIST(freeit == NULL);
+ return (1);
+ } else if (strcasecmp(algname, "HMAC-MD5") == 0) {
+ fprintf(stderr,
+ "The use of HMAC-MD5 was disabled\n");
+ return (1);
+#endif
+ } else if (strcasecmp(algname, "HMAC-SHA1") == 0)
+ alg = DST_ALG_HMACSHA1;
+ else if (strcasecmp(algname, "HMAC-SHA224") == 0)
+ alg = DST_ALG_HMACSHA224;
+ else if (strcasecmp(algname, "HMAC-SHA256") == 0)
+ alg = DST_ALG_HMACSHA256;
+ else if (strcasecmp(algname, "HMAC-SHA384") == 0)
+ alg = DST_ALG_HMACSHA384;
+ else if (strcasecmp(algname, "HMAC-SHA512") == 0)
+ alg = DST_ALG_HMACSHA512;
+ else {
+ 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;
+ }
+
+#ifdef PK11_MD5_DISABLE
+ INSIST((alg != DNS_KEYALG_RSAMD5) && (alg != DST_ALG_HMACMD5));
+#endif
+
+ if (!dst_algorithm_supported(alg))
+ fatal("unsupported algorithm: %d", alg);
+
+ if (use_nsec3 &&
+ alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 &&
+ alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512 &&
+ alg != DST_ALG_ECCGOST &&
+ alg != DST_ALG_ECDSA256 && alg != DST_ALG_ECDSA384 &&
+ alg != DST_ALG_ED25519 && alg != DST_ALG_ED448) {
+ 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);
+ if (size < 0)
+ size = 0;
+ }
+ else if (strcasecmp(type, "AUTHCONF") == 0)
+ /* nothing */;
+ else
+ fatal("invalid type %s", type);
+ }
+
+ if (size < 0) {
+ if (use_default) {
+ if ((kskflag & DNS_KEYFLAG_KSK) != 0)
+ size = 2048;
+ else
+ size = 1024;
+ if (verbose > 0)
+ fprintf(stderr, "key size not "
+ "specified; defaulting"
+ " to %d\n", size);
+ } else if (alg != DST_ALG_ECCGOST &&
+ alg != DST_ALG_ECDSA256 &&
+ alg != DST_ALG_ECDSA384 &&
+ alg != DST_ALG_ED25519 &&
+ alg != DST_ALG_ED448)
+ fatal("key size not specified (-b option)");
+ }
+
+ 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 (size >= 0)
+ fatal("-S and -b 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);
+ 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, &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;
+ }
+
+ switch (alg) {
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_NSEC3RSASHA1:
+ case DNS_KEYALG_RSASHA256:
+ if (size != 0 && (size < 512 || size > MAX_RSA))
+ fatal("RSA key size %d out of range", size);
+ break;
+ case DNS_KEYALG_RSASHA512:
+ if (size != 0 && (size < 1024 || size > MAX_RSA))
+ fatal("RSA key size %d out of range", size);
+ break;
+ case DNS_KEYALG_DH:
+ if (size != 0 && (size < 128 || size > 4096))
+ fatal("DH key size %d out of range", size);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_NSEC3DSA:
+ if (size != 0 && !dsa_size_ok(size))
+ fatal("invalid DSS key size: %d", size);
+ break;
+ case DST_ALG_ECCGOST:
+ size = 256;
+ break;
+ case DST_ALG_ECDSA256:
+ size = 256;
+ break;
+ case DST_ALG_ECDSA384:
+ size = 384;
+ break;
+ case DST_ALG_ED25519:
+ size = 256;
+ break;
+ case DST_ALG_ED448:
+ size = 456;
+ break;
+ case DST_ALG_HMACMD5:
+ options |= DST_TYPE_KEY;
+ if (size < 1 || size > 512)
+ fatal("HMAC-MD5 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 80 || dbits > 128))
+ fatal("HMAC-MD5 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-MD5 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA1:
+ options |= DST_TYPE_KEY;
+ if (size < 1 || size > 160)
+ fatal("HMAC-SHA1 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 80 || dbits > 160))
+ fatal("HMAC-SHA1 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA1 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA224:
+ options |= DST_TYPE_KEY;
+ if (size < 1 || size > 224)
+ fatal("HMAC-SHA224 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 112 || dbits > 224))
+ fatal("HMAC-SHA224 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA224 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA256:
+ options |= DST_TYPE_KEY;
+ if (size < 1 || size > 256)
+ fatal("HMAC-SHA256 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 128 || dbits > 256))
+ fatal("HMAC-SHA256 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA256 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA384:
+ options |= DST_TYPE_KEY;
+ if (size < 1 || size > 384)
+ fatal("HMAC-384 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 192 || dbits > 384))
+ fatal("HMAC-SHA384 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA384 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA512:
+ options |= DST_TYPE_KEY;
+ if (size < 1 || size > 512)
+ fatal("HMAC-SHA512 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 256 || dbits > 512))
+ fatal("HMAC-SHA512 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA512 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ }
+
+ if (alg != DNS_KEYALG_DH && generator != 0)
+ fatal("specified DH generator for a non-DH key");
+
+ if (nametype == NULL) {
+ if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */
+ 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 / HMAC */
+ 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 / HMAC */
+ 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 (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 &&
+ (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 ||
+ alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 ||
+ alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 ||
+ alg == DST_ALG_HMACSHA512))
+ fatal("a key with algorithm '%s' cannot be a zone key",
+ algname);
+
+ switch(alg) {
+ case DNS_KEYALG_RSAMD5:
+ 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 = generator;
+ break;
+
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_NSEC3DSA:
+ case DST_ALG_ECCGOST:
+ case DST_ALG_ECDSA256:
+ case DST_ALG_ECDSA384:
+ case DST_ALG_ED25519:
+ case DST_ALG_ED448:
+ show_progress = true;
+ /* fall through */
+
+ case DST_ALG_HMACMD5:
+ case DST_ALG_HMACSHA1:
+ case DST_ALG_HMACSHA224:
+ case DST_ALG_HMACSHA256:
+ case DST_ALG_HMACSHA384:
+ case DST_ALG_HMACSHA512:
+ param = 0;
+ break;
+ }
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
+ null_key = true;
+
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+
+ do {
+ conflict = false;
+
+ if (!quiet && show_progress) {
+ fprintf(stderr, "Generating key pair.");
+ ret = dst_key_generate2(name, alg, size, param, flags,
+ protocol, rdclass, mctx, &key,
+ &progress);
+ putc('\n', stderr);
+ fflush(stderr);
+ } else {
+ ret = dst_key_generate2(name, alg, size, param, flags,
+ protocol, rdclass, mctx, &key,
+ NULL);
+ }
+
+ isc_entropy_stopcallbacksources(ectx);
+
+ 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 generate key %s/%s: %s\n",
+ namestr, algstr, isc_result_totext(ret));
+ /* NOTREACHED */
+ exit(-1);
+ }
+
+ dst_key_setbits(key, 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 (!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 && !unsetpub)
+ dst_key_settime(key, DST_TIME_PUBLISH,
+ activate - prepub);
+ 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, revokekey);
+ }
+
+ if (setinact)
+ dst_key_settime(key, DST_TIME_INACTIVE,
+ inactive);
+
+ if (setdel) {
+ if (setinact && deltime < 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, 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 the default key TTL */
+ if (setttl)
+ dst_key_setttl(key, ttl);
+
+ /*
+ * 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, 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,
+ 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 == true);
+
+ if (conflict)
+ fatal("cannot generate a null key due to possible key ID "
+ "collision");
+
+ 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);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ dns_name_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.docbook b/bin/dnssec/dnssec-keygen.docbook
new file mode 100644
index 0000000..ee6a489
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.docbook
@@ -0,0 +1,654 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-keygen">
+ <info>
+ <date>2014-02-06</date>
+ </info>
+ <refentryinfo>
+ <date>August 21, 2015</date>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keygen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keygen</application></refname>
+ <refpurpose>DNSSEC key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-keygen</command>
+ <arg choice="opt" rep="norepeat"><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">keysize</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-3</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-C</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-G</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-g <replaceable class="parameter">generator</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S <replaceable class="parameter">key</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">strength</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-z</option></arg>
+ <arg choice="req" rep="norepeat">name</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-keygen</command>
+ 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.
+ </para>
+ <para>
+ The <option>name</option> 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.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Selects the cryptographic algorithm. For DNSSEC keys, the value
+ of <option>algorithm</option> must be one of RSAMD5, RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448.
+ For TSIG/TKEY, the value must
+ be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224,
+ HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are
+ case insensitive.
+ </para>
+ <para>
+ If no algorithm is specified, then RSASHA1 will be used by
+ default, unless the <option>-3</option> option is specified,
+ in which case NSEC3RSASHA1 will be used instead. (If
+ <option>-3</option> is used and an algorithm is specified,
+ that algorithm will be checked for compatibility with NSEC3.)
+ </para>
+ <para>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </para>
+ <para>
+ Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512
+ automatically set the -T KEY option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSA keys must be
+ between 512 and 2048 bits. Diffie Hellman keys must be between
+ 128 and 4096 bits. DSA keys must be between 512 and 1024
+ bits and an exact multiple of 64. HMAC keys must be
+ between 1 and 512 bits. Elliptic curve algorithms don't need
+ this parameter.
+ </para>
+ <para>
+ The key size does not need to be specified if using a default
+ algorithm. The default key size is 1024 bits for zone signing
+ keys (ZSKs) and 2048 bits for key signing keys (KSKs,
+ generated with <option>-f KSK</option>). However, if an
+ algorithm is explicitly specified with the <option>-a</option>,
+ then there is no default key size, and the <option>-b</option>
+ must be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">nametype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the owner type of the key. The value of
+ <option>nametype</option> 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. Defaults to ZONE for DNSKEY
+ generation.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-3</term>
+ <listitem>
+ <para>
+ Use an NSEC3-capable algorithm to generate a DNSSEC key.
+ If this option is used and no algorithm is explicitly
+ set on the command line, NSEC3RSASHA1 will be used by
+ default. Note that RSASHA256, RSASHA512, ECCGOST,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519 and ED448
+ algorithms are NSEC3-capable.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Compatibility mode: generates an old-style key, without
+ any metadata. By default, <command>dnssec-keygen</command>
+ will include the key's creation date in the metadata stored
+ with the private key, and other dates may be set there as well
+ (publication date, activation date, etc). Keys that include
+ this data may be incompatible with older versions of BIND; the
+ <option>-C</option> option suppresses them.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the cryptographic hardware to use, when applicable.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flags are KSK (Key Signing Key) and REVOKE.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-G</term>
+ <listitem>
+ <para>
+ Generate a key, but do not publish it or sign with it. This
+ option is incompatible with -P and -A.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g <replaceable class="parameter">generator</replaceable></term>
+ <listitem>
+ <para>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to be written.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Deprecated in favor of -T KEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. If this value is not set and there
+ is no existing DNSKEY RRset, the TTL will default to the
+ SOA TTL. Setting the default TTL to <literal>0</literal>
+ or <literal>none</literal> is the same as leaving it unset.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ Sets the protocol value for the generated 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ Quiet mode: Suppresses unnecessary output, including
+ progress indication. Without this option, when
+ <command>dnssec-keygen</command> is run interactively
+ to generate an RSA or DSA key pair, it will print a string
+ of symbols to <filename>stderr</filename> 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; a space
+ means that the number has passed all the tests and is
+ a satisfactory key.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the source of randomness. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">key</replaceable></term>
+ <listitem>
+ <para>
+ Create a new key which is an explicit successor to an
+ existing key. The name, algorithm, size, and type of the
+ key will be set to match the existing key. The activation
+ date of the new key will be set to the inactivation date of
+ the existing one. The publication date will be set to the
+ activation date minus the prepublication interval, which
+ defaults to 30 days.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">strength</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T <replaceable class="parameter">rrtype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the resource record type to use for the key.
+ <option>rrtype</option> 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).
+ <para>
+ </para>
+ Using any TSIG algorithm (HMAC-* or DH) forces this option
+ to KEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Indicates the use of the key. <option>type</option> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>TIMING OPTIONS</title></info>
+
+
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it. If not set, and if the -G option has
+ not been used, the default is "now".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which CDS and CDNSKEY records that match this
+ key are to be published to the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included in the zone and used to sign
+ it. If not set, and if the -G option has not been used, the
+ default is "now". If set, if and -P is not set, then
+ the publication date will be set to the activation date
+ minus the prepublication interval.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be retired. After that
+ date, the key will still be included in the zone, but it
+ will not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">interval</replaceable></term>
+ <listitem>
+ <para>
+ 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 isn't, then the publication date will default
+ to this much time before the activation date; conversely, if
+ the publication date is specified but activation date isn't,
+ then activation will be set to this much time after publication.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ As with date offsets, if the argument is followed by one of
+ the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
+ interval is measured in years, months, weeks, days, hours,
+ or minutes, respectively. Without a suffix, the interval is
+ measured in seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+
+ <refsection><info><title>GENERATED KEYS</title></info>
+
+ <para>
+ When <command>dnssec-keygen</command> completes
+ successfully,
+ it prints a string of the form <filename>Knnnn.+aaa+iiiii</filename>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><filename>nnnn</filename> is the key name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>aaa</filename> is the numeric representation
+ of the
+ algorithm.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>iiiii</filename> is the key identifier (or
+ footprint).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para><command>dnssec-keygen</command>
+ creates two files, with names based
+ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
+ contains the public key, and
+ <filename>Knnnn.+aaa+iiiii.private</filename> contains the
+ private
+ key.
+ </para>
+ <para>
+ The <filename>.key</filename> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </para>
+ <para>
+ The <filename>.private</filename> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </para>
+ <para>
+ Both <filename>.key</filename> and <filename>.private</filename>
+ files are generated for symmetric cryptography algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </para>
+ </refsection>
+
+ <refsection><info><title>EXAMPLE</title></info>
+
+ <para>
+ To generate a 768-bit DSA key for the domain
+ <userinput>example.com</userinput>, the following command would be
+ issued:
+ </para>
+ <para><userinput>dnssec-keygen -a DSA -b 768 -n ZONE example.com</userinput>
+ </para>
+ <para>
+ The command would print a string of the form:
+ </para>
+ <para><userinput>Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ In this example, <command>dnssec-keygen</command> creates
+ the files <filename>Kexample.com.+003+26160.key</filename>
+ and
+ <filename>Kexample.com.+003+26160.private</filename>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2539</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 4034</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-keygen.html b/bin/dnssec/dnssec-keygen.html
new file mode 100644
index 0000000..4cdeca6
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.html
@@ -0,0 +1,545 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2005, 2007-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keygen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-keygen"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-keygen</span>
+ &#8212; DNSSEC key generation tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-keygen</code>
+ [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>]
+ [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>]
+ [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>]
+ [<code class="option">-3</code>]
+ [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-C</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>]
+ [<code class="option">-G</code>]
+ [<code class="option">-g <em class="replaceable"><code>generator</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-I <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>]
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-k</code>]
+ [<code class="option">-L <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-P sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>]
+ [<code class="option">-S <em class="replaceable"><code>key</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>strength</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-z</code>]
+ {name}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-keygen</strong></span>
+ 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.
+ </p>
+ <p>
+ The <code class="option">name</code> 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.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+ <p>
+ Selects the cryptographic algorithm. For DNSSEC keys, the value
+ of <code class="option">algorithm</code> must be one of RSAMD5, RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448.
+ For TSIG/TKEY, the value must
+ be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224,
+ HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are
+ case insensitive.
+ </p>
+ <p>
+ If no algorithm is specified, then RSASHA1 will be used by
+ default, unless the <code class="option">-3</code> option is specified,
+ in which case NSEC3RSASHA1 will be used instead. (If
+ <code class="option">-3</code> is used and an algorithm is specified,
+ that algorithm will be checked for compatibility with NSEC3.)
+ </p>
+ <p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </p>
+ <p>
+ Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512
+ automatically set the -T KEY option.
+ </p>
+ </dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSA keys must be
+ between 512 and 2048 bits. Diffie Hellman keys must be between
+ 128 and 4096 bits. DSA keys must be between 512 and 1024
+ bits and an exact multiple of 64. HMAC keys must be
+ between 1 and 512 bits. Elliptic curve algorithms don't need
+ this parameter.
+ </p>
+ <p>
+ The key size does not need to be specified if using a default
+ algorithm. The default key size is 1024 bits for zone signing
+ keys (ZSKs) and 2048 bits for key signing keys (KSKs,
+ generated with <code class="option">-f KSK</code>). However, if an
+ algorithm is explicitly specified with the <code class="option">-a</code>,
+ then there is no default key size, and the <code class="option">-b</code>
+ must be used.
+ </p>
+ </dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> 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. Defaults to ZONE for DNSKEY
+ generation.
+ </p>
+ </dd>
+<dt><span class="term">-3</span></dt>
+<dd>
+ <p>
+ Use an NSEC3-capable algorithm to generate a DNSSEC key.
+ If this option is used and no algorithm is explicitly
+ set on the command line, NSEC3RSASHA1 will be used by
+ default. Note that RSASHA256, RSASHA512, ECCGOST,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519 and ED448
+ algorithms are NSEC3-capable.
+ </p>
+ </dd>
+<dt><span class="term">-C</span></dt>
+<dd>
+ <p>
+ Compatibility mode: generates an old-style key, without
+ any metadata. By default, <span class="command"><strong>dnssec-keygen</strong></span>
+ will include the key's creation date in the metadata stored
+ with the private key, and other dates may be set there as well
+ (publication date, activation date, etc). Keys that include
+ this data may be incompatible with older versions of BIND; the
+ <code class="option">-C</code> option suppresses them.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the cryptographic hardware to use, when applicable.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd>
+ <p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flags are KSK (Key Signing Key) and REVOKE.
+ </p>
+ </dd>
+<dt><span class="term">-G</span></dt>
+<dd>
+ <p>
+ Generate a key, but do not publish it or sign with it. This
+ option is incompatible with -P and -A.
+ </p>
+ </dd>
+<dt><span class="term">-g <em class="replaceable"><code>generator</code></em></span></dt>
+<dd>
+ <p>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Prints a short summary of the options and arguments to
+ <span class="command"><strong>dnssec-keygen</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which the key files are to be written.
+ </p>
+ </dd>
+<dt><span class="term">-k</span></dt>
+<dd>
+ <p>
+ Deprecated in favor of -T KEY.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>ttl</code></em></span></dt>
+<dd>
+ <p>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. If this value is not set and there
+ is no existing DNSKEY RRset, the TTL will default to the
+ SOA TTL. Setting the default TTL to <code class="literal">0</code>
+ or <code class="literal">none</code> is the same as leaving it unset.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd>
+ <p>
+ Sets the protocol value for the generated 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.
+ </p>
+ </dd>
+<dt><span class="term">-q</span></dt>
+<dd>
+ <p>
+ Quiet mode: Suppresses unnecessary output, including
+ progress indication. Without this option, when
+ <span class="command"><strong>dnssec-keygen</strong></span> is run interactively
+ to generate an RSA or DSA key pair, it will print a string
+ of symbols to <code class="filename">stderr</code> 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; a space
+ means that the number has passed all the tests and is
+ a satisfactory key.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p>
+ </dd>
+<dt><span class="term">-S <em class="replaceable"><code>key</code></em></span></dt>
+<dd>
+ <p>
+ Create a new key which is an explicit successor to an
+ existing key. The name, algorithm, size, and type of the
+ key will be set to match the existing key. The activation
+ date of the new key will be set to the inactivation date of
+ the existing one. The publication date will be set to the
+ activation date minus the prepublication interval, which
+ defaults to 30 days.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>strength</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </p>
+ </dd>
+<dt><span class="term">-T <em class="replaceable"><code>rrtype</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the resource record type to use for the key.
+ <code class="option">rrtype</code> 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).
+ </p>
+<p>
+ </p>
+<p>
+ Using any TSIG algorithm (HMAC-* or DH) forces this option
+ to KEY.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>TIMING OPTIONS</h2>
+
+
+ <p>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it. If not set, and if the -G option has
+ not been used, the default is "now".
+ </p>
+ </dd>
+<dt><span class="term">-P sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which CDS and CDNSKEY records that match this
+ key are to be published to the zone.
+ </p>
+ </dd>
+<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included in the zone and used to sign
+ it. If not set, and if the -G option has not been used, the
+ default is "now". If set, if and -P is not set, then
+ the publication date will be set to the activation date
+ minus the prepublication interval.
+ </p>
+ </dd>
+<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-I <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be retired. After that
+ date, the key will still be included in the zone, but it
+ will not be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </p>
+ </dd>
+<dt><span class="term">-D sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+ <p>
+ 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 isn't, then the publication date will default
+ to this much time before the activation date; conversely, if
+ the publication date is specified but activation date isn't,
+ then activation will be set to this much time after publication.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ As with date offsets, if the argument is followed by one of
+ the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
+ interval is measured in years, months, weeks, days, hours,
+ or minutes, respectively. Without a suffix, the interval is
+ measured in seconds.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>GENERATED KEYS</h2>
+
+ <p>
+ When <span class="command"><strong>dnssec-keygen</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </p>
+ <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ <p><code class="filename">nnnn</code> is the key name.
+ </p>
+ </li>
+<li class="listitem">
+ <p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p>
+ </li>
+<li class="listitem">
+ <p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p>
+ </li>
+</ul></div>
+ <p><span class="command"><strong>dnssec-keygen</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+ <p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+ <p>
+ The <code class="filename">.private</code> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+ <p>
+ Both <code class="filename">.key</code> and <code class="filename">.private</code>
+ files are generated for symmetric cryptography algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>EXAMPLE</h2>
+
+ <p>
+ To generate a 768-bit DSA key for the domain
+ <strong class="userinput"><code>example.com</code></strong>, the following command would be
+ issued:
+ </p>
+ <p><strong class="userinput"><code>dnssec-keygen -a DSA -b 768 -n ZONE example.com</code></strong>
+ </p>
+ <p>
+ The command would print a string of the form:
+ </p>
+ <p><strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ </p>
+ <p>
+ In this example, <span class="command"><strong>dnssec-keygen</strong></span> creates
+ the files <code class="filename">Kexample.com.+003+26160.key</code>
+ and
+ <code class="filename">Kexample.com.+003+26160.private</code>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4034</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-revoke.8 b/bin/dnssec/dnssec-revoke.8
new file mode 100644
index 0000000..9722069
--- /dev/null
+++ b/bin/dnssec/dnssec-revoke.8
@@ -0,0 +1,103 @@
+.\" Copyright (C) 2009, 2011, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-revoke
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-15
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-REVOKE" "8" "2014\-01\-15" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-revoke \- set the REVOKED bit on a DNSSEC key
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-revoke\fR\ 'u
+\fBdnssec\-revoke\fR [\fB\-hr\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\fR] [\fB\-R\fR] {keyfile}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-revoke\fR
+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\&.
+.SH "OPTIONS"
+.PP
+\-h
+.RS 4
+Emit usage message and exit\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which the key files are to reside\&.
+.RE
+.PP
+\-r
+.RS 4
+After writing the new keyset files remove the original keyset files\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.PP
+\-E \fIengine\fR
+.RS 4
+Specifies the cryptographic hardware to use, when applicable\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.PP
+\-f
+.RS 4
+Force overwrite: Causes
+\fBdnssec\-revoke\fR
+to write the new key pair even if a file already exists matching the algorithm and key ID of the revoked key\&.
+.RE
+.PP
+\-R
+.RS 4
+Print the key tag of the key with the REVOKE bit set but do not revoke the key\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 5011\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2011, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c
new file mode 100644
index 0000000..1a2b545
--- /dev/null
+++ b/bin/dnssec/dnssec-revoke.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-revoke";
+int verbose;
+
+static isc_mem_t *mctx = NULL;
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+#if defined(PKCS11CRYPTO)
+ fprintf(stderr, " -E engine: specify PKCS#11 provider "
+ "(default: %s)\n", PK11_LIB_LOCATION);
+#elif defined(USE_PKCS11)
+ fprintf(stderr, " -E engine: specify OpenSSL engine "
+ "(default \"pkcs11\")\n");
+#else
+ fprintf(stderr, " -E engine: specify OpenSSL engine\n");
+#endif
+ fprintf(stderr, " -f: force overwrite\n");
+ fprintf(stderr, " -K directory: use directory for key files\n");
+ fprintf(stderr, " -h: help\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;
+#ifdef USE_PKCS11
+ const char *engine = PKCS11_ENGINE;
+#else
+ const char *engine = NULL;
+#endif
+ char const *filename = NULL;
+ char *dir = NULL;
+ char newname[1024], oldname[1024];
+ char keystr[DST_KEY_FORMATSIZE];
+ char *endp;
+ int ch;
+ isc_entropy_t *ectx = NULL;
+ 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();
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("Out of memory");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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);
+ if (dir == NULL) {
+ fatal("Failed to allocate memory for "
+ "directory");
+ }
+ 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;
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("Could not initialize hash");
+ result = dst_lib_init2(mctx, ectx, engine,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("Could not initialize dst: %s",
+ isc_result_totext(result));
+ isc_entropy_stopcallbacksources(ectx);
+
+ 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 && dst_key_alg(key) != DST_ALG_RSAMD5) {
+ 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();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ 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.docbook b/bin/dnssec/dnssec-revoke.docbook
new file mode 100644
index 0000000..8055905
--- /dev/null
+++ b/bin/dnssec/dnssec-revoke.docbook
@@ -0,0 +1,169 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-revoke">
+ <info>
+ <date>2014-01-15</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-revoke</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-revoke</application></refname>
+ <refpurpose>set the REVOKED bit on a DNSSEC key</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2011</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-revoke</command>
+ <arg choice="opt" rep="norepeat"><option>-hr</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R</option></arg>
+ <arg choice="req" rep="norepeat">keyfile</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-revoke</command>
+ 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.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Emit usage message and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to reside.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r</term>
+ <listitem>
+ <para>
+ After writing the new keyset files remove the original keyset
+ files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the cryptographic hardware to use, when applicable.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Force overwrite: Causes <command>dnssec-revoke</command> to
+ write the new key pair even if a file already exists matching
+ the algorithm and key ID of the revoked key.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R</term>
+ <listitem>
+ <para>
+ Print the key tag of the key with the REVOKE bit set but do
+ not revoke the key.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 5011</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-revoke.html b/bin/dnssec/dnssec-revoke.html
new file mode 100644
index 0000000..f70ff3c
--- /dev/null
+++ b/bin/dnssec/dnssec-revoke.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2011, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-revoke</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-revoke"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-revoke</span>
+ &#8212; set the REVOKED bit on a DNSSEC key
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-revoke</code>
+ [<code class="option">-hr</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>]
+ [<code class="option">-f</code>]
+ [<code class="option">-R</code>]
+ {keyfile}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-revoke</strong></span>
+ 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.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Emit usage message and exit.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which the key files are to reside.
+ </p>
+ </dd>
+<dt><span class="term">-r</span></dt>
+<dd>
+ <p>
+ After writing the new keyset files remove the original keyset
+ files.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the cryptographic hardware to use, when applicable.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+<dt><span class="term">-f</span></dt>
+<dd>
+ <p>
+ Force overwrite: Causes <span class="command"><strong>dnssec-revoke</strong></span> to
+ write the new key pair even if a file already exists matching
+ the algorithm and key ID of the revoked key.
+ </p>
+ </dd>
+<dt><span class="term">-R</span></dt>
+<dd>
+ <p>
+ Print the key tag of the key with the REVOKE bit set but do
+ not revoke the key.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 5011</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-settime.8 b/bin/dnssec/dnssec-settime.8
new file mode 100644
index 0000000..cd04021
--- /dev/null
+++ b/bin/dnssec/dnssec-settime.8
@@ -0,0 +1,204 @@
+.\" Copyright (C) 2009-2011, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-settime
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2015-08-21
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-SETTIME" "8" "2015\-08\-21" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-settime \- set the key timing metadata for a DNSSEC key
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-settime\fR\ 'u
+\fBdnssec\-settime\fR [\fB\-f\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-h\fR] [\fB\-V\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] {keyfile}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-settime\fR
+reads a DNSSEC private key file and sets the key timing metadata as specified by the
+\fB\-P\fR,
+\fB\-A\fR,
+\fB\-R\fR,
+\fB\-I\fR, and
+\fB\-D\fR
+options\&. The metadata can then be used by
+\fBdnssec\-signzone\fR
+or other signing software to determine when a key is to be published, whether it should be used for signing a zone, etc\&.
+.PP
+If none of these options is set on the command line, then
+\fBdnssec\-settime\fR
+simply prints the key timing metadata already stored in the key\&.
+.PP
+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\*(Aqs permissions are always set to be inaccessible to anyone other than the owner (mode 0600)\&.
+.SH "OPTIONS"
+.PP
+\-f
+.RS 4
+Force an update of an old\-format key with no metadata fields\&. Without this option,
+\fBdnssec\-settime\fR
+will fail when attempting to update a legacy key\&. With this option, the key will be recreated in the new format, but with the original key data retained\&. The key\*(Aqs creation date will be set to the present time\&. If no other values are specified, then the key\*(Aqs publication and activation dates will also be set to the present time\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which the key files are to reside\&.
+.RE
+.PP
+\-L \fIttl\fR
+.RS 4
+Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL\&. Setting the default TTL to
+0
+or
+none
+removes it from the key\&.
+.RE
+.PP
+\-h
+.RS 4
+Emit usage message and exit\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-E \fIengine\fR
+.RS 4
+Specifies the cryptographic hardware to use, when applicable\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.SH "TIMING OPTIONS"
+.PP
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset 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 \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&.
+.PP
+\-P \fIdate/offset\fR
+.RS 4
+Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&.
+.RE
+.PP
+\-P sync \fIdate/offset\fR
+.RS 4
+Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone\&.
+.RE
+.PP
+\-A \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be activated\&. After that date, the key will be included in the zone and used to sign it\&.
+.RE
+.PP
+\-R \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&.
+.RE
+.PP
+\-I \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be retired\&. After that date, the key will still be included in the zone, but it will not be used to sign it\&.
+.RE
+.PP
+\-D \fIdate/offset\fR
+.RS 4
+Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.)
+.RE
+.PP
+\-D sync \fIdate/offset\fR
+.RS 4
+Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted\&.
+.RE
+.PP
+\-S \fIpredecessor key\fR
+.RS 4
+Select a key for which the key being modified will be 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 will be set to the inactivation date of the predecessor\&. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days\&.
+.RE
+.PP
+\-i \fIinterval\fR
+.RS 4
+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 isn\*(Aqt, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn\*(Aqt, then activation will be set to this much time after publication\&.
+.sp
+If the key is being set to be an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero\&.
+.sp
+As with date offsets, if the argument is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the interval is measured in years, months, weeks, days, hours, or minutes, respectively\&. Without a suffix, the interval is measured in seconds\&.
+.RE
+.SH "PRINTING OPTIONS"
+.PP
+\fBdnssec\-settime\fR
+can also be used to print the timing metadata associated with a key\&.
+.PP
+\-u
+.RS 4
+Print times in UNIX epoch format\&.
+.RE
+.PP
+\-p \fIC/P/Psync/A/R/I/D/Dsync/all\fR
+.RS 4
+Print a specific metadata value or set of metadata values\&. The
+\fB\-p\fR
+option may be followed by one or more of the following letters or strings to indicate which value or values to print:
+\fBC\fR
+for the creation date,
+\fBP\fR
+for the publication date,
+\fBPsync\fR
+for the CDS and CDNSKEY publication date,
+\fBA\fR
+for the activation date,
+\fBR\fR
+for the revocation date,
+\fBI\fR
+for the inactivation date,
+\fBD\fR
+for the deletion date, and
+\fBDsync\fR
+for the CDS and CDNSKEY deletion date To print all of the metadata, use
+\fB\-p all\fR\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 5011\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009-2011, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c
new file mode 100644
index 0000000..f355903
--- /dev/null
+++ b/bin/dnssec/dnssec-settime.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/result.h>
+#include <dns/log.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-settime";
+int verbose;
+
+static isc_mem_t *mctx = NULL;
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "General options:\n");
+#if defined(PKCS11CRYPTO)
+ fprintf(stderr, " -E engine: specify PKCS#11 provider "
+ "(default: %s)\n", PK11_LIB_LOCATION);
+#elif defined(USE_PKCS11)
+ fprintf(stderr, " -E engine: specify OpenSSL engine "
+ "(default \"pkcs11\")\n");
+#else
+ fprintf(stderr, " -E engine: specify OpenSSL engine\n");
+#endif
+ 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 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 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, "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;
+ const char *output = NULL;
+ 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 timet = when;
+ output = ctime(&timet);
+ fprintf(stream, "%s", output);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+#ifdef USE_PKCS11
+ const char *engine = PKCS11_ENGINE;
+#else
+ const char *engine = NULL;
+#endif
+ const char *filename = NULL;
+ char *directory = NULL;
+ char newname[1024];
+ char keystr[DST_KEY_FORMATSIZE];
+ char *endp, *p;
+ int ch;
+ isc_entropy_t *ectx = NULL;
+ const char *predecessor = NULL;
+ dst_key_t *prevkey = NULL;
+ dst_key_t *key = NULL;
+ isc_buffer_t buf;
+ dns_name_t *name = NULL;
+ dns_secalg_t alg = 0;
+ unsigned int size = 0;
+ uint16_t flags = 0;
+ int prepub = -1;
+ dns_ttl_t ttl = 0;
+ isc_stdtime_t now;
+ isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0;
+ isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0;
+ 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;
+ 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;
+
+ if (argc == 1)
+ usage();
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("Out of memory");
+
+ setup_logging(mctx, &log);
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ isc_commandline_errprint = false;
+
+ isc_stdtime_get(&now);
+
+#define CMDLINE_FLAGS "A:D:E:fhI:i:K:L:P:p:R:S:uv:V"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+ case 'f':
+ force = true;
+ 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;
+ break;
+ }
+
+ do {
+ switch (*p++) {
+ case 'C':
+ printcreate = true;
+ break;
+ case 'P':
+ if (!strncmp(p, "sync", 4)) {
+ p += 4;
+ printsyncadd = true;
+ break;
+ }
+ printpub = true;
+ break;
+ case 'A':
+ printact = true;
+ break;
+ case 'R':
+ printrev = true;
+ break;
+ case 'I':
+ printinact = true;
+ break;
+ case 'D':
+ if (!strncmp(p, "sync", 4)) {
+ p += 4;
+ printsyncdel = true;
+ break;
+ }
+ printdel = true;
+ break;
+ case ' ':
+ break;
+ default:
+ usage();
+ break;
+ }
+ } while (*p != '\0');
+ break;
+ case 'u':
+ epoch = true;
+ 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);
+ if (directory == NULL) {
+ fatal("Failed to allocate memory for "
+ "directory");
+ }
+ break;
+ case 'L':
+ ttl = strtottl(isc_commandline_argument);
+ setttl = true;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("-v must be followed by a number");
+ 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;
+ }
+ (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 'A':
+ if (setact || unsetact)
+ fatal("-A specified more than once");
+
+ changed = true;
+ act = strtotime(isc_commandline_argument,
+ now, now, &setact);
+ unsetact = !setact;
+ 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 'I':
+ if (setinact || unsetinact)
+ fatal("-I specified more than once");
+
+ changed = true;
+ inact = 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");
+
+ changed = true;
+ 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");
+
+ changed = true;
+ del = 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 '?':
+ 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 (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("Could not initialize hash");
+ result = dst_lib_init2(mctx, ectx, engine,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("Could not initialize dst: %s",
+ isc_result_totext(result));
+ isc_entropy_stopcallbacksources(ectx);
+
+ 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,
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ 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,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ 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 (setttl)
+ dst_key_setttl(key, ttl);
+
+ /*
+ * 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;
+ }
+
+ 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 (changed) {
+ 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, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
+ 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 (prevkey != NULL)
+ dst_key_free(&prevkey);
+ dst_key_free(&key);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ 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.docbook b/bin/dnssec/dnssec-settime.docbook
new file mode 100644
index 0000000..bf432bd
--- /dev/null
+++ b/bin/dnssec/dnssec-settime.docbook
@@ -0,0 +1,376 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-settime">
+ <info>
+ <date>2015-08-21</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-settime</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-settime</application></refname>
+ <refpurpose>set the key timing metadata for a DNSSEC key</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-settime</command>
+ <arg choice="opt" rep="norepeat"><option>-f</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D sync <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S <replaceable class="parameter">key</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">keyfile</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-settime</command>
+ reads a DNSSEC private key file and sets the key timing metadata
+ as specified by the <option>-P</option>, <option>-A</option>,
+ <option>-R</option>, <option>-I</option>, and <option>-D</option>
+ options. The metadata can then be used by
+ <command>dnssec-signzone</command> or other signing software to
+ determine when a key is to be published, whether it should be
+ used for signing a zone, etc.
+ </para>
+ <para>
+ If none of these options is set on the command line,
+ then <command>dnssec-settime</command> simply prints the key timing
+ metadata already stored in the key.
+ </para>
+ <para>
+ When key metadata fields are changed, both files of a key
+ pair (<filename>Knnnn.+aaa+iiiii.key</filename> and
+ <filename>Knnnn.+aaa+iiiii.private</filename>) 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).
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Force an update of an old-format key with no metadata fields.
+ Without this option, <command>dnssec-settime</command> will
+ fail when attempting to update a legacy key. With this option,
+ the key will be recreated in the new format, but with the
+ original key data retained. The key's creation date will be
+ set to the present time. If no other values are specified,
+ then the key's publication and activation dates will also
+ be set to the present time.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to reside.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. If this value is not set and there
+ is no existing DNSKEY RRset, the TTL will default to the
+ SOA TTL. Setting the default TTL to <literal>0</literal>
+ or <literal>none</literal> removes it from the key.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Emit usage message and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the cryptographic hardware to use, when applicable.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>TIMING OPTIONS</title></info>
+
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which CDS and CDNSKEY records that match this
+ key are to be published to the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included in the zone and used to sign
+ it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be retired. After that
+ date, the key will still be included in the zone, but it
+ will not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D sync <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">predecessor key</replaceable></term>
+ <listitem>
+ <para>
+ Select a key for which the key being modified will be 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 will be set
+ to the inactivation date of the predecessor. The publication
+ date will be set to the activation date minus the prepublication
+ interval, which defaults to 30 days.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">interval</replaceable></term>
+ <listitem>
+ <para>
+ 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 isn't, then the publication date will default
+ to this much time before the activation date; conversely, if
+ the publication date is specified but activation date isn't,
+ then activation will be set to this much time after publication.
+ </para>
+ <para>
+ If the key is being set to be an explicit successor to another
+ key, then the default prepublication interval is 30 days;
+ otherwise it is zero.
+ </para>
+ <para>
+ As with date offsets, if the argument is followed by one of
+ the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
+ interval is measured in years, months, weeks, days, hours,
+ or minutes, respectively. Without a suffix, the interval is
+ measured in seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>PRINTING OPTIONS</title></info>
+
+ <para>
+ <command>dnssec-settime</command> can also be used to print the
+ timing metadata associated with a key.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-u</term>
+ <listitem>
+ <para>
+ Print times in UNIX epoch format.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">C/P/Psync/A/R/I/D/Dsync/all</replaceable></term>
+ <listitem>
+ <para>
+ Print a specific metadata value or set of metadata values.
+ The <option>-p</option> option may be followed by one or more
+ of the following letters or strings to indicate which value
+ or values to print:
+ <option>C</option> for the creation date,
+ <option>P</option> for the publication date,
+ <option>Psync</option> for the CDS and CDNSKEY publication date,
+ <option>A</option> for the activation date,
+ <option>R</option> for the revocation date,
+ <option>I</option> for the inactivation date,
+ <option>D</option> for the deletion date, and
+ <option>Dsync</option> for the CDS and CDNSKEY deletion date
+ To print all of the metadata, use <option>-p all</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 5011</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-settime.html b/bin/dnssec/dnssec-settime.html
new file mode 100644
index 0000000..58122a3
--- /dev/null
+++ b/bin/dnssec/dnssec-settime.html
@@ -0,0 +1,315 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009-2011, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-settime</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-settime"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-settime</span>
+ &#8212; set the key timing metadata for a DNSSEC key
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-settime</code>
+ [<code class="option">-f</code>]
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-P sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-I <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-D sync <em class="replaceable"><code>date/offset</code></em></code>]
+ [<code class="option">-S <em class="replaceable"><code>key</code></em></code>]
+ [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>]
+ {keyfile}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-settime</strong></span>
+ reads a DNSSEC private key file and sets the key timing metadata
+ as specified by the <code class="option">-P</code>, <code class="option">-A</code>,
+ <code class="option">-R</code>, <code class="option">-I</code>, and <code class="option">-D</code>
+ options. The metadata can then be used by
+ <span class="command"><strong>dnssec-signzone</strong></span> or other signing software to
+ determine when a key is to be published, whether it should be
+ used for signing a zone, etc.
+ </p>
+ <p>
+ If none of these options is set on the command line,
+ then <span class="command"><strong>dnssec-settime</strong></span> simply prints the key timing
+ metadata already stored in the key.
+ </p>
+ <p>
+ When key metadata fields are changed, both files of a key
+ pair (<code class="filename">Knnnn.+aaa+iiiii.key</code> and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code>) 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).
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-f</span></dt>
+<dd>
+ <p>
+ Force an update of an old-format key with no metadata fields.
+ Without this option, <span class="command"><strong>dnssec-settime</strong></span> will
+ fail when attempting to update a legacy key. With this option,
+ the key will be recreated in the new format, but with the
+ original key data retained. The key's creation date will be
+ set to the present time. If no other values are specified,
+ then the key's publication and activation dates will also
+ be set to the present time.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which the key files are to reside.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>ttl</code></em></span></dt>
+<dd>
+ <p>
+ Sets the default TTL to use for this key when it is converted
+ into a DNSKEY RR. If the key is imported into a zone,
+ this is the TTL that will be used for it, unless there was
+ already a DNSKEY RRset in place, in which case the existing TTL
+ would take precedence. If this value is not set and there
+ is no existing DNSKEY RRset, the TTL will default to the
+ SOA TTL. Setting the default TTL to <code class="literal">0</code>
+ or <code class="literal">none</code> removes it from the key.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Emit usage message and exit.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the cryptographic hardware to use, when applicable.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>TIMING OPTIONS</h2>
+
+ <p>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset 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' or 'never'.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-P sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which CDS and CDNSKEY records that match this
+ key are to be published to the zone.
+ </p>
+ </dd>
+<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included in the zone and used to sign
+ it.
+ </p>
+ </dd>
+<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-I <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be retired. After that
+ date, the key will still be included in the zone, but it
+ will not be used to sign it.
+ </p>
+ </dd>
+<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the key is to be deleted. After that
+ date, the key will no longer be included in the zone. (It
+ may remain in the key repository, however.)
+ </p>
+ </dd>
+<dt><span class="term">-D sync <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+ <p>
+ Sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+ </p>
+ </dd>
+<dt><span class="term">-S <em class="replaceable"><code>predecessor key</code></em></span></dt>
+<dd>
+ <p>
+ Select a key for which the key being modified will be 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 will be set
+ to the inactivation date of the predecessor. The publication
+ date will be set to the activation date minus the prepublication
+ interval, which defaults to 30 days.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+ <p>
+ 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 isn't, then the publication date will default
+ to this much time before the activation date; conversely, if
+ the publication date is specified but activation date isn't,
+ then activation will be set to this much time after publication.
+ </p>
+ <p>
+ If the key is being set to be an explicit successor to another
+ key, then the default prepublication interval is 30 days;
+ otherwise it is zero.
+ </p>
+ <p>
+ As with date offsets, if the argument is followed by one of
+ the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the
+ interval is measured in years, months, weeks, days, hours,
+ or minutes, respectively. Without a suffix, the interval is
+ measured in seconds.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>PRINTING OPTIONS</h2>
+
+ <p>
+ <span class="command"><strong>dnssec-settime</strong></span> can also be used to print the
+ timing metadata associated with a key.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-u</span></dt>
+<dd>
+ <p>
+ Print times in UNIX epoch format.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>C/P/Psync/A/R/I/D/Dsync/all</code></em></span></dt>
+<dd>
+ <p>
+ Print a specific metadata value or set of metadata values.
+ The <code class="option">-p</code> option may be followed by one or more
+ of the following letters or strings to indicate which value
+ or values to print:
+ <code class="option">C</code> for the creation date,
+ <code class="option">P</code> for the publication date,
+ <code class="option">Psync</code> for the CDS and CDNSKEY publication date,
+ <code class="option">A</code> for the activation date,
+ <code class="option">R</code> for the revocation date,
+ <code class="option">I</code> for the inactivation date,
+ <code class="option">D</code> for the deletion date, and
+ <code class="option">Dsync</code> for the CDS and CDNSKEY deletion date
+ To print all of the metadata, use <code class="option">-p all</code>.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 5011</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-signzone.8 b/bin/dnssec/dnssec-signzone.8
new file mode 100644
index 0000000..fc86ff0
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.8
@@ -0,0 +1,480 @@
+.\" Copyright (C) 2000-2009, 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-signzone
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-02-18
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-SIGNZONE" "8" "2014\-02\-18" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-signzone \- DNSSEC zone signing tool
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-signzone\fR\ 'u
+\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-M\ \fR\fB\fImaxttl\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-P\fR] [\fB\-p\fR] [\fB\-Q\fR] [\fB\-R\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-t\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-X\ \fR\fB\fIextended\ end\-time\fR\fR] [\fB\-x\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-signzone\fR
+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 or not) is determined by the presence or absence of a
+keyset
+file for each child zone\&.
+.SH "OPTIONS"
+.PP
+\-a
+.RS 4
+Verify all generated signatures\&.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specifies the DNS class of the zone\&.
+.RE
+.PP
+\-C
+.RS 4
+Compatibility mode: Generate a
+keyset\-\fIzonename\fR
+file in addition to
+dsset\-\fIzonename\fR
+when signing a zone, for use by older versions of
+\fBdnssec\-signzone\fR\&.
+.RE
+.PP
+\-d \fIdirectory\fR
+.RS 4
+Look for
+dsset\-
+or
+keyset\-
+files in
+\fBdirectory\fR\&.
+.RE
+.PP
+\-D
+.RS 4
+Output only those record types automatically managed by
+\fBdnssec\-signzone\fR, i\&.e\&. RRSIG, NSEC, NSEC3 and NSEC3PARAM records\&. If smart signing (\fB\-S\fR) is used, DNSKEY records are also included\&. The resulting file can be included in the original zone file with
+\fB$INCLUDE\fR\&. This option cannot be combined with
+\fB\-O raw\fR,
+\fB\-O map\fR, or serial number updating\&.
+.RE
+.PP
+\-E \fIengine\fR
+.RS 4
+When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.PP
+\-g
+.RS 4
+Generate DS records for child zones from
+dsset\-
+or
+keyset\-
+file\&. Existing DS records will be removed\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Key repository: Specify a directory to search for DNSSEC keys\&. If not specified, defaults to the current directory\&.
+.RE
+.PP
+\-k \fIkey\fR
+.RS 4
+Treat specified key as a key signing key ignoring any key flags\&. This option may be specified multiple times\&.
+.RE
+.PP
+\-l \fIdomain\fR
+.RS 4
+Generate a DLV set in addition to the key (DNSKEY) and DS sets\&. The domain is appended to the name of the records\&.
+.RE
+.PP
+\-M \fImaxttl\fR
+.RS 4
+Sets the maximum TTL for the signed zone\&. Any TTL higher than
+\fImaxttl\fR
+in the input zone will be reduced to
+\fImaxttl\fR
+in the output\&. This provides certainty as to the largest possible TTL in the signed zone, which is useful to know when rolling keys because it is the longest possible time before signatures that have been retrieved by resolvers will expire from resolver caches\&. Zones that are signed with this option should be configured to use a matching
+\fBmax\-zone\-ttl\fR
+in
+named\&.conf\&. (Note: This option is incompatible with
+\fB\-D\fR, because it modifies non\-DNSSEC data in the output zone\&.)
+.RE
+.PP
+\-s \fIstart\-time\fR
+.RS 4
+Specify 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
+\fBstart\-time\fR
+is specified, the current time minus 1 hour (to allow for clock skew) is used\&.
+.RE
+.PP
+\-e \fIend\-time\fR
+.RS 4
+Specify the date and time when the generated RRSIG records expire\&. As with
+\fBstart\-time\fR, 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
+\fBend\-time\fR
+is specified, 30 days from the start time is used as a default\&.
+\fBend\-time\fR
+must be later than
+\fBstart\-time\fR\&.
+.RE
+.PP
+\-X \fIextended end\-time\fR
+.RS 4
+Specify the date and time when the generated RRSIG records for the DNSKEY RRset will 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\&.
+.sp
+As with
+\fBstart\-time\fR, 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
+\fBextended end\-time\fR
+is specified, the value of
+\fBend\-time\fR
+is used as the default\&. (\fBend\-time\fR, in turn, defaults to 30 days from the start time\&.)
+\fBextended end\-time\fR
+must be later than
+\fBstart\-time\fR\&.
+.RE
+.PP
+\-f \fIoutput\-file\fR
+.RS 4
+The name of the output file containing the signed zone\&. The default is to append
+\&.signed
+to the input filename\&. If
+\fBoutput\-file\fR
+is set to
+"\-", then the signed zone is written to the standard output, with a default output format of "full"\&.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-signzone\fR\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.PP
+\-i \fIinterval\fR
+.RS 4
+When a previously\-signed zone is passed as input, records may be resigned\&. The
+\fBinterval\fR
+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 will be replaced\&.
+.sp
+The default cycle interval is one quarter of the difference between the signature end and start times\&. So if neither
+\fBend\-time\fR
+or
+\fBstart\-time\fR
+are specified,
+\fBdnssec\-signzone\fR
+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 would be replaced\&.
+.RE
+.PP
+\-I \fIinput\-format\fR
+.RS 4
+The format of the input zone file\&. Possible formats are
+\fB"text"\fR
+(default),
+\fB"raw"\fR, and
+\fB"map"\fR\&. 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\&. The use of this option does not make much sense for non\-dynamic zones\&.
+.RE
+.PP
+\-j \fIjitter\fR
+.RS 4
+When signing a zone with a fixed signature lifetime, all RRSIG records issued at the time of signing expires simultaneously\&. If the zone is incrementally signed, i\&.e\&. a previously\-signed zone is passed as input to the signer, all expired signatures have to be regenerated at about the same time\&. The
+\fBjitter\fR
+option specifies a jitter window that will be used to randomize the signature expire time, thus spreading incremental signature regeneration over time\&.
+.sp
+Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i\&.e\&. if large numbers of RRSIGs don\*(Aqt expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time\&.
+.RE
+.PP
+\-L \fIserial\fR
+.RS 4
+When writing a signed zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number\&. (This is expected to be used primarily for testing purposes\&.)
+.RE
+.PP
+\-n \fIncpus\fR
+.RS 4
+Specifies the number of threads to use\&. By default, one thread is started for each detected CPU\&.
+.RE
+.PP
+\-N \fIsoa\-serial\-format\fR
+.RS 4
+The SOA serial number format of the signed zone\&. Possible formats are
+\fB"keep"\fR
+(default),
+\fB"increment"\fR,
+\fB"unixtime"\fR, and
+\fB"date"\fR\&.
+.PP
+\fB"keep"\fR
+.RS 4
+Do not modify the SOA serial number\&.
+.RE
+.PP
+\fB"increment"\fR
+.RS 4
+Increment the SOA serial number using RFC 1982 arithmetics\&.
+.RE
+.PP
+\fB"unixtime"\fR
+.RS 4
+Set the SOA serial number to the number of seconds since epoch\&.
+.RE
+.PP
+\fB"date"\fR
+.RS 4
+Set the SOA serial number to today\*(Aqs date in YYYYMMDDNN format\&.
+.RE
+.RE
+.PP
+\-o \fIorigin\fR
+.RS 4
+The zone origin\&. If not specified, the name of the zone file is assumed to be the origin\&.
+.RE
+.PP
+\-O \fIoutput\-format\fR
+.RS 4
+The format of the output file containing the signed zone\&. Possible formats are
+\fB"text"\fR
+(default), which is the standard textual representation of the zone;
+\fB"full"\fR, which is text output in a format suitable for processing by external scripts; and
+\fB"map"\fR,
+\fB"raw"\fR, and
+\fB"raw=N"\fR, which store the zone in binary formats for rapid loading by
+\fBnamed\fR\&.
+\fB"raw=N"\fR
+specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of
+\fBnamed\fR; if N is 1, the file can be read by release 9\&.9\&.0 or higher; the default is 1\&.
+.RE
+.PP
+\-p
+.RS 4
+Use pseudo\-random data when signing the zone\&. This is faster, but less secure, than using real random data\&. This option may be useful when signing large zones or when the entropy source is limited\&.
+.RE
+.PP
+\-P
+.RS 4
+Disable post sign verification tests\&.
+.sp
+The post sign verification test ensures 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\&.
+.RE
+.PP
+\-Q
+.RS 4
+Remove signatures from keys that are no longer active\&.
+.sp
+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
+\fB\-Q\fR
+forces
+\fBdnssec\-signzone\fR
+to remove signatures from keys that are no longer active\&. This enables ZSK rollover using the procedure described in RFC 4641, section 4\&.2\&.1\&.1 ("Pre\-Publish Key Rollover")\&.
+.RE
+.PP
+\-R
+.RS 4
+Remove signatures from keys that are no longer published\&.
+.sp
+This option is similar to
+\fB\-Q\fR, except it forces
+\fBdnssec\-signzone\fR
+to signatures from keys that are no longer published\&. This enables ZSK rollover using the procedure described in RFC 4641, section 4\&.2\&.1\&.2 ("Double Signature Zone Signing Key Rollover")\&.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies the source of randomness\&. If the operating system does not provide a
+/dev/random
+or equivalent device, the default source of randomness is keyboard input\&.
+randomdev
+specifies the name of a character device or file containing random data to be used instead of the default\&. The special value
+keyboard
+indicates that keyboard input should be used\&.
+.RE
+.PP
+\-S
+.RS 4
+Smart signing: Instructs
+\fBdnssec\-signzone\fR
+to search the key repository for keys that match the zone being signed, and to include them in the zone if appropriate\&.
+.sp
+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:
+.PP
+.RS 4
+If no timing metadata has been set for the key, the key is published in the zone and used to sign the zone\&.
+.RE
+.PP
+.RS 4
+If the key\*(Aqs publication date is set and is in the past, the key is published in the zone\&.
+.RE
+.PP
+.RS 4
+If the key\*(Aqs activation date is set and in the past, the key is published (regardless of publication date) and used to sign the zone\&.
+.RE
+.PP
+.RS 4
+If the key\*(Aqs revocation date is set and in the past, and the key is published, then the key is revoked, and the revoked key is used to sign the zone\&.
+.RE
+.PP
+.RS 4
+If either of the key\*(Aqs unpublication or deletion dates are set and in the past, the key is NOT published or used to sign the zone, regardless of any other metadata\&.
+.RE
+.RE
+.PP
+\-T \fIttl\fR
+.RS 4
+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\*(Aqs SOA record\&. This option is ignored when signing without
+\fB\-S\fR, 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\*(Aq TTL values will be set to match them, or if any of the imported DNSKEY records had a default TTL value\&. In the event of a a conflict between TTL values in imported keys, the shortest one is used\&.
+.RE
+.PP
+\-t
+.RS 4
+Print statistics at completion\&.
+.RE
+.PP
+\-u
+.RS 4
+Update 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 switch to NSEC or to NSEC3 with different parameters\&. Without this option,
+\fBdnssec\-signzone\fR
+will retain the existing chain when re\-signing\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-x
+.RS 4
+Only sign the DNSKEY RRset with key\-signing keys, and omit signatures from zone\-signing keys\&. (This is similar to the
+\fBdnssec\-dnskey\-kskonly yes;\fR
+zone option in
+\fBnamed\fR\&.)
+.RE
+.PP
+\-z
+.RS 4
+Ignore KSK flag on key when determining what to sign\&. This causes KSK\-flagged keys to sign all records, not just the DNSKEY RRset\&. (This is similar to the
+\fBupdate\-check\-ksk no;\fR
+zone option in
+\fBnamed\fR\&.)
+.RE
+.PP
+\-3 \fIsalt\fR
+.RS 4
+Generate an NSEC3 chain with the given hex encoded salt\&. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain\&.
+.RE
+.PP
+\-H \fIiterations\fR
+.RS 4
+When generating an NSEC3 chain, use this many iterations\&. The default is 10\&.
+.RE
+.PP
+\-A
+.RS 4
+When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations\&.
+.sp
+Using this option twice (i\&.e\&.,
+\fB\-AA\fR) turns the OPTOUT flag off for all records\&. This is useful when using the
+\fB\-u\fR
+option to modify an NSEC3 chain which previously had OPTOUT set\&.
+.RE
+.PP
+zonefile
+.RS 4
+The file containing the zone to be signed\&.
+.RE
+.PP
+key
+.RS 4
+Specify which keys should be used to sign the zone\&. If no keys are specified, then the zone will be examined for DNSKEY records at the zone apex\&. If these are found and there are matching private keys, in the current directory, then these will be used for signing\&.
+.RE
+.SH "EXAMPLE"
+.PP
+The following command signs the
+\fBexample\&.com\fR
+zone with the DSA key generated by
+\fBdnssec\-keygen\fR
+(Kexample\&.com\&.+003+17247)\&. Because the
+\fB\-S\fR
+option is not being used, the zone\*(Aqs 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 (\fB\-g\fR)\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+% dnssec\-signzone \-g \-o example\&.com db\&.example\&.com \e
+Kexample\&.com\&.+003+17247
+db\&.example\&.com\&.signed
+%
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+In the above example,
+\fBdnssec\-signzone\fR
+creates the file
+db\&.example\&.com\&.signed\&. This file should be referenced in a zone statement in a
+named\&.conf
+file\&.
+.PP
+This example re\-signs a previously signed zone with default parameters\&. The private keys are assumed to be in the current directory\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+% cp db\&.example\&.com\&.signed db\&.example\&.com
+% dnssec\-signzone \-o example\&.com db\&.example\&.com
+db\&.example\&.com\&.signed
+%
+.fi
+.if n \{\
+.RE
+.\}
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 4033,
+RFC 4641\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2009, 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c
new file mode 100644
index 0000000..c6a0313
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.c
@@ -0,0 +1,3902 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * 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 <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base32.h>
+#include <isc/commandline.h>
+#include <isc/entropy.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/rwlock.h>
+#include <isc/serial.h>
+#include <isc/safe.h>
+#include <isc/stdio.h>
+#include <isc/stdlib.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/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+#include <dns/update.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
+#endif
+
+const char *program = "dnssec-signzone";
+int verbose;
+
+typedef struct hashlist hashlist_t;
+
+static int nsec_datatype = dns_rdatatype_nsec;
+
+#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;
+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 isc_entropy_t *ectx = 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_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 = 10U;
+static unsigned char saltbuf[255];
+static unsigned char *gsalt = saltbuf;
+static size_t salt_length = 0;
+static isc_task_t *master = NULL;
+static unsigned int ntasks = 0;
+static bool shuttingdown = false, finished = false;
+static bool nokeys = false;
+static bool removefile = false;
+static bool generateds = false;
+static bool ignore_kskflag = false;
+static bool keyset_kskonly = false;
+static dns_name_t *dlv = NULL;
+static dns_fixedname_t dlv_fixed;
+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;
+bool set_maxttl = false;
+static dns_ttl_t maxttl = 0;
+
+#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, NULL);
+
+ 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, &iter);
+ check_result(result, "dns_db_allrdatasets");
+
+ dns_rdataset_init(&rds);
+
+ result = isc_buffer_allocate(mctx, &buffer, bufsize);
+ check_result(result, "isc_buffer_allocate");
+
+ 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, buffer);
+ if (result != ISC_R_NOSPACE)
+ break;
+
+ bufsize <<= 1;
+ isc_buffer_free(&buffer);
+ result = isc_buffer_allocate(mctx, &buffer, bufsize);
+ check_result(result, "isc_buffer_allocate");
+ }
+ 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) ? isc_random_jitter(expiry, jitter) : expiry;
+ isc_buffer_init(&b, array, sizeof(array));
+ result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
+ mctx, &b, &trdata);
+ isc_entropy_stopcallbacksources(ectx);
+ 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, mctx, &trdata);
+ if (result == ISC_R_SUCCESS) {
+ 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 inline bool
+issigningkey(dns_dnsseckey_t *key) {
+ return (key->force_sign || key->hint_sign);
+}
+
+static inline bool
+ispublishedkey(dns_dnsseckey_t *key) {
+ return ((key->force_publish || key->hint_publish) &&
+ !key->hint_remove);
+}
+
+static inline bool
+iszonekey(dns_dnsseckey_t *key) {
+ return (dns_name_equal(dst_key_name(key->key), gorigin) &&
+ dst_key_iszonekey(key->key));
+}
+
+static inline bool
+isksk(dns_dnsseckey_t *key) {
+ return (key->ksk);
+}
+
+static inline 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;
+
+ isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
+ key = keythatsigned_unlocked(rrsig);
+ isc_rwlock_unlock(&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);
+ }
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("failure looking for '%s DNSKEY' in database: %s",
+ namestr, isc_result_totext(result));
+ /* NOTREACHED */
+ return (false); /* removes a warning */
+}
+
+static inline 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, mctx, rrsig);
+ if (result == ISC_R_SUCCESS) {
+ 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[TYPE_FORMATSIZE];
+ char sigstr[SIG_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ type_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));
+ if (wassignedby == NULL || nowsignedby == NULL)
+ fatal("out of memory");
+
+ 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));
+ if (key != NULL && issigningkey(key))
+ expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
+ else
+ expired = isc_serial_gt(now, 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, "removing 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_dnskey &&
+ dns_name_equal(name, gorigin)) {
+ bool have_ksk;
+ dns_dnsseckey_t *tmpkey;
+
+ have_ksk = isksk(key);
+ for (tmpkey = ISC_LIST_HEAD(keylist);
+ tmpkey != NULL;
+ tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
+ if (dst_key_alg(key->key) !=
+ dst_key_alg(tmpkey->key))
+ continue;
+ if (REVOKE(tmpkey->key))
+ continue;
+ if (isksk(tmpkey))
+ have_ksk = true;
+ }
+ if (isksk(key) || !have_ksk ||
+ (iszsk(key) && !keyset_kskonly))
+ signwithkey(name, set, key->key, ttl, add,
+ "signing with dnskey");
+ } else if (set->type == dns_rdatatype_cds ||
+ set->type == dns_rdatatype_cdnskey ||
+ iszsk(key)) {
+ 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 (isc_safe_memcompare(a, b, hash_length + 1));
+}
+
+static void
+hashlist_sort(hashlist_t *l) {
+ 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 hashs.
+ */
+ 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_load3(*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_SHA1,
+ 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);
+
+ dns_rdata_reset(&ds);
+ 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);
+}
+
+/*%
+ * 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, &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 extranous RRSIG records for node.
+ */
+static inline 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, &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, &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);
+ zone_soa_min_ttl = dns_soa_getminimum(&rdata);
+ soa_ttl = soaset.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;
+
+ 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);
+ } else if (serial != 0 || method == dns_updatemethod_none) {
+ /* Set SOA serial to the value provided. */
+ new_serial = serial;
+ } else {
+ /* Increment SOA serial using RFC 1982 arithmetics */
+ new_serial = (old_serial + 1) & 0xFFFFFFFF;
+ if (new_serial == 0)
+ new_serial = 1;
+ }
+
+ /* 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, &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)
+ 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 master 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 (shuttingdown)
+ return;
+
+ LOCK(&namelock);
+ if (finished) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ goto unlock;
+ }
+
+ fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
+ if (fname == NULL)
+ fatal("out of memory");
+ 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) {
+ 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));
+ if (sevent == NULL)
+ fatal("failed to allocate event\n");
+
+ 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));
+ if (wevent == NULL)
+ fatal("failed to allocate event\n");
+ wevent->node = node;
+ wevent->fname = fname;
+ isc_task_send(master, 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, &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()");
+ continue;
+ }
+ }
+ 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, &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, &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_find(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[TYPE_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ type_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, &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, NULL);
+ 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 hashs 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, NULL);
+ 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_load2(*db, file, inputformat);
+ 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, ...) {
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ putc('\n', stderr);
+}
+
+static void
+build_final_keylist(void) {
+ isc_result_t result;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+ dns_dnsseckeylist_t matchkeys;
+ char name[DNS_NAME_FORMATSIZE];
+
+ /*
+ * Find keys that match this zone in the key repository.
+ */
+ ISC_LIST_INIT(matchkeys);
+ result = dns_dnssec_findmatchingkeys(gorigin, directory,
+ 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");
+
+ dns_diff_init(mctx, &diff);
+
+ /*
+ * Update keylist with information from from the key repository.
+ */
+ dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
+ &diff, ignore_kskflag, mctx, report);
+
+ 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_closeversion(gdb, &ver, true);
+
+ dns_diff_clear(&diff);
+}
+
+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_fixedname_t fixed;
+ 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, *tmpkey;
+ 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 (filename == NULL)
+ fatal("out of memory");
+ 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);
+
+ if (type == dns_rdatatype_dlv) {
+ dns_name_t tname;
+ unsigned int labels;
+
+ dns_name_init(&tname, NULL);
+ name = dns_fixedname_initname(&fixed);
+ labels = dns_name_countlabels(gorigin);
+ dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
+ result = dns_name_concatenate(&tname, dlv, name, NULL);
+ check_result(result, "dns_name_concatenate");
+ } else
+ 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 (tmpkey = ISC_LIST_HEAD(keylist);
+ tmpkey != NULL;
+ tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
+ if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
+ continue;
+ if (REVOKE(tmpkey->key))
+ continue;
+ if (isksk(tmpkey))
+ 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_SHA1,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+ if (type == dns_rdatatype_dlv)
+ ds.type = dns_rdatatype_dlv;
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_ADDRESIGN,
+ name, 0, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+
+ dns_rdata_reset(&ds);
+ result = dns_ds_buildrdata(gorigin, &rdata,
+ DNS_DSDIGEST_SHA256,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+ if (type == dns_rdatatype_dlv)
+ ds.type = dns_rdatatype_dlv;
+ 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);
+ 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;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ currenttime = time(NULL);
+ fprintf(fp, "; File written on %s", ctime(&currenttime));
+}
+
+static void
+print_version(FILE *fp) {
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ fprintf(fp, "; dnssec_signzone version " VERSION "\n");
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+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", 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-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-r randomdev:\n");
+ fprintf(stderr, "\t\ta file containing random data\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");
+#if defined(PKCS11CRYPTO)
+ fprintf(stderr, "\t\tpath to PKCS#11 provider library "
+ "(default is %s)\n", PK11_LIB_LOCATION);
+#elif defined(USE_PKCS11)
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+#else
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
+#endif
+ fprintf(stderr, "\t-p:\t");
+ fprintf(stderr, "use pseudorandom data (faster but less secure)\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-l lookasidezone\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;
+ isc_log_t *log = NULL;
+ bool pseudorandom = false;
+#ifdef USE_PKCS11
+ const char *engine = PKCS11_ENGINE;
+#else
+ const char *engine = NULL;
+#endif
+ unsigned int eflags;
+ bool free_output = false;
+ int tempfilelen = 0;
+ dns_rdataclass_t rdclass;
+ isc_task_t **tasks = NULL;
+ isc_buffer_t b;
+ int len;
+ hashlist_t hashlist;
+ bool make_keyset = false;
+ bool set_salt = false;
+ bool set_optout = false;
+ bool set_iter = false;
+ bool nonsecify = 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:PpQRr: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;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+#ifdef _WIN32
+ InitSockets();
+#endif
+
+ masterstyle = &dns_master_style_explicitttl;
+
+ check_result(isc_app_start(), "isc_app_start");
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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;
+ 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':
+ len = strlen(isc_commandline_argument);
+ isc_buffer_init(&b, isc_commandline_argument, len);
+ isc_buffer_add(&b, len);
+
+ dlv = dns_fixedname_initname(&dlv_fixed);
+ result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
+ NULL);
+ check_result(result, "dns_name_fromtext(dlv)");
+ 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':
+ pseudorandom = true;
+ break;
+
+ case 'Q':
+ remove_inactkeysigs = true;
+ break;
+
+ case 'R':
+ remove_orphansigs = true;
+ break;
+
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ 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 '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);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ eflags = ISC_ENTROPY_BLOCKING;
+ if (!pseudorandom)
+ eflags |= ISC_ENTROPY_GOODONLY;
+
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create hash context");
+
+ result = dst_lib_init2(mctx, ectx, engine, eflags);
+ 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);
+ if (output == NULL)
+ fatal("out of memory");
+ snprintf(output, size, "%s.signed", file);
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0)
+ inputformat = dns_masterformat_text;
+ else if (strcasecmp(inputformatstr, "map") == 0)
+ inputformat = dns_masterformat_map;
+ 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, "map") == 0) {
+ outputformat = dns_masterformat_map;
+ } else if (strcasecmp(outputformatstr, "raw") == 0) {
+ outputformat = dns_masterformat_raw;
+ } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
+ char *end;
+ outputformat = dns_masterformat_raw;
+
+ 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, 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);
+ result = isc_rwlock_init(&keylist_lock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize keylist_lock: %s",
+ isc_result_totext(result));
+
+ /*
+ * 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) {
+ unsigned int max;
+ bool answer;
+
+ hash_length = dns_nsec3_hashlength(dns_hash_sha1);
+ hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
+ hash_length);
+ result = dns_nsec_nseconly(gdb, gversion, &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");
+
+ result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
+ check_result(result, "dns_nsec3_maxiterations()");
+ if (nsec3iter > max)
+ fatal("NSEC3 iterations too big for weakest DNSKEY "
+ "strength. Maximum iterations allowed %u.", max);
+ } 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 (dlv != NULL) {
+ writeset("dlvset-", dns_rdatatype_dlv);
+ }
+ }
+
+ if (output_stdout) {
+ outfp = stdout;
+ if (outputformatstr == NULL)
+ masterstyle = &dns_master_style_full;
+ } else {
+ tempfilelen = strlen(output) + 20;
+ tempfile = isc_mem_get(mctx, tempfilelen);
+ if (tempfile == NULL)
+ fatal("out of memory");
+
+ 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);
+
+ result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task manager: %s",
+ isc_result_totext(result));
+
+ master = NULL;
+ result = isc_task_create(taskmgr, 0, &master);
+ 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 *));
+ if (tasks == NULL)
+ fatal("out of memory");
+ 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));
+ }
+
+ RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
+ if (printstats)
+ RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
+
+ presign();
+ TIME_NOW(&sign_start);
+ signapex();
+ if (!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, master, startworker,
+ tasks[i]);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to start task: %s",
+ isc_result_totext(result));
+ }
+ (void)isc_app_run();
+ if (!finished)
+ fatal("process aborted by user");
+ } else
+ isc_task_detach(&master);
+ shuttingdown = true;
+ for (i = 0; i < (int)ntasks; i++)
+ isc_task_detach(&tasks[i]);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
+ postsign();
+ TIME_NOW(&sign_finish);
+
+ if (!disable_zone_check)
+ verifyzone(gdb, gversion, gorigin, mctx,
+ ignore_kskflag, keyset_kskonly);
+
+ 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_dumptostream3(mctx, gdb, gversion,
+ masterstyle, outputformat,
+ &header, outfp);
+ check_result(result, "dns_master_dumptostream3");
+ }
+
+ DESTROYLOCK(&namelock);
+ if (printstats)
+ DESTROYLOCK(&statslock);
+
+ if (!output_stdout) {
+ result = isc_stdio_close(outfp);
+ check_result(result, "isc_stdio_close");
+ removefile = false;
+
+ 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);
+ }
+
+ 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();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_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);
+ }
+
+#ifdef _WIN32
+ DestroySockets();
+#endif
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook
new file mode 100644
index 0000000..333d929
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.docbook
@@ -0,0 +1,838 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-signzone">
+ <info>
+ <date>2014-02-18</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-signzone</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-signzone</application></refname>
+ <refpurpose>DNSSEC zone signing tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-signzone</command>
+ <arg choice="opt" rep="norepeat"><option>-a</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-e <replaceable class="parameter">end-time</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">output-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-g</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">input-format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-j <replaceable class="parameter">jitter</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">key</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">serial</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-M <replaceable class="parameter">maxttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-N <replaceable class="parameter">soa-serial-format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-O <replaceable class="parameter">output-format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-Q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-u</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-X <replaceable class="parameter">extended end-time</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-z</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-3 <replaceable class="parameter">salt</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-H <replaceable class="parameter">iterations</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-A</option></arg>
+ <arg choice="req" rep="norepeat">zonefile</arg>
+ <arg rep="repeat" choice="opt">key</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-signzone</command>
+ 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 or not) is
+ determined by the presence or absence of a
+ <filename>keyset</filename> file for each child zone.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ Verify all generated signatures.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class of the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Compatibility mode: Generate a
+ <filename>keyset-<replaceable>zonename</replaceable></filename>
+ file in addition to
+ <filename>dsset-<replaceable>zonename</replaceable></filename>
+ when signing a zone, for use by older versions of
+ <command>dnssec-signzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Look for <filename>dsset-</filename> or
+ <filename>keyset-</filename> files in <option>directory</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D</term>
+ <listitem>
+ <para>
+ Output only those record types automatically managed by
+ <command>dnssec-signzone</command>, i.e. RRSIG, NSEC,
+ NSEC3 and NSEC3PARAM records. If smart signing
+ (<option>-S</option>) is used, DNSKEY records are also
+ included. The resulting file can be included in the original
+ zone file with <command>$INCLUDE</command>. This option
+ cannot be combined with <option>-O raw</option>,
+ <option>-O map</option>, or serial number updating.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+ When applicable, specifies the hardware to use for
+ cryptographic operations, such as a secure key store used
+ for signing.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Generate DS records for child zones from
+ <filename>dsset-</filename> or <filename>keyset-</filename>
+ file. Existing DS records will be removed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Key repository: Specify a directory to search for DNSSEC keys.
+ If not specified, defaults to the current directory.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">key</replaceable></term>
+ <listitem>
+ <para>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-M <replaceable class="parameter">maxttl</replaceable></term>
+ <listitem>
+ <para>
+ Sets the maximum TTL for the signed zone.
+ Any TTL higher than <replaceable>maxttl</replaceable> in the
+ input zone will be reduced to <replaceable>maxttl</replaceable>
+ in the output. This provides certainty as to the largest
+ possible TTL in the signed zone, which is useful to know when
+ rolling keys because it is the longest possible time before
+ signatures that have been retrieved by resolvers will expire
+ from resolver caches. Zones that are signed with this
+ option should be configured to use a matching
+ <option>max-zone-ttl</option> in <filename>named.conf</filename>.
+ (Note: This option is incompatible with <option>-D</option>,
+ because it modifies non-DNSSEC data in the output zone.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">start-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify 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 <option>start-time</option> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e <replaceable class="parameter">end-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <option>start-time</option>, 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 <option>end-time</option> is
+ specified, 30 days from the start time is used as a default.
+ <option>end-time</option> must be later than
+ <option>start-time</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-X <replaceable class="parameter">extended end-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated RRSIG records
+ for the DNSKEY RRset will 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.
+ </para>
+ <para>
+ As with <option>start-time</option>, 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 <option>extended end-time</option> is
+ specified, the value of <option>end-time</option> is used as
+ the default. (<option>end-time</option>, in turn, defaults to
+ 30 days from the start time.) <option>extended end-time</option>
+ must be later than <option>start-time</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">output-file</replaceable></term>
+ <listitem>
+ <para>
+ The name of the output file containing the signed zone. The
+ default is to append <filename>.signed</filename> to
+ the input filename. If <option>output-file</option> is
+ set to <literal>"-"</literal>, then the signed zone is
+ written to the standard output, with a default output
+ format of "full".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-signzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">interval</replaceable></term>
+ <listitem>
+ <para>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <option>interval</option> 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 will be replaced.
+ </para>
+ <para>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <option>end-time</option> or <option>start-time</option>
+ are specified, <command>dnssec-signzone</command>
+ 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 would be
+ replaced.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">input-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the input zone file.
+ Possible formats are <command>"text"</command> (default),
+ <command>"raw"</command>, and <command>"map"</command>.
+ 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.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j <replaceable class="parameter">jitter</replaceable></term>
+ <listitem>
+ <para>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <option>jitter</option> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </para>
+ <para>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">serial</replaceable></term>
+ <listitem>
+ <para>
+ When writing a signed zone to "raw" or "map" format, set the
+ "source serial" value in the header to the specified serial
+ number. (This is expected to be used primarily for testing
+ purposes.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">ncpus</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-N <replaceable class="parameter">soa-serial-format</replaceable></term>
+ <listitem>
+ <para>
+ The SOA serial number format of the signed zone.
+ Possible formats are <command>"keep"</command> (default),
+ <command>"increment"</command>, <command>"unixtime"</command>,
+ and <command>"date"</command>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>"keep"</command></term>
+ <listitem>
+ <para>Do not modify the SOA serial number.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"increment"</command></term>
+ <listitem>
+ <para>Increment the SOA serial number using RFC 1982
+ arithmetics.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"unixtime"</command></term>
+ <listitem>
+ <para>Set the SOA serial number to the number of seconds
+ since epoch.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"date"</command></term>
+ <listitem>
+ <para>Set the SOA serial number to today's date in
+ YYYYMMDDNN format.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-o <replaceable class="parameter">origin</replaceable></term>
+ <listitem>
+ <para>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-O <replaceable class="parameter">output-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the output file containing the signed zone.
+ Possible formats are <command>"text"</command> (default),
+ which is the standard textual representation of the zone;
+ <command>"full"</command>, which is text output in a
+ format suitable for processing by external scripts;
+ and <command>"map"</command>, <command>"raw"</command>,
+ and <command>"raw=N"</command>, which store the zone in
+ binary formats for rapid loading by <command>named</command>.
+ <command>"raw=N"</command> specifies the format version of
+ the raw zone file: if N is 0, the raw file can be read by
+ any version of <command>named</command>; if N is 1, the file
+ can be read by release 9.9.0 or higher; the default is 1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p</term>
+ <listitem>
+ <para>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P</term>
+ <listitem>
+ <para>
+ Disable post sign verification tests.
+ </para>
+ <para>
+ The post sign verification test ensures 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-Q</term>
+ <listitem>
+ <para>
+ Remove signatures from keys that are no longer active.
+ </para>
+ <para>
+ 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 <command>dnssec-signzone</command> to remove
+ signatures from keys that are no longer active. This
+ enables ZSK rollover using the procedure described in
+ RFC 4641, section 4.2.1.1 ("Pre-Publish Key Rollover").
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>-R</term>
+ <listitem>
+ <para>
+ Remove signatures from keys that are no longer published.
+ </para>
+ <para>
+ This option is similar to <option>-Q</option>, except it
+ forces <command>dnssec-signzone</command> to signatures from
+ keys that are no longer published. This enables ZSK rollover
+ using the procedure described in RFC 4641, section 4.2.1.2
+ ("Double Signature Zone Signing Key Rollover").
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the source of randomness. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S</term>
+ <listitem>
+ <para>
+ Smart signing: Instructs <command>dnssec-signzone</command> to
+ search the key repository for keys that match the zone being
+ signed, and to include them in the zone if appropriate.
+ </para>
+ <para>
+ 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:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <listitem>
+ <para>
+ If no timing metadata has been set for the key, the key is
+ published in the zone and used to sign the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If the key's publication date is set and is in the past, the
+ key is published in the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If the key's activation date is set and in the past, the
+ key is published (regardless of publication date) and
+ used to sign the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If the key's revocation date is set and in the past, and the
+ key is published, then the key is revoked, and the revoked key
+ is used to sign the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If either of the key's unpublication or deletion dates are set
+ and in the past, the key is NOT published or used to sign the
+ zone, regardless of any other metadata.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ 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</option>, 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 will be set to match
+ them, or if any of the imported DNSKEY records had a default
+ TTL value. In the event of a a conflict between TTL values in
+ imported keys, the shortest one is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t</term>
+ <listitem>
+ <para>
+ Print statistics at completion.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u</term>
+ <listitem>
+ <para>
+ Update 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 switch to NSEC or to NSEC3 with different parameters.
+ Without this option, <command>dnssec-signzone</command> will
+ retain the existing chain when re-signing.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x</term>
+ <listitem>
+ <para>
+ Only sign the DNSKEY RRset with key-signing keys, and omit
+ signatures from zone-signing keys. (This is similar to the
+ <command>dnssec-dnskey-kskonly yes;</command> zone option in
+ <command>named</command>.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Ignore KSK flag on key when determining what to sign. This
+ causes KSK-flagged keys to sign all records, not just the
+ DNSKEY RRset. (This is similar to the
+ <command>update-check-ksk no;</command> zone option in
+ <command>named</command>.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-3 <replaceable class="parameter">salt</replaceable></term>
+ <listitem>
+ <para>
+ Generate an NSEC3 chain with the given hex encoded salt.
+ A dash (<replaceable class="parameter">salt</replaceable>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-H <replaceable class="parameter">iterations</replaceable></term>
+ <listitem>
+ <para>
+ When generating an NSEC3 chain, use this many iterations. The
+ default is 10.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A</term>
+ <listitem>
+ <para>
+ When generating an NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </para>
+ <para>
+ Using this option twice (i.e., <option>-AA</option>)
+ turns the OPTOUT flag off for all records. This is useful
+ when using the <option>-u</option> option to modify an NSEC3
+ chain which previously had OPTOUT set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zonefile</term>
+ <listitem>
+ <para>
+ The file containing the zone to be signed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>key</term>
+ <listitem>
+ <para>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>EXAMPLE</title></info>
+
+ <para>
+ The following command signs the <userinput>example.com</userinput>
+ zone with the DSA key generated by <command>dnssec-keygen</command>
+ (Kexample.com.+003+17247). Because the <command>-S</command> option
+ is not being used, the zone's keys must be in the master file
+ (<filename>db.example.com</filename>). This invocation looks
+ for <filename>dsset</filename> files, in the current directory,
+ so that DS records can be imported from them (<command>-g</command>).
+ </para>
+<programlisting>% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</programlisting>
+ <para>
+ In the above example, <command>dnssec-signzone</command> creates
+ the file <filename>db.example.com.signed</filename>. This
+ file should be referenced in a zone statement in a
+ <filename>named.conf</filename> file.
+ </para>
+ <para>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </para>
+<programlisting>% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</programlisting>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 4033</citetitle>, <citetitle>RFC 4641</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-signzone.html b/bin/dnssec/dnssec-signzone.html
new file mode 100644
index 0000000..08ff79a
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.html
@@ -0,0 +1,674 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2009, 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-signzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-signzone"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-signzone</span>
+ &#8212; DNSSEC zone signing tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-signzone</code>
+ [<code class="option">-a</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-D</code>]
+ [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>]
+ [<code class="option">-e <em class="replaceable"><code>end-time</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>output-file</code></em></code>]
+ [<code class="option">-g</code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>]
+ [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>]
+ [<code class="option">-j <em class="replaceable"><code>jitter</code></em></code>]
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-k <em class="replaceable"><code>key</code></em></code>]
+ [<code class="option">-L <em class="replaceable"><code>serial</code></em></code>]
+ [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>]
+ [<code class="option">-M <em class="replaceable"><code>maxttl</code></em></code>]
+ [<code class="option">-N <em class="replaceable"><code>soa-serial-format</code></em></code>]
+ [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>]
+ [<code class="option">-O <em class="replaceable"><code>output-format</code></em></code>]
+ [<code class="option">-P</code>]
+ [<code class="option">-p</code>]
+ [<code class="option">-Q</code>]
+ [<code class="option">-R</code>]
+ [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>]
+ [<code class="option">-S</code>]
+ [<code class="option">-s <em class="replaceable"><code>start-time</code></em></code>]
+ [<code class="option">-T <em class="replaceable"><code>ttl</code></em></code>]
+ [<code class="option">-t</code>]
+ [<code class="option">-u</code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-X <em class="replaceable"><code>extended end-time</code></em></code>]
+ [<code class="option">-x</code>]
+ [<code class="option">-z</code>]
+ [<code class="option">-3 <em class="replaceable"><code>salt</code></em></code>]
+ [<code class="option">-H <em class="replaceable"><code>iterations</code></em></code>]
+ [<code class="option">-A</code>]
+ {zonefile}
+ [key...]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-signzone</strong></span>
+ 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 or not) is
+ determined by the presence or absence of a
+ <code class="filename">keyset</code> file for each child zone.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a</span></dt>
+<dd>
+ <p>
+ Verify all generated signatures.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the DNS class of the zone.
+ </p>
+ </dd>
+<dt><span class="term">-C</span></dt>
+<dd>
+ <p>
+ Compatibility mode: Generate a
+ <code class="filename">keyset-<em class="replaceable"><code>zonename</code></em></code>
+ file in addition to
+ <code class="filename">dsset-<em class="replaceable"><code>zonename</code></em></code>
+ when signing a zone, for use by older versions of
+ <span class="command"><strong>dnssec-signzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Look for <code class="filename">dsset-</code> or
+ <code class="filename">keyset-</code> files in <code class="option">directory</code>.
+ </p>
+ </dd>
+<dt><span class="term">-D</span></dt>
+<dd>
+ <p>
+ Output only those record types automatically managed by
+ <span class="command"><strong>dnssec-signzone</strong></span>, i.e. RRSIG, NSEC,
+ NSEC3 and NSEC3PARAM records. If smart signing
+ (<code class="option">-S</code>) is used, DNSKEY records are also
+ included. The resulting file can be included in the original
+ zone file with <span class="command"><strong>$INCLUDE</strong></span>. This option
+ cannot be combined with <code class="option">-O raw</code>,
+ <code class="option">-O map</code>, or serial number updating.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt>
+<dd>
+ <p>
+ When applicable, specifies the hardware to use for
+ cryptographic operations, such as a secure key store used
+ for signing.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+<dt><span class="term">-g</span></dt>
+<dd>
+ <p>
+ Generate DS records for child zones from
+ <code class="filename">dsset-</code> or <code class="filename">keyset-</code>
+ file. Existing DS records will be removed.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Key repository: Specify a directory to search for DNSSEC keys.
+ If not specified, defaults to the current directory.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>key</code></em></span></dt>
+<dd>
+ <p>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </p>
+ </dd>
+<dt><span class="term">-M <em class="replaceable"><code>maxttl</code></em></span></dt>
+<dd>
+ <p>
+ Sets the maximum TTL for the signed zone.
+ Any TTL higher than <em class="replaceable"><code>maxttl</code></em> in the
+ input zone will be reduced to <em class="replaceable"><code>maxttl</code></em>
+ in the output. This provides certainty as to the largest
+ possible TTL in the signed zone, which is useful to know when
+ rolling keys because it is the longest possible time before
+ signatures that have been retrieved by resolvers will expire
+ from resolver caches. Zones that are signed with this
+ option should be configured to use a matching
+ <code class="option">max-zone-ttl</code> in <code class="filename">named.conf</code>.
+ (Note: This option is incompatible with <code class="option">-D</code>,
+ because it modifies non-DNSSEC data in the output zone.)
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>start-time</code></em></span></dt>
+<dd>
+ <p>
+ Specify 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 <code class="option">start-time</code> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </p>
+ </dd>
+<dt><span class="term">-e <em class="replaceable"><code>end-time</code></em></span></dt>
+<dd>
+ <p>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <code class="option">start-time</code>, 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 <code class="option">end-time</code> is
+ specified, 30 days from the start time is used as a default.
+ <code class="option">end-time</code> must be later than
+ <code class="option">start-time</code>.
+ </p>
+ </dd>
+<dt><span class="term">-X <em class="replaceable"><code>extended end-time</code></em></span></dt>
+<dd>
+ <p>
+ Specify the date and time when the generated RRSIG records
+ for the DNSKEY RRset will 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.
+ </p>
+ <p>
+ As with <code class="option">start-time</code>, 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 <code class="option">extended end-time</code> is
+ specified, the value of <code class="option">end-time</code> is used as
+ the default. (<code class="option">end-time</code>, in turn, defaults to
+ 30 days from the start time.) <code class="option">extended end-time</code>
+ must be later than <code class="option">start-time</code>.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>output-file</code></em></span></dt>
+<dd>
+ <p>
+ The name of the output file containing the signed zone. The
+ default is to append <code class="filename">.signed</code> to
+ the input filename. If <code class="option">output-file</code> is
+ set to <code class="literal">"-"</code>, then the signed zone is
+ written to the standard output, with a default output
+ format of "full".
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Prints a short summary of the options and arguments to
+ <span class="command"><strong>dnssec-signzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+ <p>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <code class="option">interval</code> 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 will be replaced.
+ </p>
+ <p>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <code class="option">end-time</code> or <code class="option">start-time</code>
+ are specified, <span class="command"><strong>dnssec-signzone</strong></span>
+ 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 would be
+ replaced.
+ </p>
+ </dd>
+<dt><span class="term">-I <em class="replaceable"><code>input-format</code></em></span></dt>
+<dd>
+ <p>
+ The format of the input zone file.
+ Possible formats are <span class="command"><strong>"text"</strong></span> (default),
+ <span class="command"><strong>"raw"</strong></span>, and <span class="command"><strong>"map"</strong></span>.
+ 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.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </p>
+ </dd>
+<dt><span class="term">-j <em class="replaceable"><code>jitter</code></em></span></dt>
+<dd>
+ <p>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <code class="option">jitter</code> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </p>
+ <p>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>serial</code></em></span></dt>
+<dd>
+ <p>
+ When writing a signed zone to "raw" or "map" format, set the
+ "source serial" value in the header to the specified serial
+ number. (This is expected to be used primarily for testing
+ purposes.)
+ </p>
+ </dd>
+<dt><span class="term">-n <em class="replaceable"><code>ncpus</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </p>
+ </dd>
+<dt><span class="term">-N <em class="replaceable"><code>soa-serial-format</code></em></span></dt>
+<dd>
+ <p>
+ The SOA serial number format of the signed zone.
+ Possible formats are <span class="command"><strong>"keep"</strong></span> (default),
+ <span class="command"><strong>"increment"</strong></span>, <span class="command"><strong>"unixtime"</strong></span>,
+ and <span class="command"><strong>"date"</strong></span>.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><span class="command"><strong>"keep"</strong></span></span></dt>
+<dd>
+ <p>Do not modify the SOA serial number.</p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>"increment"</strong></span></span></dt>
+<dd>
+ <p>Increment the SOA serial number using RFC 1982
+ arithmetics.</p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>"unixtime"</strong></span></span></dt>
+<dd>
+ <p>Set the SOA serial number to the number of seconds
+ since epoch.</p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>"date"</strong></span></span></dt>
+<dd>
+ <p>Set the SOA serial number to today's date in
+ YYYYMMDDNN format.</p>
+ </dd>
+</dl></div>
+
+ </dd>
+<dt><span class="term">-o <em class="replaceable"><code>origin</code></em></span></dt>
+<dd>
+ <p>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </p>
+ </dd>
+<dt><span class="term">-O <em class="replaceable"><code>output-format</code></em></span></dt>
+<dd>
+ <p>
+ The format of the output file containing the signed zone.
+ Possible formats are <span class="command"><strong>"text"</strong></span> (default),
+ which is the standard textual representation of the zone;
+ <span class="command"><strong>"full"</strong></span>, which is text output in a
+ format suitable for processing by external scripts;
+ and <span class="command"><strong>"map"</strong></span>, <span class="command"><strong>"raw"</strong></span>,
+ and <span class="command"><strong>"raw=N"</strong></span>, which store the zone in
+ binary formats for rapid loading by <span class="command"><strong>named</strong></span>.
+ <span class="command"><strong>"raw=N"</strong></span> specifies the format version of
+ the raw zone file: if N is 0, the raw file can be read by
+ any version of <span class="command"><strong>named</strong></span>; if N is 1, the file
+ can be read by release 9.9.0 or higher; the default is 1.
+ </p>
+ </dd>
+<dt><span class="term">-p</span></dt>
+<dd>
+ <p>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </p>
+ </dd>
+<dt><span class="term">-P</span></dt>
+<dd>
+ <p>
+ Disable post sign verification tests.
+ </p>
+ <p>
+ The post sign verification test ensures 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.
+ </p>
+ </dd>
+<dt><span class="term">-Q</span></dt>
+<dd>
+ <p>
+ Remove signatures from keys that are no longer active.
+ </p>
+ <p>
+ 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 <code class="option">-Q</code>
+ forces <span class="command"><strong>dnssec-signzone</strong></span> to remove
+ signatures from keys that are no longer active. This
+ enables ZSK rollover using the procedure described in
+ RFC 4641, section 4.2.1.1 ("Pre-Publish Key Rollover").
+ </p>
+ </dd>
+<dt><span class="term">-R</span></dt>
+<dd>
+ <p>
+ Remove signatures from keys that are no longer published.
+ </p>
+ <p>
+ This option is similar to <code class="option">-Q</code>, except it
+ forces <span class="command"><strong>dnssec-signzone</strong></span> to signatures from
+ keys that are no longer published. This enables ZSK rollover
+ using the procedure described in RFC 4641, section 4.2.1.2
+ ("Double Signature Zone Signing Key Rollover").
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p>
+ </dd>
+<dt><span class="term">-S</span></dt>
+<dd>
+ <p>
+ Smart signing: Instructs <span class="command"><strong>dnssec-signzone</strong></span> to
+ search the key repository for keys that match the zone being
+ signed, and to include them in the zone if appropriate.
+ </p>
+ <p>
+ 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:
+ </p>
+ <div class="variablelist"><dl class="variablelist">
+<dt></dt>
+<dd>
+ <p>
+ If no timing metadata has been set for the key, the key is
+ published in the zone and used to sign the zone.
+ </p>
+ </dd>
+<dt></dt>
+<dd>
+ <p>
+ If the key's publication date is set and is in the past, the
+ key is published in the zone.
+ </p>
+ </dd>
+<dt></dt>
+<dd>
+ <p>
+ If the key's activation date is set and in the past, the
+ key is published (regardless of publication date) and
+ used to sign the zone.
+ </p>
+ </dd>
+<dt></dt>
+<dd>
+ <p>
+ If the key's revocation date is set and in the past, and the
+ key is published, then the key is revoked, and the revoked key
+ is used to sign the zone.
+ </p>
+ </dd>
+<dt></dt>
+<dd>
+ <p>
+ If either of the key's unpublication or deletion dates are set
+ and in the past, the key is NOT published or used to sign the
+ zone, regardless of any other metadata.
+ </p>
+ </dd>
+</dl></div>
+ </dd>
+<dt><span class="term">-T <em class="replaceable"><code>ttl</code></em></span></dt>
+<dd>
+ <p>
+ 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
+ <code class="option">-S</code>, 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 will be set to match
+ them, or if any of the imported DNSKEY records had a default
+ TTL value. In the event of a a conflict between TTL values in
+ imported keys, the shortest one is used.
+ </p>
+ </dd>
+<dt><span class="term">-t</span></dt>
+<dd>
+ <p>
+ Print statistics at completion.
+ </p>
+ </dd>
+<dt><span class="term">-u</span></dt>
+<dd>
+ <p>
+ Update 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 switch to NSEC or to NSEC3 with different parameters.
+ Without this option, <span class="command"><strong>dnssec-signzone</strong></span> will
+ retain the existing chain when re-signing.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-x</span></dt>
+<dd>
+ <p>
+ Only sign the DNSKEY RRset with key-signing keys, and omit
+ signatures from zone-signing keys. (This is similar to the
+ <span class="command"><strong>dnssec-dnskey-kskonly yes;</strong></span> zone option in
+ <span class="command"><strong>named</strong></span>.)
+ </p>
+ </dd>
+<dt><span class="term">-z</span></dt>
+<dd>
+ <p>
+ Ignore KSK flag on key when determining what to sign. This
+ causes KSK-flagged keys to sign all records, not just the
+ DNSKEY RRset. (This is similar to the
+ <span class="command"><strong>update-check-ksk no;</strong></span> zone option in
+ <span class="command"><strong>named</strong></span>.)
+ </p>
+ </dd>
+<dt><span class="term">-3 <em class="replaceable"><code>salt</code></em></span></dt>
+<dd>
+ <p>
+ Generate an NSEC3 chain with the given hex encoded salt.
+ A dash (<em class="replaceable"><code>salt</code></em>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </p>
+ </dd>
+<dt><span class="term">-H <em class="replaceable"><code>iterations</code></em></span></dt>
+<dd>
+ <p>
+ When generating an NSEC3 chain, use this many iterations. The
+ default is 10.
+ </p>
+ </dd>
+<dt><span class="term">-A</span></dt>
+<dd>
+ <p>
+ When generating an NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </p>
+ <p>
+ Using this option twice (i.e., <code class="option">-AA</code>)
+ turns the OPTOUT flag off for all records. This is useful
+ when using the <code class="option">-u</code> option to modify an NSEC3
+ chain which previously had OPTOUT set.
+ </p>
+ </dd>
+<dt><span class="term">zonefile</span></dt>
+<dd>
+ <p>
+ The file containing the zone to be signed.
+ </p>
+ </dd>
+<dt><span class="term">key</span></dt>
+<dd>
+ <p>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>EXAMPLE</h2>
+
+ <p>
+ The following command signs the <strong class="userinput"><code>example.com</code></strong>
+ zone with the DSA key generated by <span class="command"><strong>dnssec-keygen</strong></span>
+ (Kexample.com.+003+17247). Because the <span class="command"><strong>-S</strong></span> option
+ is not being used, the zone's keys must be in the master file
+ (<code class="filename">db.example.com</code>). This invocation looks
+ for <code class="filename">dsset</code> files, in the current directory,
+ so that DS records can be imported from them (<span class="command"><strong>-g</strong></span>).
+ </p>
+<pre class="programlisting">% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</pre>
+ <p>
+ In the above example, <span class="command"><strong>dnssec-signzone</strong></span> creates
+ the file <code class="filename">db.example.com.signed</code>. This
+ file should be referenced in a zone statement in a
+ <code class="filename">named.conf</code> file.
+ </p>
+ <p>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </p>
+<pre class="programlisting">% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</pre>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 4033</em>, <em class="citetitle">RFC 4641</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-verify.8 b/bin/dnssec/dnssec-verify.8
new file mode 100644
index 0000000..592dd08
--- /dev/null
+++ b/bin/dnssec/dnssec-verify.8
@@ -0,0 +1,117 @@
+.\" Copyright (C) 2012, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-verify
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-15
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-VERIFY" "8" "2014\-01\-15" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-verify \- DNSSEC zone verification tool
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-verify\fR\ 'u
+\fBdnssec\-verify\fR [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-x\fR] [\fB\-z\fR] {zonefile}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-verify\fR
+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\&.
+.SH "OPTIONS"
+.PP
+\-c \fIclass\fR
+.RS 4
+Specifies the DNS class of the zone\&.
+.RE
+.PP
+\-E \fIengine\fR
+.RS 4
+Specifies the cryptographic hardware to use, when applicable\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.PP
+\-I \fIinput\-format\fR
+.RS 4
+The format of the input zone file\&. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR\&. 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\&. The use of this option does not make much sense for non\-dynamic zones\&.
+.RE
+.PP
+\-o \fIorigin\fR
+.RS 4
+The zone origin\&. If not specified, the name of the zone file is assumed to be the origin\&.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level\&.
+.RE
+.PP
+\-V
+.RS 4
+Prints version information\&.
+.RE
+.PP
+\-x
+.RS 4
+Only verify that the DNSKEY RRset is signed with key\-signing keys\&. Without this flag, it is assumed that the DNSKEY RRset will be signed by all active keys\&. When this flag is set, it will not be an error if the DNSKEY RRset is not signed by zone\-signing keys\&. This corresponds to the
+\fB\-x\fR
+option in
+\fBdnssec\-signzone\fR\&.
+.RE
+.PP
+\-z
+.RS 4
+Ignore the KSK flag on the keys when determining whether the zone if correctly signed\&. Without this flag it is assumed that there will be a non\-revoked, self\-signed DNSKEY with the KSK flag set for each algorithm and that RRsets other than DNSKEY RRset will be signed with a different DNSKEY without the KSK flag set\&.
+.sp
+With this flag set, we only require that for each algorithm, there will be at least one non\-revoked, self\-signed DNSKEY, regardless of the KSK flag state, and that other RRsets will 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
+\fB\-z\fR
+option in
+\fBdnssec\-signzone\fR\&.
+.RE
+.PP
+zonefile
+.RS 4
+The file containing the zone to be signed\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 4033\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2012, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-verify.c b/bin/dnssec/dnssec-verify.c
new file mode 100644
index 0000000..4c293bf
--- /dev/null
+++ b/bin/dnssec/dnssec-verify.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/base32.h>
+#include <isc/commandline.h>
+#include <isc/entropy.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/rwlock.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/stdlib.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/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+
+#include <dst/dst.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-verify";
+int verbose;
+
+static isc_stdtime_t now;
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = 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;
+
+/*%
+ * 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_load2(*db, file, inputformat);
+ 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));
+ }
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+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", VERSION);
+
+ fprintf(stderr, "Options: (default value in parenthesis) \n");
+ fprintf(stderr, "\t-v debuglevel (0)\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");
+#if defined(PKCS11CRYPTO)
+ fprintf(stderr, "\t\tpath to PKCS#11 provider library "
+ "(default is %s)\n", PK11_LIB_LOCATION);
+#elif defined(USE_PKCS11)
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+#else
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
+#endif
+ 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;
+#ifdef USE_PKCS11
+ const char *engine = PKCS11_ENGINE;
+#else
+ const char *engine = NULL;
+#endif
+ char *classname = NULL;
+ dns_rdataclass_t rdclass;
+ char *endp;
+ int ch;
+
+#define CMDLINE_FLAGS \
+ "hm:o:I:c:E:v: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;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+ check_result(isc_app_start(), "isc_app_start");
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ 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 '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);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create hash context");
+
+ result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING);
+ 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;
+ fprintf(stderr, "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()");
+
+ verifyzone(gdb, gversion, gorigin, mctx,
+ ignore_kskflag, keyset_kskonly);
+
+ dns_db_closeversion(gdb, &gversion, false);
+ dns_db_detach(&gdb);
+
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ (void) isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-verify.docbook b/bin/dnssec/dnssec-verify.docbook
new file mode 100644
index 0000000..9d7c746
--- /dev/null
+++ b/bin/dnssec/dnssec-verify.docbook
@@ -0,0 +1,203 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-verify">
+ <info>
+ <date>2014-01-15</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-verify</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-verify</application></refname>
+ <refpurpose>DNSSEC zone verification tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2012</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-verify</command>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">input-format</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-z</option></arg>
+ <arg choice="req" rep="norepeat">zonefile</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-verify</command>
+ 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.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class of the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the cryptographic hardware to use, when applicable.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">input-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the input zone file.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ 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.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-o <replaceable class="parameter">origin</replaceable></term>
+ <listitem>
+ <para>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Prints version information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x</term>
+ <listitem>
+ <para>
+ Only verify that the DNSKEY RRset is signed with key-signing
+ keys. Without this flag, it is assumed that the DNSKEY RRset
+ will be signed by all active keys. When this flag is set,
+ it will not be an error if the DNSKEY RRset is not signed
+ by zone-signing keys. This corresponds to the <option>-x</option>
+ option in <command>dnssec-signzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Ignore the KSK flag on the keys when determining whether
+ the zone if correctly signed. Without this flag it is
+ assumed that there will be a non-revoked, self-signed
+ DNSKEY with the KSK flag set for each algorithm and
+ that RRsets other than DNSKEY RRset will be signed with
+ a different DNSKEY without the KSK flag set.
+ </para>
+ <para>
+ With this flag set, we only require that for each algorithm,
+ there will be at least one non-revoked, self-signed DNSKEY,
+ regardless of the KSK flag state, and that other RRsets
+ will 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>
+ option in <command>dnssec-signzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zonefile</term>
+ <listitem>
+ <para>
+ The file containing the zone to be signed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dnssec/dnssec-verify.html b/bin/dnssec/dnssec-verify.html
new file mode 100644
index 0000000..aff7f84
--- /dev/null
+++ b/bin/dnssec/dnssec-verify.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2012, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-verify</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-verify"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-verify</span>
+ &#8212; DNSSEC zone verification tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-verify</code>
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>]
+ [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>]
+ [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>]
+ [<code class="option">-v <em class="replaceable"><code>level</code></em></code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-x</code>]
+ [<code class="option">-z</code>]
+ {zonefile}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-verify</strong></span>
+ 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.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the DNS class of the zone.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt>
+<dd>
+ <p>
+ Specifies the cryptographic hardware to use, when applicable.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+<dt><span class="term">-I <em class="replaceable"><code>input-format</code></em></span></dt>
+<dd>
+ <p>
+ The format of the input zone file.
+ Possible formats are <span class="command"><strong>"text"</strong></span> (default)
+ and <span class="command"><strong>"raw"</strong></span>.
+ 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.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </p>
+ </dd>
+<dt><span class="term">-o <em class="replaceable"><code>origin</code></em></span></dt>
+<dd>
+ <p>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </p>
+ </dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Sets the debugging level.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Prints version information.
+ </p>
+ </dd>
+<dt><span class="term">-x</span></dt>
+<dd>
+ <p>
+ Only verify that the DNSKEY RRset is signed with key-signing
+ keys. Without this flag, it is assumed that the DNSKEY RRset
+ will be signed by all active keys. When this flag is set,
+ it will not be an error if the DNSKEY RRset is not signed
+ by zone-signing keys. This corresponds to the <code class="option">-x</code>
+ option in <span class="command"><strong>dnssec-signzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-z</span></dt>
+<dd>
+ <p>
+ Ignore the KSK flag on the keys when determining whether
+ the zone if correctly signed. Without this flag it is
+ assumed that there will be a non-revoked, self-signed
+ DNSKEY with the KSK flag set for each algorithm and
+ that RRsets other than DNSKEY RRset will be signed with
+ a different DNSKEY without the KSK flag set.
+ </p>
+ <p>
+ With this flag set, we only require that for each algorithm,
+ there will be at least one non-revoked, self-signed DNSKEY,
+ regardless of the KSK flag state, and that other RRsets
+ will 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 <code class="option">-z</code>
+ option in <span class="command"><strong>dnssec-signzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">zonefile</span></dt>
+<dd>
+ <p>
+ The file containing the zone to be signed.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c
new file mode 100644
index 0000000..fbc7ece
--- /dev/null
+++ b/bin/dnssec/dnssectool.c
@@ -0,0 +1,1934 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/*%
+ * DNSSEC Support Routines.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <Winsock2.h>
+#endif
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/heap.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/time.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/rdatastruct.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/time.h>
+
+#include "dnssectool.h"
+
+static isc_heap_t *expected_chains, *found_chains;
+
+struct nsec3_chain_fixed {
+ uint8_t hash;
+ uint8_t salt_length;
+ uint8_t next_length;
+ uint16_t iterations;
+ /* unsigned char salt[0]; */
+ /* unsigned char owner[0]; */
+ /* unsigned char next[0]; */
+};
+
+extern int verbose;
+extern const char *program;
+
+typedef struct entropysource entropysource_t;
+
+struct entropysource {
+ isc_entropysource_t *source;
+ isc_mem_t *mctx;
+ ISC_LINK(entropysource_t) link;
+};
+
+static ISC_LIST(entropysource_t) sources;
+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, VERSION);
+ exit(0);
+}
+
+void
+type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_result_t result;
+
+ isc_buffer_init(&b, cp, size - 1);
+ result = dns_rdatatype_totext(type, &b);
+ check_result(result, "dns_rdatatype_totext()");
+ isc_buffer_usedregion(&b, &r);
+ r.base[r.length] = 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_result_t result;
+ 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;
+ }
+
+ RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+
+ RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
+
+ /*
+ * 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;
+ result = isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC,
+ level,
+ &destination,
+ ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
+ check_result(result, "isc_log_createchannel()");
+
+ 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);
+}
+
+void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
+ isc_result_t result;
+ isc_entropysource_t *source = NULL;
+ entropysource_t *elt;
+ int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
+
+ REQUIRE(ectx != NULL);
+
+ if (*ectx == NULL) {
+ result = isc_entropy_create(mctx, ectx);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create entropy object");
+ ISC_LIST_INIT(sources);
+ }
+
+ if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+ usekeyboard = ISC_ENTROPY_KEYBOARDYES;
+ randomfile = NULL;
+ }
+
+ result = isc_entropy_usebestsource(*ectx, &source, randomfile,
+ usekeyboard);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize entropy source: %s",
+ isc_result_totext(result));
+
+ if (source != NULL) {
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ fatal("out of memory");
+ elt->source = source;
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ ISC_LIST_APPEND(sources, elt, link);
+ }
+}
+
+void
+cleanup_entropy(isc_entropy_t **ectx) {
+ entropysource_t *source;
+ while (!ISC_LIST_EMPTY(sources)) {
+ source = ISC_LIST_HEAD(sources);
+ ISC_LIST_UNLINK(sources, source, link);
+ isc_entropy_destroysource(&source->source);
+ isc_mem_put(source->mctx, source, sizeof(*source));
+ }
+ isc_entropy_detach(ectx);
+}
+
+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);
+ }
+ /* NOTREACHED */
+ 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);
+ }
+ /* NOTREACHED */
+ return(0); /* silence compiler warning */
+}
+
+static inline bool
+isnone(const char *str) {
+ return ((strcasecmp(str, "none") == 0) ||
+ (strcasecmp(str, "never") == 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);
+}
+
+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;
+
+ 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)
+ * [+-]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 (strncmp(str, "now", 3) == 0) {
+ base = now;
+ str += 3;
+ }
+
+ 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 ret;
+
+ if (str == NULL)
+ return dns_rdataclass_in;
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+ ret = dns_rdataclass_fromtext(&rdclass, &r);
+ if (ret != ISC_R_SUCCESS)
+ fatal("unknown class %s", str);
+ return (rdclass);
+}
+
+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[ISC_DIR_NAMEMAX];
+ isc_buffer_t fileb;
+
+ if (exact != NULL)
+ *exact = false;
+
+ id = dst_key_id(dstkey);
+ rid = dst_key_rid(dstkey);
+ alg = dst_key_alg(dstkey);
+
+ /*
+ * For HMAC and 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.
+ */
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ case DST_ALG_HMACSHA1:
+ case DST_ALG_HMACSHA224:
+ case DST_ALG_HMACSHA256:
+ case DST_ALG_HMACSHA384:
+ case DST_ALG_HMACSHA512:
+ case 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);
+ result = dns_dnssec_findmatchingkeys(name, dir, 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
+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);
+}
+
+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);
+}
+
+static bool
+goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name,
+ dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx)
+{
+ dns_rdata_dnskey_t key;
+ dns_rdata_rrsig_t sig;
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+
+ result = dns_rdata_tostruct(sigrdata, &sig, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+
+ for (result = dns_rdataset_first(keyrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(keyrdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(keyrdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &key, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ result = dns_dnssec_keyfromrdata(origin, &rdata, mctx,
+ &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (false);
+ if (sig.algorithm != key.algorithm ||
+ sig.keyid != dst_key_id(dstkey) ||
+ !dns_name_equal(&sig.signer, origin)) {
+ dst_key_free(&dstkey);
+ continue;
+ }
+ result = dns_dnssec_verify(name, rdataset, dstkey, false,
+ mctx, sigrdata);
+ dst_key_free(&dstkey);
+ if (result == ISC_R_SUCCESS)
+ return(true);
+ }
+ return (false);
+}
+
+static bool
+nsec_bitmap_equal(dns_rdata_nsec_t *nsec, dns_rdata_t *rdata) {
+ isc_result_t result;
+ dns_rdata_nsec_t tmpnsec;
+
+ result = dns_rdata_tostruct(rdata, &tmpnsec, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (nsec->len != tmpnsec.len ||
+ memcmp(nsec->typebits, tmpnsec.typebits, nsec->len) != 0) {
+ return (false);
+ }
+ return (true);
+}
+
+static isc_result_t
+verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_dbnode_t *node, dns_name_t *nextname)
+{
+ unsigned char buffer[DNS_NSEC_BUFFERSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char nextbuf[DNS_NAME_FORMATSIZE];
+ char found[DNS_NAME_FORMATSIZE];
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t tmprdata = DNS_RDATA_INIT;
+ dns_rdata_nsec_t nsec;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "Missing NSEC record for %s\n", namebuf);
+ goto failure;
+ }
+
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first()");
+
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ /* Check bit next name is consistent */
+ if (!dns_name_equal(&nsec.next, nextname)) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_name_format(nextname, nextbuf, sizeof(nextbuf));
+ dns_name_format(&nsec.next, found, sizeof(found));
+ fprintf(stderr, "Bad NSEC record for %s, next name "
+ "mismatch (expected:%s, found:%s)\n", namebuf,
+ nextbuf, found);
+ goto failure;
+ }
+ /* Check bit map is consistent */
+ result = dns_nsec_buildrdata(db, ver, node, nextname, buffer,
+ &tmprdata);
+ check_result(result, "dns_nsec_buildrdata()");
+ if (!nsec_bitmap_equal(&nsec, &tmprdata)) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "Bad NSEC record for %s, bit map "
+ "mismatch\n", namebuf);
+ goto failure;
+ }
+ result = dns_rdataset_next(&rdataset);
+ if (result != ISC_R_NOMORE) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "Multipe NSEC records for %s\n", namebuf);
+ goto failure;
+
+ }
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_R_SUCCESS);
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_R_FAILURE);
+}
+
+static void
+check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset,
+ dns_name_t *name, dns_dbnode_t *node)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[80];
+ dns_rdataset_t sigrdataset;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ isc_result_t result;
+
+ dns_rdataset_init(&sigrdataset);
+ result = dns_db_allrdatasets(db, node, ver, 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, &sigrdataset);
+ if (sigrdataset.type == dns_rdatatype_rrsig &&
+ sigrdataset.covers == rdataset->type)
+ break;
+ dns_rdataset_disassociate(&sigrdataset);
+ }
+ if (result == ISC_R_SUCCESS) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ type_format(rdataset->type, typebuf, sizeof(typebuf));
+ fprintf(stderr, "Warning: Found unexpected signatures for "
+ "%s/%s\n", namebuf, typebuf);
+ }
+ if (dns_rdataset_isassociated(&sigrdataset))
+ dns_rdataset_disassociate(&sigrdataset);
+ dns_rdatasetiter_destroy(&rdsiter);
+}
+
+static bool
+chain_compare(void *arg1, void *arg2) {
+ struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
+ size_t len;
+
+ /*
+ * Do each element in turn to get a stable sort.
+ */
+ if (e1->hash < e2->hash)
+ return (true);
+ if (e1->hash > e2->hash)
+ return (false);
+ if (e1->iterations < e2->iterations)
+ return (true);
+ if (e1->iterations > e2->iterations)
+ return (false);
+ if (e1->salt_length < e2->salt_length)
+ return (true);
+ if (e1->salt_length > e2->salt_length)
+ return (false);
+ if (e1->next_length < e2->next_length)
+ return (true);
+ if (e1->next_length > e2->next_length)
+ return (false);
+ len = e1->salt_length + 2 * e1->next_length;
+ if (memcmp(e1 + 1, e2 + 1, len) < 0)
+ return (true);
+ return (false);
+}
+
+static bool
+chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) {
+ size_t len;
+
+ if (e1->hash != e2->hash)
+ return (false);
+ if (e1->iterations != e2->iterations)
+ return (false);
+ if (e1->salt_length != e2->salt_length)
+ return (false);
+ if (e1->next_length != e2->next_length)
+ return (false);
+ len = e1->salt_length + 2 * e1->next_length;
+ if (memcmp(e1 + 1, e2 + 1, len) != 0)
+ return (false);
+ return (true);
+}
+
+static isc_result_t
+record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3,
+ isc_mem_t *mctx, isc_heap_t *chains)
+{
+ struct nsec3_chain_fixed *element;
+ size_t len;
+ unsigned char *cp;
+ isc_result_t result;
+
+ len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
+
+ element = isc_mem_get(mctx, len);
+ if (element == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(element, 0, len);
+ element->hash = nsec3->hash;
+ element->salt_length = nsec3->salt_length;
+ element->next_length = nsec3->next_length;
+ element->iterations = nsec3->iterations;
+ cp = (unsigned char *)(element + 1);
+ memmove(cp, nsec3->salt, nsec3->salt_length);
+ cp += nsec3->salt_length;
+ memmove(cp, rawhash, nsec3->next_length);
+ cp += nsec3->next_length;
+ memmove(cp, nsec3->next, nsec3->next_length);
+ result = isc_heap_insert(chains, element);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_heap_insert failed: %s\n",
+ isc_result_totext(result));
+ isc_mem_put(mctx, element, len);
+ }
+ return (result);
+}
+
+static isc_result_t
+match_nsec3(dns_name_t *name, isc_mem_t *mctx,
+ dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
+ unsigned char types[8192], unsigned int maxtype,
+ unsigned char *rawhash, size_t rhsize)
+{
+ unsigned char cbm[8244];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_rdata_nsec3_t nsec3;
+ isc_result_t result;
+ unsigned int len;
+
+ /*
+ * Find matching NSEC3 record.
+ */
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ if (nsec3.hash == nsec3param->hash &&
+ nsec3.next_length == rhsize &&
+ nsec3.iterations == nsec3param->iterations &&
+ nsec3.salt_length == nsec3param->salt_length &&
+ memcmp(nsec3.salt, nsec3param->salt,
+ nsec3param->salt_length) == 0)
+ break;
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf);
+ return (result);
+ }
+
+ /*
+ * Check the type list.
+ */
+ len = dns_nsec_compressbitmap(cbm, types, maxtype);
+ if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "Bad NSEC3 record for %s, bit map "
+ "mismatch\n", namebuf);
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * Record chain.
+ */
+ result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
+ check_result(result, "record_nsec3()");
+
+ /*
+ * Make sure there is only one NSEC3 record with this set of
+ * parameters.
+ */
+ for (result = dns_rdataset_next(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ if (nsec3.hash == nsec3param->hash &&
+ nsec3.iterations == nsec3param->iterations &&
+ nsec3.salt_length == nsec3param->salt_length &&
+ memcmp(nsec3.salt, nsec3param->salt,
+ nsec3.salt_length) == 0) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "Multiple NSEC3 records with the "
+ "same parameter set for %s", namebuf);
+ result = DNS_R_DUPLICATE;
+ break;
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+static bool
+innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
+ dns_rdata_nsec3param_t nsec3param;
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(nsec3paramset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(nsec3paramset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(nsec3paramset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ if (nsec3param.flags == 0 &&
+ nsec3param.hash == nsec3->hash &&
+ nsec3param.iterations == nsec3->iterations &&
+ nsec3param.salt_length == nsec3->salt_length &&
+ memcmp(nsec3param.salt, nsec3->salt,
+ nsec3->salt_length) == 0)
+ return (true);
+ }
+ return (false);
+}
+
+static isc_result_t
+record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
+ dns_name_t *name, dns_dbnode_t *node,
+ dns_rdataset_t *nsec3paramset)
+{
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ dns_rdata_nsec3_t nsec3;
+ dns_rdataset_t rdataset;
+ dns_label_t hashlabel;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
+ return (ISC_R_SUCCESS);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ dns_name_getlabel(name, 0, &hashlabel);
+ isc_region_consume(&hashlabel, 1);
+ isc_buffer_init(&b, owner, sizeof(owner));
+ result = isc_base32hex_decoderegion(&hashlabel, &b);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ if (nsec3.next_length != isc_buffer_usedlength(&b))
+ continue;
+ /*
+ * We only care about NSEC3 records that match a NSEC3PARAM
+ * record.
+ */
+ if (!innsec3params(&nsec3, nsec3paramset))
+ continue;
+
+ /*
+ * Record chain.
+ */
+ result = record_nsec3(owner, &nsec3, mctx, found_chains);
+ check_result(result, "record_nsec3()");
+ }
+
+ cleanup:
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_R_SUCCESS);
+}
+
+static bool
+isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ dns_rdata_t *nsec3rdata)
+{
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_fixedname_t fixed;
+ dns_name_t *hashname;
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
+ size_t rhsize = sizeof(rawhash);
+ bool ret;
+
+ result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+
+ dns_fixedname_init(&fixed);
+ result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin,
+ nsec3param.hash, nsec3param.iterations,
+ nsec3param.salt, nsec3param.salt_length);
+ check_result(result, "dns_nsec3_hashname()");
+
+ dns_rdataset_init(&rdataset);
+ hashname = dns_fixedname_name(&fixed);
+ result = dns_db_findnsec3node(db, hashname, false, &node);
+ if (result == ISC_R_SUCCESS)
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (false);
+
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first()");
+
+ dns_rdataset_current(&rdataset, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (result != ISC_R_SUCCESS)
+ ret = false;
+ else
+ ret = (nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ return (ret);
+}
+
+static isc_result_t
+verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata,
+ bool delegation, bool empty,
+ unsigned char types[8192], unsigned int maxtype)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char hashbuf[DNS_NAME_FORMATSIZE];
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_fixedname_t fixed;
+ dns_name_t *hashname;
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
+ size_t rhsize = sizeof(rawhash);
+ bool optout;
+
+ result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+
+ if (nsec3param.flags != 0)
+ return (ISC_R_SUCCESS);
+
+ if (!dns_nsec3_supportedhash(nsec3param.hash))
+ return (ISC_R_SUCCESS);
+
+ optout = isoptout(db, ver, origin, rdata);
+
+ dns_fixedname_init(&fixed);
+ result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin,
+ nsec3param.hash, nsec3param.iterations,
+ nsec3param.salt, nsec3param.salt_length);
+ check_result(result, "dns_nsec3_hashname()");
+
+ /*
+ * We don't use dns_db_find() here as it works with the choosen
+ * nsec3 chain and we may also be called with uncommitted data
+ * from dnssec-signzone so the secure status of the zone may not
+ * be up to date.
+ */
+ dns_rdataset_init(&rdataset);
+ hashname = dns_fixedname_name(&fixed);
+ result = dns_db_findnsec3node(db, hashname, false, &node);
+ if (result == ISC_R_SUCCESS)
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS &&
+ (!delegation || (empty && !optout) ||
+ (!empty && dns_nsec_isset(types, dns_rdatatype_ds))))
+ {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_name_format(hashname, hashbuf, sizeof(hashbuf));
+ fprintf(stderr, "Missing NSEC3 record for %s (%s)\n",
+ namebuf, hashbuf);
+ } else if (result == ISC_R_NOTFOUND &&
+ delegation && (!empty || optout))
+ {
+ result = ISC_R_SUCCESS;
+ } else if (result == ISC_R_SUCCESS) {
+ result = match_nsec3(name, mctx, &nsec3param, &rdataset,
+ types, maxtype, rawhash, rhsize);
+ }
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+static isc_result_t
+verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset,
+ bool delegation, bool empty,
+ unsigned char types[8192], unsigned int maxtype)
+{
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(nsec3paramset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(nsec3paramset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(nsec3paramset, &rdata);
+ result = verifynsec3(db, ver, origin, mctx, name, &rdata,
+ delegation, empty, types, maxtype);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+static void
+verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_dbnode_t *node, dns_rdataset_t *keyrdataset,
+ unsigned char *act_algorithms, unsigned char *bad_algorithms)
+{
+ unsigned char set_algorithms[256];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char algbuf[80];
+ char typebuf[80];
+ dns_rdataset_t sigrdataset;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ isc_result_t result;
+ int i;
+
+ dns_rdataset_init(&sigrdataset);
+ result = dns_db_allrdatasets(db, node, ver, 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, &sigrdataset);
+ if (sigrdataset.type == dns_rdatatype_rrsig &&
+ sigrdataset.covers == rdataset->type)
+ break;
+ dns_rdataset_disassociate(&sigrdataset);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ type_format(rdataset->type, typebuf, sizeof(typebuf));
+ fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf);
+ for (i = 0; i < 256; i++)
+ if (act_algorithms[i] != 0)
+ bad_algorithms[i] = 1;
+ dns_rdatasetiter_destroy(&rdsiter);
+ return;
+ }
+
+ memset(set_algorithms, 0, sizeof(set_algorithms));
+ for (result = dns_rdataset_first(&sigrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&sigrdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+
+ dns_rdataset_current(&sigrdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &sig, NULL);
+ check_result(result, "dns_rdata_tostruct()");
+ if (rdataset->ttl != sig.originalttl) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ type_format(rdataset->type, typebuf, sizeof(typebuf));
+ fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
+ namebuf, typebuf, sig.keyid);
+ continue;
+ }
+ if ((set_algorithms[sig.algorithm] != 0) ||
+ (act_algorithms[sig.algorithm] == 0))
+ continue;
+ if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx))
+ set_algorithms[sig.algorithm] = 1;
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ type_format(rdataset->type, typebuf, sizeof(typebuf));
+ for (i = 0; i < 256; i++)
+ if ((act_algorithms[i] != 0) &&
+ (set_algorithms[i] == 0)) {
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, "No correct %s signature for "
+ "%s %s\n", algbuf, namebuf, typebuf);
+ bad_algorithms[i] = 1;
+ }
+ }
+ dns_rdataset_disassociate(&sigrdataset);
+}
+
+static isc_result_t
+verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node,
+ bool delegation, dns_rdataset_t *keyrdataset,
+ unsigned char *act_algorithms, unsigned char *bad_algorithms,
+ dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
+ dns_name_t *nextname)
+{
+ unsigned char types[8192];
+ unsigned int maxtype = 0;
+ dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL;
+ isc_result_t result, tresult;
+
+ memset(types, 0, sizeof(types));
+ result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ dns_rdataset_init(&rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ /*
+ * If we are not at a delegation then everything should be
+ * signed. If we are at a delegation then only the DS set
+ * is signed. The NS set is not signed at a delegation but
+ * its existance is recorded in the bit map. Anything else
+ * other than NSEC and DS is not signed at a delegation.
+ */
+ if (rdataset.type != dns_rdatatype_rrsig &&
+ rdataset.type != dns_rdatatype_dnskey &&
+ (!delegation || rdataset.type == dns_rdatatype_ds ||
+ rdataset.type == dns_rdatatype_nsec)) {
+ verifyset(db, ver, origin, mctx, &rdataset,
+ name, node, keyrdataset,
+ act_algorithms, bad_algorithms);
+ dns_nsec_setbit(types, rdataset.type, 1);
+ if (rdataset.type > maxtype)
+ maxtype = rdataset.type;
+ } else if (rdataset.type != dns_rdatatype_rrsig &&
+ rdataset.type != dns_rdatatype_dnskey) {
+ if (rdataset.type == dns_rdatatype_ns)
+ dns_nsec_setbit(types, rdataset.type, 1);
+ check_no_rrsig(db, ver, &rdataset, name, node);
+ } else
+ dns_nsec_setbit(types, rdataset.type, 1);
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ result = ISC_R_SUCCESS;
+
+ if (nsecset != NULL && dns_rdataset_isassociated(nsecset))
+ result = verifynsec(db, ver, name, node, nextname);
+
+ if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
+ tresult = verifynsec3s(db, ver, origin, mctx, name,
+ nsec3paramset, delegation, false,
+ types, maxtype);
+ if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ return (result);
+}
+
+static bool
+is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ isc_result_t result;
+
+ result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result == ISC_R_NOMORE)
+ return (true);
+ return (false);
+}
+
+static void
+check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db,
+ dns_dbversion_t *ver)
+{
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_NOTFOUND) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fatal("unexpected NSEC RRset at %s\n", namebuf);
+ }
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+}
+
+static bool
+newchain(const struct nsec3_chain_fixed *first,
+ const struct nsec3_chain_fixed *e)
+{
+ if (first->hash != e->hash ||
+ first->iterations != e->iterations ||
+ first->salt_length != e->salt_length ||
+ first->next_length != e->next_length ||
+ memcmp(first + 1, e + 1, first->salt_length) != 0)
+ return (true);
+ return (false);
+}
+
+static void
+free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
+ size_t len;
+
+ len = sizeof(*e) + e->salt_length + 2 * e->next_length;
+ isc_mem_put(mctx, e, len);
+}
+
+static bool
+checknext(const struct nsec3_chain_fixed *first,
+ const struct nsec3_chain_fixed *e)
+{
+ char buf[512];
+ const unsigned char *d1 = (const unsigned char *)(first + 1);
+ const unsigned char *d2 = (const unsigned char *)(e + 1);
+ isc_buffer_t b;
+ isc_region_t sr;
+
+ d1 += first->salt_length + first->next_length;
+ d2 += e->salt_length;
+
+ if (memcmp(d1, d2, first->next_length) == 0)
+ return (true);
+
+ DE_CONST(d1 - first->next_length, sr.base);
+ sr.length = first->next_length;
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_base32hex_totext(&sr, 1, "", &b);
+ fprintf(stderr, "Break in NSEC3 chain at: %.*s\n",
+ (int) isc_buffer_usedlength(&b), buf);
+
+ DE_CONST(d1, sr.base);
+ sr.length = first->next_length;
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_base32hex_totext(&sr, 1, "", &b);
+ fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b),
+ buf);
+
+ DE_CONST(d2, sr.base);
+ sr.length = first->next_length;
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_base32hex_totext(&sr, 1, "", &b);
+ fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf);
+
+ return (false);
+}
+
+#define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
+
+static isc_result_t
+verify_nsec3_chains(isc_mem_t *mctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ struct nsec3_chain_fixed *e, *f = NULL;
+ struct nsec3_chain_fixed *first = NULL, *prev = NULL;
+
+ while ((e = isc_heap_element(expected_chains, 1)) != NULL) {
+ isc_heap_delete(expected_chains, 1);
+ if (f == NULL)
+ f = isc_heap_element(found_chains, 1);
+ if (f != NULL) {
+ isc_heap_delete(found_chains, 1);
+
+ /*
+ * Check that they match.
+ */
+ if (chain_equal(e, f)) {
+ free_element(mctx, f);
+ f = NULL;
+ } else {
+ if (result == ISC_R_SUCCESS)
+ fprintf(stderr, EXPECTEDANDFOUND);
+ result = ISC_R_FAILURE;
+ /*
+ * Attempt to resync found_chain.
+ */
+ while (f != NULL && !chain_compare(e, f)) {
+ free_element(mctx, f);
+ f = isc_heap_element(found_chains, 1);
+ if (f != NULL)
+ isc_heap_delete(found_chains, 1);
+ if (f != NULL && chain_equal(e, f)) {
+ free_element(mctx, f);
+ f = NULL;
+ break;
+ }
+ }
+ }
+ } else if (result == ISC_R_SUCCESS) {
+ fprintf(stderr, EXPECTEDANDFOUND);
+ result = ISC_R_FAILURE;
+ }
+ if (first == NULL || newchain(first, e)) {
+ if (prev != NULL) {
+ if (!checknext(prev, first))
+ result = ISC_R_FAILURE;
+ if (prev != first)
+ free_element(mctx, prev);
+ }
+ if (first != NULL)
+ free_element(mctx, first);
+ prev = first = e;
+ continue;
+ }
+ if (!checknext(prev, e))
+ result = ISC_R_FAILURE;
+ if (prev != first)
+ free_element(mctx, prev);
+ prev = e;
+ }
+ if (prev != NULL) {
+ if (!checknext(prev, first))
+ result = ISC_R_FAILURE;
+ if (prev != first)
+ free_element(mctx, prev);
+ }
+ if (first != NULL)
+ free_element(mctx, first);
+ do {
+ if (f != NULL) {
+ if (result == ISC_R_SUCCESS) {
+ fprintf(stderr, EXPECTEDANDFOUND);
+ result = ISC_R_FAILURE;
+ }
+ free_element(mctx, f);
+ }
+ f = isc_heap_element(found_chains, 1);
+ if (f != NULL)
+ isc_heap_delete(found_chains, 1);
+ } while (f != NULL);
+
+ return (result);
+}
+
+static isc_result_t
+verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname,
+ bool isdelegation, dns_rdataset_t *nsec3paramset)
+{
+ dns_namereln_t reln;
+ int order;
+ unsigned int labels, nlabels, i;
+ dns_name_t suffix;
+ isc_result_t result = ISC_R_SUCCESS, tresult;
+
+ reln = dns_name_fullcompare(prevname, name, &order, &labels);
+ if (order >= 0)
+ return (result);
+
+ nlabels = dns_name_countlabels(name);
+
+ if (reln == dns_namereln_commonancestor ||
+ reln == dns_namereln_contains) {
+ dns_name_init(&suffix, NULL);
+ for (i = labels + 1; i < nlabels; i++) {
+ dns_name_getlabelsequence(name, nlabels - i, i,
+ &suffix);
+ if (nsec3paramset != NULL &&
+ dns_rdataset_isassociated(nsec3paramset)) {
+ tresult = verifynsec3s(db, ver, origin, mctx,
+ &suffix, nsec3paramset,
+ isdelegation, true,
+ NULL, 0);
+ if (result == ISC_R_SUCCESS &&
+ tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ }
+ }
+ return (result);
+}
+
+/*%
+ * Verify that certain things are sane:
+ *
+ * The apex has a DNSKEY record with at least one KSK, and at least
+ * one ZSK if the -x flag was not used.
+ *
+ * The DNSKEY record was signed with at least one of the KSKs in this
+ * set.
+ *
+ * The rest of the zone was signed with at least one of the ZSKs
+ * present in the DNSKEY RRSET.
+ */
+void
+verifyzone(dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *origin, isc_mem_t *mctx,
+ bool ignore_kskflag, bool keyset_kskonly)
+{
+ char algbuf[80];
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fprevname, fzonecut;
+ dns_name_t *name, *nextname, *prevname, *zonecut;
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t keyset, soaset;
+ dns_rdataset_t keysigs, soasigs;
+ dns_rdataset_t nsecset, nsecsigs;
+ dns_rdataset_t nsec3paramset, nsec3paramsigs;
+ int i;
+ bool done = false;
+ bool first = true;
+ bool goodksk = false;
+ bool goodzsk = false;
+ isc_result_t result, vresult = ISC_R_UNSET;
+ unsigned char revoked_ksk[256];
+ unsigned char revoked_zsk[256];
+ unsigned char standby_ksk[256];
+ unsigned char standby_zsk[256];
+ unsigned char ksk_algorithms[256];
+ unsigned char zsk_algorithms[256];
+ unsigned char bad_algorithms[256];
+ unsigned char act_algorithms[256];
+
+ result = isc_heap_create(mctx, chain_compare, NULL, 1024,
+ &expected_chains);
+ check_result(result, "isc_heap_create()");
+ result = isc_heap_create(mctx, chain_compare, NULL, 1024,
+ &found_chains);
+ check_result(result, "isc_heap_create()");
+
+ result = dns_db_findnode(db, origin, false, &node);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to find the zone's origin: %s",
+ isc_result_totext(result));
+
+ dns_rdataset_init(&keyset);
+ dns_rdataset_init(&keysigs);
+ dns_rdataset_init(&soaset);
+ dns_rdataset_init(&soasigs);
+ dns_rdataset_init(&nsecset);
+ dns_rdataset_init(&nsecsigs);
+ dns_rdataset_init(&nsec3paramset);
+ dns_rdataset_init(&nsec3paramsigs);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
+ 0, 0, &keyset, &keysigs);
+ if (result != ISC_R_SUCCESS)
+ fatal("Zone contains no DNSSEC keys\n");
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
+ 0, 0, &soaset, &soasigs);
+ if (result != ISC_R_SUCCESS)
+ fatal("Zone contains no SOA record\n");
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, 0, &nsecset, &nsecsigs);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ fatal("NSEC lookup failed\n");
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, 0, &nsec3paramset, &nsec3paramsigs);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ fatal("NSEC3PARAM lookup failed\n");
+
+ if (!dns_rdataset_isassociated(&keysigs))
+ fatal("DNSKEY is not signed (keys offline or inactive?)\n");
+
+ if (!dns_rdataset_isassociated(&soasigs))
+ fatal("SOA is not signed (keys offline or inactive?)\n");
+
+ if (dns_rdataset_isassociated(&nsecset) &&
+ !dns_rdataset_isassociated(&nsecsigs))
+ fatal("NSEC is not signed (keys offline or inactive?)\n");
+
+ if (dns_rdataset_isassociated(&nsec3paramset) &&
+ !dns_rdataset_isassociated(&nsec3paramsigs))
+ fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n");
+
+ if (!dns_rdataset_isassociated(&nsecset) &&
+ !dns_rdataset_isassociated(&nsec3paramset))
+ fatal("No valid NSEC/NSEC3 chain for testing\n");
+
+ dns_db_detachnode(db, &node);
+
+ memset(revoked_ksk, 0, sizeof(revoked_ksk));
+ memset(revoked_zsk, 0, sizeof(revoked_zsk));
+ memset(standby_ksk, 0, sizeof(standby_ksk));
+ memset(standby_zsk, 0, sizeof(standby_zsk));
+ memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
+ memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
+ memset(bad_algorithms, 0, sizeof(bad_algorithms));
+ memset(act_algorithms, 0, sizeof(act_algorithms));
+
+ /*
+ * Check that the DNSKEY RR has at least one self signing KSK
+ * and one ZSK per algorithm in it (or, if -x was used, one
+ * self-signing KSK).
+ */
+ for (result = dns_rdataset_first(&keyset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset)) {
+ dns_rdataset_current(&keyset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
+ ;
+ else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
+ if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
+ !dns_dnssec_selfsigns(&rdata, origin, &keyset,
+ &keysigs, false,
+ mctx)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char buffer[1024];
+ isc_buffer_t buf;
+
+ dns_name_format(origin, namebuf,
+ sizeof(namebuf));
+ isc_buffer_init(&buf, buffer, sizeof(buffer));
+ result = dns_rdata_totext(&rdata, NULL, &buf);
+ check_result(result, "dns_rdata_totext");
+ fatal("revoked KSK is not self signed:\n"
+ "%s DNSKEY %.*s", namebuf,
+ (int)isc_buffer_usedlength(&buf), buffer);
+ }
+ if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
+ revoked_ksk[dnskey.algorithm] != 255)
+ revoked_ksk[dnskey.algorithm]++;
+ else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
+ revoked_zsk[dnskey.algorithm] != 255)
+ revoked_zsk[dnskey.algorithm]++;
+ } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
+ if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
+ &keysigs, false, mctx)) {
+ if (ksk_algorithms[dnskey.algorithm] != 255)
+ ksk_algorithms[dnskey.algorithm]++;
+ goodksk = true;
+ } else {
+ if (standby_ksk[dnskey.algorithm] != 255)
+ standby_ksk[dnskey.algorithm]++;
+ }
+ } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
+ &keysigs, false, mctx)) {
+ if (zsk_algorithms[dnskey.algorithm] != 255)
+ zsk_algorithms[dnskey.algorithm]++;
+ goodzsk = true;
+ } else if (dns_dnssec_signs(&rdata, origin, &soaset,
+ &soasigs, false, mctx)) {
+ if (zsk_algorithms[dnskey.algorithm] != 255)
+ zsk_algorithms[dnskey.algorithm]++;
+ } else {
+ if (standby_zsk[dnskey.algorithm] != 255)
+ standby_zsk[dnskey.algorithm]++;
+ }
+ dns_rdata_freestruct(&dnskey);
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&keysigs);
+ dns_rdataset_disassociate(&soaset);
+ dns_rdataset_disassociate(&soasigs);
+ if (dns_rdataset_isassociated(&nsecsigs))
+ dns_rdataset_disassociate(&nsecsigs);
+ if (dns_rdataset_isassociated(&nsec3paramsigs))
+ dns_rdataset_disassociate(&nsec3paramsigs);
+
+ if (ignore_kskflag ) {
+ if (!goodksk && !goodzsk)
+ fatal("No self-signed DNSKEY found.");
+ } else if (!goodksk)
+ fatal("No self-signed KSK DNSKEY found. Supply an active\n"
+ "key with the KSK flag set, or use '-P'.");
+
+ fprintf(stderr, "Verifying the zone using the following algorithms:");
+ for (i = 0; i < 256; i++) {
+ if (ignore_kskflag)
+ act_algorithms[i] = (ksk_algorithms[i] != 0 ||
+ zsk_algorithms[i] != 0) ? 1 : 0;
+ else
+ act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0;
+ if (act_algorithms[i] != 0) {
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, " %s", algbuf);
+ }
+ }
+ fprintf(stderr, ".\n");
+
+ if (!ignore_kskflag && !keyset_kskonly) {
+ for (i = 0; i < 256; i++) {
+ /*
+ * The counts should both be zero or both be non-zero.
+ * Mark the algorithm as bad if this is not met.
+ */
+ if ((ksk_algorithms[i] != 0) ==
+ (zsk_algorithms[i] != 0))
+ continue;
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, "Missing %s for algorithm %s\n",
+ (ksk_algorithms[i] != 0)
+ ? "ZSK"
+ : "self-signed KSK",
+ algbuf);
+ bad_algorithms[i] = 1;
+ }
+ }
+
+ /*
+ * Check that all the other records were signed by keys that are
+ * present in the DNSKEY RRSET.
+ */
+
+ name = dns_fixedname_initname(&fname);
+ nextname = dns_fixedname_initname(&fnextname);
+ dns_fixedname_init(&fprevname);
+ prevname = NULL;
+ dns_fixedname_init(&fzonecut);
+ zonecut = NULL;
+
+ result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ bool isdelegation = false;
+
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ if (!dns_name_issubdomain(name, origin)) {
+ check_no_nsec(name, node, db, ver);
+ dns_db_detachnode(db, &node);
+ result = dns_dbiterator_next(dbiter);
+ if (result == ISC_R_NOMORE)
+ done = true;
+ else
+ check_result(result, "dns_dbiterator_next()");
+ continue;
+ }
+ if (is_delegation(db, ver, origin, name, node, NULL)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ isdelegation = true;
+ } else if (has_dname(db, ver, node)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ }
+ nextnode = NULL;
+ result = dns_dbiterator_next(dbiter);
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ check_dns_dbiterator_current(result);
+ if (!dns_name_issubdomain(nextname, origin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut)))
+ {
+ check_no_nsec(nextname, nextnode, db, ver);
+ dns_db_detachnode(db, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (is_empty(db, ver, nextnode)) {
+ dns_db_detachnode(db, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ dns_db_detachnode(db, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ done = true;
+ nextname = origin;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ result = verifynode(db, ver, origin, mctx, name, node,
+ isdelegation, &keyset, act_algorithms,
+ bad_algorithms, &nsecset, &nsec3paramset,
+ nextname);
+ if (vresult == ISC_R_UNSET)
+ vresult = ISC_R_SUCCESS;
+ if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
+ vresult = result;
+ if (prevname != NULL) {
+ result = verifyemptynodes(db, ver, origin, mctx, name,
+ prevname, isdelegation,
+ &nsec3paramset);
+ } else
+ prevname = dns_fixedname_name(&fprevname);
+ dns_name_copy(name, prevname, NULL);
+ if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
+ vresult = result;
+ dns_db_detachnode(db, &node);
+ }
+
+ dns_dbiterator_destroy(&dbiter);
+
+ result = dns_db_createiterator(db, 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 = verifynode(db, ver, origin, mctx, name, node,
+ false, &keyset, act_algorithms,
+ bad_algorithms, NULL, NULL, NULL);
+ check_result(result, "verifynode");
+ record_found(db, ver, mctx, name, node, &nsec3paramset);
+ dns_db_detachnode(db, &node);
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ dns_rdataset_disassociate(&keyset);
+ if (dns_rdataset_isassociated(&nsecset))
+ dns_rdataset_disassociate(&nsecset);
+ if (dns_rdataset_isassociated(&nsec3paramset))
+ dns_rdataset_disassociate(&nsec3paramset);
+
+ result = verify_nsec3_chains(mctx);
+ if (vresult == ISC_R_UNSET)
+ vresult = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS)
+ vresult = result;
+ isc_heap_destroy(&expected_chains);
+ isc_heap_destroy(&found_chains);
+
+ /*
+ * If we made it this far, we have what we consider a properly signed
+ * zone. Set the good flag.
+ */
+ for (i = 0; i < 256; i++) {
+ if (bad_algorithms[i] != 0) {
+ if (first)
+ fprintf(stderr, "The zone is not fully signed "
+ "for the following algorithms:");
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, " %s", algbuf);
+ first = false;
+ }
+ }
+ if (!first) {
+ fprintf(stderr, ".\n");
+ fatal("DNSSEC completeness test failed.");
+ }
+
+ if (vresult != ISC_R_SUCCESS)
+ fatal("DNSSEC completeness test failed (%s).",
+ dns_result_totext(vresult));
+
+ if (goodksk || ignore_kskflag) {
+ /*
+ * Print the success summary.
+ */
+ fprintf(stderr, "Zone fully signed:\n");
+ for (i = 0; i < 256; i++) {
+ if ((ksk_algorithms[i] != 0) ||
+ (standby_ksk[i] != 0) ||
+ (revoked_ksk[i] != 0) ||
+ (zsk_algorithms[i] != 0) ||
+ (standby_zsk[i] != 0) ||
+ (revoked_zsk[i] != 0)) {
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, "Algorithm: %s: KSKs: "
+ "%u active, %u stand-by, %u revoked\n",
+ algbuf, ksk_algorithms[i],
+ standby_ksk[i], revoked_ksk[i]);
+ fprintf(stderr, "%*sZSKs: "
+ "%u active, %u %s, %u revoked\n",
+ (int) strlen(algbuf) + 13, "",
+ zsk_algorithms[i],
+ standby_zsk[i],
+ keyset_kskonly ? "present" : "stand-by",
+ revoked_zsk[i]);
+ }
+ }
+ }
+}
+
+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 arguement */
+ isc_commandline_index++;
+ return (true);
+ }
+ return (false);
+}
+
+#ifdef _WIN32
+void
+InitSockets(void) {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if (err != 0) {
+ fprintf(stderr, "WSAStartup() failed: %d\n", err);
+ exit(1);
+ }
+}
+
+void
+DestroySockets(void) {
+ WSACleanup();
+}
+#endif
diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h
new file mode 100644
index 0000000..b984a43
--- /dev/null
+++ b/bin/dnssec/dnssectool.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef DNSSECTOOL_H
+#define DNSSECTOOL_H 1
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/log.h>
+#include <isc/stdtime.h>
+#include <dns/rdatastruct.h>
+#include <dst/dst.h>
+
+#define check_dns_dbiterator_current(result) \
+ check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
+ "dns_dbiterator_current()")
+
+
+typedef void (fatalcallback_t)(void);
+
+ISC_PLATFORM_NORETURN_PRE void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+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);
+
+ISC_PLATFORM_NORETURN_PRE void
+version(const char *program) ISC_PLATFORM_NORETURN_POST;
+
+void
+type_format(const dns_rdatatype_t type, char *cp, unsigned int size);
+#define TYPE_FORMATSIZE 20
+
+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);
+
+void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx);
+
+void
+cleanup_entropy(isc_entropy_t **ectx);
+
+dns_ttl_t strtottl(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);
+
+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
+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);
+
+/*%
+ * Return true if version 'ver' of database 'db' contains a DNAME RRset at
+ * 'node'; return false otherwise.
+ */
+bool
+has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node);
+
+void
+verifyzone(dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *origin, isc_mem_t *mctx,
+ bool ignore_kskflag, bool keyset_kskonly);
+
+bool
+isoptarg(const char *arg, char **argv, void (*usage)(void));
+
+#ifdef _WIN32
+void InitSockets(void);
+void DestroySockets(void);
+#endif
+
+#endif /* DNSSEC_DNSSECTOOL_H */
diff --git a/bin/dnssec/win32/dnssectool.dsp.in b/bin/dnssec/win32/dnssectool.dsp.in
new file mode 100644
index 0000000..66cc4e1
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.dsp.in
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="dnssectool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104
+
+CFG=dnssectool - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dnssectool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dnssectool.mak" CFG="dnssectool - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dnssectool - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE "dnssectool - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dnssectool - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fddnssectool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/dnssectool.lib"
+
+!ELSEIF "$(CFG)" == "dnssectool - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fddnssectool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/dnssectool.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dnssectool - @PLATFORM@ Release"
+# Name "dnssectool - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dnssectool.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/dnssectool.dsw b/bin/dnssec/win32/dnssectool.dsw
new file mode 100644
index 0000000..703c508
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dnssectool"=".\dnssectool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/dnssectool.vcxproj.filters.in b/bin/dnssec/win32/dnssectool.vcxproj.filters.in
new file mode 100644
index 0000000..1743f84
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\dnssectool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssectool.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/dnssectool.vcxproj.in b/bin/dnssec/win32/dnssectool.vcxproj.in
new file mode 100644
index 0000000..7d6b3da
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.vcxproj.in
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\dnssectool.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssectool.c" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2CB7DC75-023B-4AA3-AF3A-AE5046A4EE70}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dnssectool</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <OutDir>.\$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <OutDir>.\$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/dnssectool.vcxproj.user b/bin/dnssec/win32/dnssectool.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/dsfromkey.dsp.in b/bin/dnssec/win32/dsfromkey.dsp.in
new file mode 100644
index 0000000..6967304
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="dsfromkey" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=dsfromkey - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dsfromkey.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dsfromkey.mak" CFG="dsfromkey - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dsfromkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "dsfromkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-dsfromkey.exe"
+
+!ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-dsfromkey.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "dsfromkey - @PLATFORM@ Release"
+# Name "dsfromkey - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-dsfromkey.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/dsfromkey.dsw b/bin/dnssec/win32/dsfromkey.dsw
new file mode 100644
index 0000000..62b5c48
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dsfromkey"=".\dsfromkey.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/dsfromkey.mak.in b/bin/dnssec/win32/dsfromkey.mak.in
new file mode 100644
index 0000000..f5d6ec6
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on dsfromkey.dsp
+!IF "$(CFG)" == ""
+CFG=dsfromkey - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to dsfromkey - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "dsfromkey - @PLATFORM@ Release" && "$(CFG)" != "dsfromkey - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dsfromkey.mak" CFG="dsfromkey - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dsfromkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "dsfromkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-dsfromkey.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-dsfromkey.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-dsfromkey.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dsfromkey.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dsfromkey.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-dsfromkey.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-dsfromkey.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-dsfromkey.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-dsfromkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-dsfromkey.exe" "$(OUTDIR)\dsfromkey.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-dsfromkey.obj"
+ -@erase "$(INTDIR)\dnssec-dsfromkey.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-dsfromkey.pdb"
+ -@erase "$(OUTDIR)\dsfromkey.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-dsfromkey.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-dsfromkey.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dsfromkey.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-dsfromkey.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\dsfromkey.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-dsfromkey.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-dsfromkey.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-dsfromkey.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-dsfromkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("dsfromkey.dep")
+!INCLUDE "dsfromkey.dep"
+!ELSE
+!MESSAGE Warning: cannot find "dsfromkey.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" || "$(CFG)" == "dsfromkey - @PLATFORM@ Debug"
+SOURCE="..\dnssec-dsfromkey.c"
+
+!IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-dsfromkey.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-dsfromkey.obj" "$(INTDIR)\dnssec-dsfromkey.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/dsfromkey.vcxproj.filters.in b/bin/dnssec/win32/dsfromkey.vcxproj.filters.in
new file mode 100644
index 0000000..7d0a58e
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-dsfromkey.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/dsfromkey.vcxproj.in b/bin/dnssec/win32/dsfromkey.vcxproj.in
new file mode 100644
index 0000000..b58fc1a
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.vcxproj.in
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6E6297F4-69D7-4533-85E1-BD17C30017C8}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dsfromkey</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+@IF PYTHON
+ <PostBuildEvent>
+ <Command>cd ..\..\python
+copy /Y dnssec-checkds.py ..\..\Build\$(Configuration)\dnssec-checkds.py
+copy /Y dnssec-coverage.py ..\..\Build\$(Configuration)\dnssec-coverage.py
+copy /Y dnssec-keymgr.py ..\..\Build\$(Configuration)\dnssec-keymgr.py
+cd isc
+@PYTHON@ policy.py parse \dev\nul > nul
+set PYTHONPATH=.
+@PYTHON@ -m parsetab
+</Command>
+ </PostBuildEvent>
+@END PYTHON
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+@IF PYTHON
+ <PostBuildEvent>
+ <Command>cd ..\..\python
+copy /Y dnssec-checkds.py ..\..\Build\$(Configuration)\dnssec-checkds.py
+copy /Y dnssec-coverage.py ..\..\Build\$(Configuration)\dnssec-coverage.py
+copy /Y dnssec-keymgr.py ..\..\Build\$(Configuration)\dnssec-keymgr.py
+cd isc
+@PYTHON@ policy.py parse \dev\nul > nul
+set PYTHONPATH=.
+@PYTHON@ -m parsetab
+</Command>
+ </PostBuildEvent>
+@END PYTHON
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-dsfromkey.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/dsfromkey.vcxproj.user b/bin/dnssec/win32/dsfromkey.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/importkey.dsp.in b/bin/dnssec/win32/importkey.dsp.in
new file mode 100644
index 0000000..cb6ba98
--- /dev/null
+++ b/bin/dnssec/win32/importkey.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="importkey" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=importkey - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "importkey.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "importkey.mak" CFG="importkey - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "importkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "importkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "importkey - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-importkey.exe"
+
+!ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-importkey.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "importkey - @PLATFORM@ Release"
+# Name "importkey - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-importkey.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/importkey.dsw b/bin/dnssec/win32/importkey.dsw
new file mode 100644
index 0000000..02afc26
--- /dev/null
+++ b/bin/dnssec/win32/importkey.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "importkey"=".\importkey.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/importkey.mak.in b/bin/dnssec/win32/importkey.mak.in
new file mode 100644
index 0000000..53d42af
--- /dev/null
+++ b/bin/dnssec/win32/importkey.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on importkey.dsp
+!IF "$(CFG)" == ""
+CFG=importkey - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to importkey - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "importkey - @PLATFORM@ Release" && "$(CFG)" != "importkey - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "importkey.mak" CFG="importkey - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "importkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "importkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "importkey - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "importkey - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-importkey.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-importkey.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-importkey.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\importkey.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\importkey.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-importkey.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-importkey.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-importkey.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-importkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-importkey.exe" "$(OUTDIR)\importkey.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-importkey.obj"
+ -@erase "$(INTDIR)\dnssec-importkey.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-importkey.pdb"
+ -@erase "$(OUTDIR)\importkey.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-importkey.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-importkey.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\importkey.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-importkey.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\importkey.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-importkey.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-importkey.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-importkey.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-importkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("importkey.dep")
+!INCLUDE "importkey.dep"
+!ELSE
+!MESSAGE Warning: cannot find "importkey.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "importkey - @PLATFORM@ Release" || "$(CFG)" == "importkey - @PLATFORM@ Debug"
+SOURCE="..\dnssec-importkey.c"
+
+!IF "$(CFG)" == "importkey - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-importkey.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-importkey.obj" "$(INTDIR)\dnssec-importkey.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "importkey - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/importkey.vcxproj.filters.in b/bin/dnssec/win32/importkey.vcxproj.filters.in
new file mode 100644
index 0000000..0bced36
--- /dev/null
+++ b/bin/dnssec/win32/importkey.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-importkey.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/bin/dnssec/win32/importkey.vcxproj.in b/bin/dnssec/win32/importkey.vcxproj.in
new file mode 100644
index 0000000..92f7dac
--- /dev/null
+++ b/bin/dnssec/win32/importkey.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AB6690A0-055E-458f-BAC5-BF38BCC5834F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>importkey</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-importkey.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/importkey.vcxproj.user b/bin/dnssec/win32/importkey.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/importkey.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/keyfromlabel.dsp.in b/bin/dnssec/win32/keyfromlabel.dsp.in
new file mode 100644
index 0000000..1739e9f
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="keyfromlabel" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=keyfromlabel - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keyfromlabel.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keyfromlabel.mak" CFG="keyfromlabel - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keyfromlabel - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keyfromlabel - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-keyfromlabel.exe"
+
+!ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keyfromlabel.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keyfromlabel - @PLATFORM@ Release"
+# Name "keyfromlabel - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-keyfromlabel.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/keyfromlabel.dsw b/bin/dnssec/win32/keyfromlabel.dsw
new file mode 100644
index 0000000..085c24d
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keyfromlabel"=".\keyfromlabel.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/keyfromlabel.mak.in b/bin/dnssec/win32/keyfromlabel.mak.in
new file mode 100644
index 0000000..2a58a96
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keyfromlabel.dsp
+!IF "$(CFG)" == ""
+CFG=keyfromlabel - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to keyfromlabel - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keyfromlabel - @PLATFORM@ Release" && "$(CFG)" != "keyfromlabel - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keyfromlabel.mak" CFG="keyfromlabel - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keyfromlabel - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keyfromlabel - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-keyfromlabel.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keyfromlabel.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-keyfromlabel.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keyfromlabel.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keyfromlabel.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keyfromlabel.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-keyfromlabel.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keyfromlabel.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-keyfromlabel.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-keyfromlabel.exe" "$(OUTDIR)\keyfromlabel.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keyfromlabel.obj"
+ -@erase "$(INTDIR)\dnssec-keyfromlabel.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-keyfromlabel.pdb"
+ -@erase "$(OUTDIR)\keyfromlabel.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-keyfromlabel.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-keyfromlabel.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keyfromlabel.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-keyfromlabel.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\keyfromlabel.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keyfromlabel.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keyfromlabel.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keyfromlabel.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-keyfromlabel.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keyfromlabel.dep")
+!INCLUDE "keyfromlabel.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keyfromlabel.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" || "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug"
+SOURCE="..\dnssec-keyfromlabel.c"
+
+!IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-keyfromlabel.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-keyfromlabel.obj" "$(INTDIR)\dnssec-keyfromlabel.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/keyfromlabel.vcxproj.filters.in b/bin/dnssec/win32/keyfromlabel.vcxproj.filters.in
new file mode 100644
index 0000000..bb54f81
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-keyfromlabel.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/keyfromlabel.vcxproj.in b/bin/dnssec/win32/keyfromlabel.vcxproj.in
new file mode 100644
index 0000000..d1f6eca
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{17455DC6-5FBB-47C3-8F44-7DB574A188D3}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>keyfromlabel</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-keyfromlabel.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/keyfromlabel.vcxproj.user b/bin/dnssec/win32/keyfromlabel.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/keygen.dsp.in b/bin/dnssec/win32/keygen.dsp.in
new file mode 100644
index 0000000..6b135bf
--- /dev/null
+++ b/bin/dnssec/win32/keygen.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="keygen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=keygen - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak" CFG="keygen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keygen - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-keygen.exe"
+
+!ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keygen - @PLATFORM@ Release"
+# Name "keygen - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-keygen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/keygen.dsw b/bin/dnssec/win32/keygen.dsw
new file mode 100644
index 0000000..f988651
--- /dev/null
+++ b/bin/dnssec/win32/keygen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keygen"=".\keygen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/keygen.mak.in b/bin/dnssec/win32/keygen.mak.in
new file mode 100644
index 0000000..b29d11d
--- /dev/null
+++ b/bin/dnssec/win32/keygen.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keygen.dsp
+!IF "$(CFG)" == ""
+CFG=keygen - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to keygen - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keygen - @PLATFORM@ Release" && "$(CFG)" != "keygen - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak" CFG="keygen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "keygen - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keygen - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-keygen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keygen.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-keygen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keygen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keygen.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-keygen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keygen.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-keygen.exe" "$(OUTDIR)\keygen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keygen.obj"
+ -@erase "$(INTDIR)\dnssec-keygen.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-keygen.pdb"
+ -@erase "$(OUTDIR)\keygen.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-keygen.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-keygen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-keygen.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\keygen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keygen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keygen.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keygen.dep")
+!INCLUDE "keygen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keygen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keygen - @PLATFORM@ Release" || "$(CFG)" == "keygen - @PLATFORM@ Debug"
+SOURCE="..\dnssec-keygen.c"
+
+!IF "$(CFG)" == "keygen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-keygen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-keygen.obj" "$(INTDIR)\dnssec-keygen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "keygen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/keygen.vcxproj.filters.in b/bin/dnssec/win32/keygen.vcxproj.filters.in
new file mode 100644
index 0000000..5d1fa4c
--- /dev/null
+++ b/bin/dnssec/win32/keygen.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-keygen.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/keygen.vcxproj.in b/bin/dnssec/win32/keygen.vcxproj.in
new file mode 100644
index 0000000..b4259ca
--- /dev/null
+++ b/bin/dnssec/win32/keygen.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{0BF11E21-168C-4CAA-B784-429D126BBAE5}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>keygen</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-keygen.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/keygen.vcxproj.user b/bin/dnssec/win32/keygen.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/keygen.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/revoke.dsp.in b/bin/dnssec/win32/revoke.dsp.in
new file mode 100644
index 0000000..521028d
--- /dev/null
+++ b/bin/dnssec/win32/revoke.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="revoke" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=revoke - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "revoke.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "revoke.mak" CFG="revoke - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "revoke - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "revoke - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "revoke - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-revoke.exe"
+
+!ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-revoke.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "revoke - @PLATFORM@ Release"
+# Name "revoke - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-revoke.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/revoke.dsw b/bin/dnssec/win32/revoke.dsw
new file mode 100644
index 0000000..5dadcdb
--- /dev/null
+++ b/bin/dnssec/win32/revoke.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "revoke"=".\revoke.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/revoke.mak.in b/bin/dnssec/win32/revoke.mak.in
new file mode 100644
index 0000000..03632ef
--- /dev/null
+++ b/bin/dnssec/win32/revoke.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on revoke.dsp
+!IF "$(CFG)" == ""
+CFG=revoke - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to revoke - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "revoke - @PLATFORM@ Release" && "$(CFG)" != "revoke - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "revoke.mak" CFG="revoke - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "revoke - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "revoke - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "revoke - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "revoke - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-revoke.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-revoke.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-revoke.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\revoke.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\revoke.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-revoke.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-revoke.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-revoke.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-revoke.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-revoke.exe" "$(OUTDIR)\revoke.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-revoke.obj"
+ -@erase "$(INTDIR)\dnssec-revoke.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-revoke.pdb"
+ -@erase "$(OUTDIR)\revoke.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-revoke.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-revoke.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\revoke.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-revoke.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\revoke.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-revoke.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-revoke.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-revoke.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-revoke.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("revoke.dep")
+!INCLUDE "revoke.dep"
+!ELSE
+!MESSAGE Warning: cannot find "revoke.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "revoke - @PLATFORM@ Release" || "$(CFG)" == "revoke - @PLATFORM@ Debug"
+SOURCE="..\dnssec-revoke.c"
+
+!IF "$(CFG)" == "revoke - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-revoke.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-revoke.obj" "$(INTDIR)\dnssec-revoke.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "revoke - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/revoke.vcxproj.filters.in b/bin/dnssec/win32/revoke.vcxproj.filters.in
new file mode 100644
index 0000000..46e7310
--- /dev/null
+++ b/bin/dnssec/win32/revoke.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-revoke.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/revoke.vcxproj.in b/bin/dnssec/win32/revoke.vcxproj.in
new file mode 100644
index 0000000..91c0607
--- /dev/null
+++ b/bin/dnssec/win32/revoke.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{D171F185-D3C2-4463-9CF3-ED1D0B1D6832}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>revoke</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-revoke.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/revoke.vcxproj.user b/bin/dnssec/win32/revoke.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/revoke.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/settime.dsp.in b/bin/dnssec/win32/settime.dsp.in
new file mode 100644
index 0000000..d71a3a9
--- /dev/null
+++ b/bin/dnssec/win32/settime.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="settime" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=settime - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "settime.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "settime.mak" CFG="settime - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "settime - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "settime - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "settime - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-settime.exe"
+
+!ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-settime.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "settime - @PLATFORM@ Release"
+# Name "settime - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-settime.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/settime.dsw b/bin/dnssec/win32/settime.dsw
new file mode 100644
index 0000000..742a8c6
--- /dev/null
+++ b/bin/dnssec/win32/settime.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "settime"=".\settime.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/settime.mak.in b/bin/dnssec/win32/settime.mak.in
new file mode 100644
index 0000000..1de3a84
--- /dev/null
+++ b/bin/dnssec/win32/settime.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on settime.dsp
+!IF "$(CFG)" == ""
+CFG=settime - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to settime - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "settime - @PLATFORM@ Release" && "$(CFG)" != "settime - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "settime.mak" CFG="settime - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "settime - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "settime - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "settime - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "settime - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-settime.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-settime.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-settime.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\settime.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\settime.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-settime.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-settime.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-settime.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-settime.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-settime.exe" "$(OUTDIR)\settime.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-settime.obj"
+ -@erase "$(INTDIR)\dnssec-settime.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-settime.pdb"
+ -@erase "$(OUTDIR)\settime.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-settime.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-settime.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\settime.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-settime.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\settime.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-settime.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-settime.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-settime.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-settime.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("settime.dep")
+!INCLUDE "settime.dep"
+!ELSE
+!MESSAGE Warning: cannot find "settime.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "settime - @PLATFORM@ Release" || "$(CFG)" == "settime - @PLATFORM@ Debug"
+SOURCE="..\dnssec-settime.c"
+
+!IF "$(CFG)" == "settime - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-settime.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-settime.obj" "$(INTDIR)\dnssec-settime.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "settime - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/settime.vcxproj.filters.in b/bin/dnssec/win32/settime.vcxproj.filters.in
new file mode 100644
index 0000000..62b0e82
--- /dev/null
+++ b/bin/dnssec/win32/settime.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-settime.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/settime.vcxproj.in b/bin/dnssec/win32/settime.vcxproj.in
new file mode 100644
index 0000000..0b68c40
--- /dev/null
+++ b/bin/dnssec/win32/settime.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{03FB7588-C5A7-4572-968F-14F1206BC69C}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>settime</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-settime.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/settime.vcxproj.user b/bin/dnssec/win32/settime.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/settime.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/signzone.dsp.in b/bin/dnssec/win32/signzone.dsp.in
new file mode 100644
index 0000000..ee45ec9
--- /dev/null
+++ b/bin/dnssec/win32/signzone.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="signzone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=signzone - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak" CFG="signzone - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "signzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "signzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "signzone - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-signzone.exe"
+
+!ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "signzone - @PLATFORM@ Release"
+# Name "signzone - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-signzone.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/signzone.dsw b/bin/dnssec/win32/signzone.dsw
new file mode 100644
index 0000000..f3314b9
--- /dev/null
+++ b/bin/dnssec/win32/signzone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "signzone"=".\signzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/signzone.mak.in b/bin/dnssec/win32/signzone.mak.in
new file mode 100644
index 0000000..a106465
--- /dev/null
+++ b/bin/dnssec/win32/signzone.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on signzone.dsp
+!IF "$(CFG)" == ""
+CFG=signzone - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to signzone - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "signzone - @PLATFORM@ Release" && "$(CFG)" != "signzone - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak" CFG="signzone - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "signzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "signzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "signzone - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "signzone - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-signzone.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-signzone.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-signzone.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\signzone.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-signzone.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-signzone.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-signzone.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-signzone.exe" "$(OUTDIR)\signzone.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-signzone.obj"
+ -@erase "$(INTDIR)\dnssec-signzone.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-signzone.pdb"
+ -@erase "$(OUTDIR)\signzone.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-signzone.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-signzone.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-signzone.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\signzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-signzone.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-signzone.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("signzone.dep")
+!INCLUDE "signzone.dep"
+!ELSE
+!MESSAGE Warning: cannot find "signzone.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "signzone - @PLATFORM@ Release" || "$(CFG)" == "signzone - @PLATFORM@ Debug"
+SOURCE="..\dnssec-signzone.c"
+
+!IF "$(CFG)" == "signzone - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-signzone.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-signzone.obj" "$(INTDIR)\dnssec-signzone.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "signzone - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/signzone.vcxproj.filters.in b/bin/dnssec/win32/signzone.vcxproj.filters.in
new file mode 100644
index 0000000..682ae55
--- /dev/null
+++ b/bin/dnssec/win32/signzone.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-signzone.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/signzone.vcxproj.in b/bin/dnssec/win32/signzone.vcxproj.in
new file mode 100644
index 0000000..0b9a9f6
--- /dev/null
+++ b/bin/dnssec/win32/signzone.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{205ED8A9-2E4C-41CC-9385-F3613402AA90}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>signzone</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-signzone.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/signzone.vcxproj.user b/bin/dnssec/win32/signzone.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/signzone.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/verify.dsp.in b/bin/dnssec/win32/verify.dsp.in
new file mode 100644
index 0000000..3c76ecd
--- /dev/null
+++ b/bin/dnssec/win32/verify.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="verify" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=verify - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "verify.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "verify.mak" CFG="verify - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "verify - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "verify - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "verify - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-verify.exe"
+
+!ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-verify.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "verify - @PLATFORM@ Release"
+# Name "verify - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-verify.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/verify.dsw b/bin/dnssec/win32/verify.dsw
new file mode 100644
index 0000000..a479950
--- /dev/null
+++ b/bin/dnssec/win32/verify.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "verify"=".\verify.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/verify.mak.in b/bin/dnssec/win32/verify.mak.in
new file mode 100644
index 0000000..a858a8b
--- /dev/null
+++ b/bin/dnssec/win32/verify.mak.in
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on verify.dsp
+!IF "$(CFG)" == ""
+CFG=verify - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to verify - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "verify - @PLATFORM@ Release" && "$(CFG)" != "verify - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "verify.mak" CFG="verify - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "verify - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "verify - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "verify - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "verify - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-verify.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-verify.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-verify.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\verify.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\verify.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-verify.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-verify.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-verify.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-verify.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-verify.exe" "$(OUTDIR)\verify.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-verify.obj"
+ -@erase "$(INTDIR)\dnssec-verify.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-verify.pdb"
+ -@erase "$(OUTDIR)\verify.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-verify.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-verify.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\verify.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-verify.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\verify.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-verify.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-verify.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-verify.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-verify.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("verify.dep")
+!INCLUDE "verify.dep"
+!ELSE
+!MESSAGE Warning: cannot find "verify.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "verify - @PLATFORM@ Release" || "$(CFG)" == "verify - @PLATFORM@ Debug"
+SOURCE="..\dnssec-verify.c"
+
+!IF "$(CFG)" == "verify - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssec-verify.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssec-verify.obj" "$(INTDIR)\dnssec-verify.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "verify - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/verify.vcxproj.filters.in b/bin/dnssec/win32/verify.vcxproj.filters.in
new file mode 100644
index 0000000..3b194bd
--- /dev/null
+++ b/bin/dnssec/win32/verify.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-verify.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dnssec/win32/verify.vcxproj.in b/bin/dnssec/win32/verify.vcxproj.in
new file mode 100644
index 0000000..251a893
--- /dev/null
+++ b/bin/dnssec/win32/verify.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FD653434-F1A8-44A9-85B2-A7468491DA6D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>verify</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>dnssec-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalDependencies>dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dnssec-verify.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dnssec/win32/verify.vcxproj.user b/bin/dnssec/win32/verify.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dnssec/win32/verify.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in
new file mode 100644
index 0000000..1c41397
--- /dev/null
+++ b/bin/named/Makefile.in
@@ -0,0 +1,192 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+# Attempt to disable parallel processing.
+.NOTPARALLEL:
+.NO_PARALLEL:
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_PRODUCT@
+
+@BIND9_DESCRIPTION@
+
+@BIND9_SRCID@
+
+@BIND9_CONFIGARGS@
+
+@BIND9_MAKE_INCLUDES@
+
+#
+# Add database drivers here.
+#
+DBDRIVER_OBJS =
+DBDRIVER_SRCS =
+DBDRIVER_INCLUDES =
+DBDRIVER_LIBS =
+
+DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers
+
+DLZDRIVER_OBJS = @DLZ_DRIVER_OBJS@
+DLZDRIVER_SRCS = @DLZ_DRIVER_SRCS@
+DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@
+DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@
+
+CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \
+ ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
+ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@
+
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \
+ ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
+ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \
+ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
+
+NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
+ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \
+ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
+
+SUBDIRS = unix
+
+TARGETS = named@EXEEXT@ lwresd@EXEEXT@
+
+GEOIPLINKOBJS = geoip.@O@
+
+OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
+ controlconf.@O@ fuzz.@O@ @GEOIPLINKOBJS@ interfacemgr.@O@ \
+ listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \
+ query.@O@ server.@O@ sortlist.@O@ statschannel.@O@ \
+ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \
+ zoneconf.@O@ \
+ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
+ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \
+ ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS}
+
+UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@
+
+SYMOBJS = symtbl.@O@
+
+GEOIPLINKSRCS = geoip.c
+
+SRCS = builtin.c client.c config.c control.c \
+ controlconf.c fuzz.c @GEOIPLINKSRCS@ interfacemgr.c \
+ listenlist.c log.c logconf.c main.c notify.c \
+ query.c server.c sortlist.c statschannel.c \
+ tkeyconf.c tsigconf.c update.c xfrout.c \
+ zoneconf.c \
+ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
+ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \
+ ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS}
+
+MANPAGES = named.8 lwresd.8 named.conf.5
+
+HTMLPAGES = named.html lwresd.html named.conf.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+main.@O@: main.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DPRODUCT=\"${PRODUCT}\" \
+ -DDESCRIPTION=\"${DESCRIPTION}\" \
+ -DSRCID=\"${SRCID}\" \
+ -DCONFIGARGS="\"${CONFIGARGS}\"" \
+ -DBUILDER="\"make\"" \
+ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c
+
+config.@O@: config.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DSRCID=\"${SRCID}\" \
+ -DDYNDB_LIBDIR=\"@libdir@/bind\" \
+ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -DNS_SYSCONFDIR=\"${sysconfdir}\" \
+ -c ${srcdir}/config.c
+
+server.@O@: server.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DPRODUCT=\"${PRODUCT}\" \
+ -DVERSION=\"${VERSION}\" -c ${srcdir}/server.c
+
+named@EXEEXT@: ${OBJS} ${DEPLIBS}
+ export MAKE_SYMTABLE="yes"; \
+ export BASEOBJS="${OBJS} ${UOBJS}"; \
+ ${FINALBUILDCMD}
+
+lwresd@EXEEXT@: named@EXEEXT@
+ rm -f lwresd@EXEEXT@
+ @LN@ named@EXEEXT@ lwresd@EXEEXT@
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS} ${OBJS}
+
+maintainer-clean::
+
+bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl
+ ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h
+
+depend: bind9.xsl.h
+statschannel.@O@: bind9.xsl.h
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir}
+ (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@)
+ ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man5/named.conf.5
+ rm -f ${DESTDIR}${mandir}/man8/lwresd.8
+ rm -f ${DESTDIR}${mandir}/man8/named.8
+ rm -f ${DESTDIR}${sbindir}/lwresd@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named@EXEEXT@
+
+@DLZ_DRIVER_RULES@
+
+named-symtbl.@O@: named-symtbl.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c named-symtbl.c
diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl
new file mode 100644
index 0000000..890654c
--- /dev/null
+++ b/bin/named/bind9.xsl
@@ -0,0 +1,1019 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<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"/>
+ <xsl:template match="statistics[@version=&quot;3.8&quot;]">
+ <html>
+ <head>
+ <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;
+ }
+
+ .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;
+ }
+
+ .totals {
+ background-color: rgb(1,169,206);
+ color: #ffffff;
+ }
+
+ 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>
+ <th>Boot time:</th>
+ <td>
+ <xsl:value-of select="server/boot-time"/>
+ </td>
+ </tr>
+ <tr>
+ <th>Last reconfigured:</th>
+ <td>
+ <xsl:value-of select="server/config-time"/>
+ </td>
+ </tr>
+ <tr>
+ <th>Current time:</th>
+ <td>
+ <xsl:value-of select="server/current-time"/>
+ </td>
+ </tr>
+ <tr>
+ <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"/>
+ <tr>
+ <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="@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="@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="@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="@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/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="socketmgr/sockets/socket">
+ <h2>Network Status</h2>
+ <table class="netstat">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>Type</th>
+ <th>References</th>
+ <th>LocalAddress</th>
+ <th>PeerAddress</th>
+ <th>State</th>
+ </tr>
+ <xsl:for-each select="socketmgr/sockets/socket">
+ <xsl:sort select="id"/>
+ <xsl:variable name="css-class12">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class12}">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="type"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="local-address"/>
+ </td>
+ <td>
+ <xsl:value-of select="peer-address"/>
+ </td>
+ <td>
+ <xsl:for-each select="states">
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </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>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="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/bind9.xsl.h b/bin/named/bind9.xsl.h
new file mode 100644
index 0000000..31425cf
--- /dev/null
+++ b/bin/named/bind9.xsl.h
@@ -0,0 +1,1024 @@
+/*
+ * Generated by convertxsl.pl 1.14 2008/07/17 23:43:26 jinmei Exp
+ * From unknown
+ */
+static char xslmsg[] =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!--\n"
+ " - Copyright (C) Internet Systems Consortium, Inc. (\"ISC\")\n"
+ " -\n"
+ " - This Source Code Form is subject to the terms of the Mozilla Public\n"
+ " - License, v. 2.0. If a copy of the MPL was not distributed with this\n"
+ " - file, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
+ " -\n"
+ " - See the COPYRIGHT file distributed with this work for additional\n"
+ " - information regarding copyright ownership.\n"
+ "-->\n"
+ "\n"
+ "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns=\"http://www.w3.org/1999/xhtml\" version=\"1.0\">\n"
+ " <xsl:output method=\"html\" indent=\"yes\" version=\"4.0\"/>\n"
+ " <xsl:template match=\"statistics[@version=&quot;3.8&quot;]\">\n"
+ " <html>\n"
+ " <head>\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"/>\n"
+ " <script type=\"text/javascript\">\n"
+ "\n"
+ " google.load(\"visualization\", \"1\", {packages:[\"corechart\"]});\n"
+ " google.setOnLoadCallback(loadGraphs);\n"
+ "\n"
+ " var graphs=[];\n"
+ "\n"
+ " function drawChart(chart_title,target,style,data) {\n"
+ " var data = google.visualization.arrayToDataTable(data);\n"
+ "\n"
+ " var options = {\n"
+ " title: chart_title\n"
+ " };\n"
+ "\n"
+ " var chart;\n"
+ " if (style == \"barchart\") {\n"
+ " chart = new google.visualization.BarChart(document.getElementById(target));\n"
+ " chart.draw(data, options);\n"
+ " } else if (style == \"piechart\") {\n"
+ " chart = new google.visualization.PieChart(document.getElementById(target));\n"
+ " chart.draw(data, options);\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " function loadGraphs(){\n"
+ " var g;\n"
+ "\n"
+ " while(g = graphs.shift()){\n"
+ " // alert(\"going for: \" + g.target);\n"
+ " if(g.data.length > 1){\n"
+ " drawChart(g.title,g.target,g.style,g.data);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " <xsl:if test=\"server/counters[@type=&quot;qtype&quot;]/counter\">\n"
+ " // Server Incoming Query Types\n"
+ " graphs.push({\n"
+ " 'title' : \"Server Incoming Query Types\",\n"
+ " 'target': 'chart_incoming_qtypes',\n"
+ " 'style': 'barchart',\n"
+ " '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>]\n"
+ " });\n"
+ " </xsl:if>\n"
+ "\n"
+ " <xsl:if test=\"server/counters[@type=&quot;opcode&quot;]/counter\">\n"
+ " // Server Incoming Requests by opcode\n"
+ " graphs.push({\n"
+ " 'title' : \"Server Incoming Requests by DNS Opcode\",\n"
+ " 'target': 'chart_incoming_opcodes',\n"
+ " 'style': 'barchart',\n"
+ " '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>]});\n"
+ " </xsl:if>\n"
+ " </script>\n"
+ " </xsl:if>\n"
+ " <style type=\"text/css\">\n"
+ " body {\n"
+ " font-family: sans-serif;\n"
+ " background-color: #ffffff;\n"
+ " color: #000000;\n"
+ " font-size: 10pt;\n"
+ " }\n"
+ "\n"
+ " .odd{\n"
+ " background-color: #f0f0f0;\n"
+ " }\n"
+ "\n"
+ " .even{\n"
+ " background-color: #ffffff;\n"
+ " }\n"
+ "\n"
+ " p.footer{\n"
+ " font-style:italic;\n"
+ " color: grey;\n"
+ " }\n"
+ "\n"
+ " table {\n"
+ " border-collapse: collapse;\n"
+ " border: 1px solid grey;\n"
+ " }\n"
+ "\n"
+ " table.counters{\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.counters th {\n"
+ " text-align: right;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.counters td {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.counters tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.info {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.info th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.info td {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.info tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.tasks {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.tasks th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.tasks td {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.tasks td:nth-child(2) {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.tasks td:nth-child(4) {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.tasks tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.netstat {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.netstat th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.netstat td {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.netstat td:nth-child(4) {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.netstat td:nth-child(7) {\n"
+ " text-align: left;\n"
+ " }\n"
+ " table.netstat tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.mctx {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.mctx th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " }\n"
+ " table.mctx td {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.mctx td:nth-child(-n+2) {\n"
+ " text-align: left;\n"
+ " width: 100px;\n"
+ " }\n"
+ " table.mctx tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " .totals {\n"
+ " background-color: rgb(1,169,206);\n"
+ " color: #ffffff;\n"
+ " }\n"
+ "\n"
+ " td, th {\n"
+ " padding-right: 5px;\n"
+ " padding-left: 5px;\n"
+ " border: 1px solid grey;\n"
+ " }\n"
+ "\n"
+ " .header h1 {\n"
+ " color: rgb(1,169,206);\n"
+ " padding: 0px;\n"
+ " }\n"
+ "\n"
+ " .content {\n"
+ " background-color: #ffffff;\n"
+ " color: #000000;\n"
+ " padding: 4px;\n"
+ " }\n"
+ "\n"
+ " .item {\n"
+ " padding: 4px;\n"
+ " text-align: right;\n"
+ " }\n"
+ "\n"
+ " .value {\n"
+ " padding: 4px;\n"
+ " font-weight: bold;\n"
+ " }\n"
+ "\n"
+ "\n"
+ " h2 {\n"
+ " color: grey;\n"
+ " font-size: 14pt;\n"
+ " width:500px;\n"
+ " text-align:center;\n"
+ " }\n"
+ "\n"
+ " h3 {\n"
+ " color: #444444;\n"
+ " font-size: 12pt;\n"
+ " width:500px;\n"
+ " text-align:center;\n"
+ " }\n"
+ " h4 {\n"
+ " color: rgb(1,169,206);\n"
+ " font-size: 10pt;\n"
+ " width:500px;\n"
+ " text-align:center;\n"
+ " }\n"
+ "\n"
+ " .pie {\n"
+ " width:500px;\n"
+ " height: 500px;\n"
+ " }\n"
+ "\n"
+ " </style>\n"
+ " <title>ISC BIND 9 Statistics</title>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"header\">\n"
+ " <h1>ISC Bind 9 Configuration and Statistics</h1>\n"
+ " </div>\n"
+ " <p>Alternate statistics views: <a href=\"/\">All</a>,\n"
+ " <a href=\"/xml/v3/status\">Status</a>,\n"
+ " <a href=\"/xml/v3/server\">Server</a>,\n"
+ " <a href=\"/xml/v3/zones\">Zones</a>,\n"
+ " <a href=\"/xml/v3/net\">Network</a>,\n"
+ " <a href=\"/xml/v3/tasks\">Tasks</a>,\n"
+ " <a href=\"/xml/v3/mem\">Memory</a> and\n"
+ " <a href=\"/xml/v3/traffic\">Traffic Size</a></p>\n"
+ " <hr/>\n"
+ " <h2>Server Status</h2>\n"
+ " <table class=\"info\">\n"
+ " <tr>\n"
+ " <th>Boot time:</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"server/boot-time\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <th>Last reconfigured:</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"server/config-time\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <th>Current time:</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"server/current-time\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <th>Server version:</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"server/version\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </table>\n"
+ " <br/>\n"
+ " <xsl:if test=\"server/counters[@type=&quot;opcode&quot;]/counter[. &gt; 0]\">\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <h2>Incoming Requests by DNS Opcode</h2>\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <div class=\"pie\" id=\"chart_incoming_opcodes\">\n"
+ " [cannot display chart]\n"
+ " </div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"server/counters[@type=&quot;opcode&quot;]/counter[. &gt; 0 or substring(@name,1,3) != 'RES']\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <tr>\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " <tr>\n"
+ " <th class=\"totals\">Total:</th>\n"
+ " <td class=\"totals\">\n"
+ " <xsl:value-of select=\"sum(server/counters[@type=&quot;opcode&quot;]/counter)\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type=&quot;qtype&quot;]/counter\">\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <h3>Incoming Queries by Query Type</h3>\n"
+ " <div class=\"pie\" id=\"chart_incoming_qtypes\">\n"
+ " [cannot display chart]\n"
+ " </div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"server/counters[@type=&quot;qtype&quot;]/counter\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " <tr>\n"
+ " <th class=\"totals\">Total:</th>\n"
+ " <td class=\"totals\">\n"
+ " <xsl:value-of select=\"sum(server/counters[@type=&quot;qtype&quot;]/counter)\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"views/view[count(counters[@type=&quot;resqtype&quot;]/counter) &gt; 0]\">\n"
+ " <h2>Outgoing Queries per view</h2>\n"
+ " <xsl:for-each select=\"views/view[count(counters[@type=&quot;resqtype&quot;]/counter) &gt; 0]\">\n"
+ " <h3>View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <script type=\"text/javascript\">\n"
+ " graphs.push({\n"
+ " 'title': \"Outgoing Queries for view: <xsl:value-of select=\"@name\"/>\",\n"
+ " 'target': 'chart_outgoing_queries_view_<xsl:value-of select=\"@name\"/>',\n"
+ " 'style': 'barchart',\n"
+ " '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>]\n"
+ " });\n"
+ " </script>\n"
+ " <xsl:variable name=\"target\">\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </xsl:variable>\n"
+ " <div class=\"pie\" id=\"chart_outgoing_queries_view_{$target}\">[no data to display]</div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"counters[@type=&quot;resqtype&quot;]/counter\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class1\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class1}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:for-each>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type=&quot;nsstat&quot;]/counter[.&gt;0]\">\n"
+ " <h2>Server Statistics</h2>\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <script type=\"text/javascript\">\n"
+ " graphs.push({\n"
+ " 'title' : \"Server Counters\",\n"
+ " 'target': 'chart_server_nsstat_restype',\n"
+ " 'style': 'barchart',\n"
+ " '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>]\n"
+ " });\n"
+ " </script>\n"
+ " <div class=\"pie\" id=\"chart_server_nsstat_restype\">[no data to display]</div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"server/counters[@type=&quot;nsstat&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class2\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class2}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type=&quot;zonestat&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <h2>Zone Maintenance Statistics</h2>\n"
+ " <script type=\"text/javascript\">\n"
+ " graphs.push({\n"
+ " 'title' : \"Zone Maintenance Stats\",\n"
+ " 'target': 'chart_server_zone_maint',\n"
+ " 'style': 'barchart',\n"
+ " '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>]\n"
+ " });\n"
+ " </script>\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <div class=\"pie\" id=\"chart_server_zone_maint\">[no data to display]</div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"server/counters[@type=&quot;zonestat&quot;]/counter\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class3\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class3}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type=&quot;resstat&quot;]/counter[.&gt;0]\">\n"
+ " <h2>Resolver Statistics (Common)</h2>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"server/counters[@type=&quot;resstat&quot;]/counter\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class4\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class4}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <xsl:if test=\"counters[@type=&quot;resstats&quot;]/counter[.&gt;0]\">\n"
+ " <h3>Resolver Statistics for View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"counters[@type=&quot;resstats&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class5\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class5}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " </xsl:for-each>\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <xsl:if test=\"counters[@type=&quot;adbstat&quot;]/counter[.&gt;0]\">\n"
+ " <h3>ADB Statistics for View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"counters[@type=&quot;adbstat&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class5\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class5}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " </xsl:for-each>\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <xsl:if test=\"counters[@type=&quot;cachestats&quot;]/counter[.&gt;0]\">\n"
+ " <h3>Cache Statistics for View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"counters[@type=&quot;cachestats&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class5\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class5}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " </xsl:for-each>\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <xsl:if test=\"cache/rrset\">\n"
+ " <h3>Cache DB RRsets for View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"cache/rrset\">\n"
+ " <xsl:variable name=\"css-class6\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class6}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counter\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " </xsl:for-each>\n"
+ " <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]\">\n"
+ " <h2>Traffic Size Statistics</h2>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"traffic/udp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]\">\n"
+ " <h4>UDP Requests Received</h4>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"traffic/udp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:variable name=\"css-class7\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class7}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"traffic/udp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]\">\n"
+ " <h4>UDP Responses Sent</h4>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"traffic/udp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:variable name=\"css-class7\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class7}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"traffic/tcp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]\">\n"
+ " <h4>TCP Requests Received</h4>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"traffic/tcp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:variable name=\"css-class7\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class7}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"traffic/tcp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]\">\n"
+ " <h4>TCP Responses Sent</h4>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"traffic/tcp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:variable name=\"css-class7\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class7}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type=&quot;sockstat&quot;]/counter[.&gt;0]\">\n"
+ " <h2>Socket I/O Statistics</h2>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"server/counters[@type=&quot;sockstat&quot;]/counter[.&gt;0]\">\n"
+ " <xsl:variable name=\"css-class7\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class7}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"views/view[zones/zone/counters[@type=&quot;qtype&quot;]/counter &gt;0]\">\n"
+ " <h2>Received QTYPES per view/zone</h2>\n"
+ " <xsl:for-each select=\"views/view[zones/zone/counters[@type=&quot;qtype&quot;]/counter &gt;0]\">\n"
+ " <h3>View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <xsl:variable name=\"thisview\">\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </xsl:variable>\n"
+ " <xsl:for-each select=\"zones/zone\">\n"
+ " <xsl:if test=\"counters[@type=&quot;qtype&quot;]/counter[count(.) &gt; 0]\">\n"
+ " <h4>Zone <xsl:value-of select=\"@name\"/></h4>\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <script type=\"text/javascript\">\n"
+ " graphs.push({\n"
+ " 'title': \"Query types for zone <xsl:value-of select=\"@name\"/>\",\n"
+ " 'target': 'chart_qtype_<xsl:value-of select=\"../../@name\"/>_<xsl:value-of select=\"@name\"/>',\n"
+ " 'style': 'barchart',\n"
+ " '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>]\n"
+ " });\n"
+ "\n"
+ " </script>\n"
+ " <xsl:variable name=\"target\">\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </xsl:variable>\n"
+ " <div class=\"pie\" id=\"chart_qtype_{$thisview}_{$target}\">[no data to display]</div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"counters[@type=&quot;qtype&quot;]/counter\">\n"
+ " <xsl:sort select=\".\"/>\n"
+ " <xsl:variable name=\"css-class10\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class10}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " </xsl:for-each>\n"
+ " </xsl:for-each>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"views/view[zones/zone/counters[@type=&quot;rcode&quot;]/counter &gt;0]\">\n"
+ " <h2>Response Codes per view/zone</h2>\n"
+ " <xsl:for-each select=\"views/view[zones/zone/counters[@type=&quot;rcode&quot;]/counter &gt;0]\">\n"
+ " <h3>View <xsl:value-of select=\"@name\"/></h3>\n"
+ " <xsl:variable name=\"thisview2\">\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </xsl:variable>\n"
+ " <xsl:for-each select=\"zones/zone\">\n"
+ " <xsl:if test=\"counters[@type=&quot;rcode&quot;]/counter[. &gt; 0]\">\n"
+ " <h4>Zone <xsl:value-of select=\"@name\"/></h4>\n"
+ " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <!-- Non Mozilla specific markup -->\n"
+ " <script type=\"text/javascript\">\n"
+ " graphs.push({\n"
+ " 'title': \"Response codes for zone <xsl:value-of select=\"@name\"/>\",\n"
+ " 'target': 'chart_rescode_<xsl:value-of select=\"../../@name\"/>_<xsl:value-of select=\"@name\"/>',\n"
+ " 'style': 'barchart',\n"
+ " '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>]\n"
+ " });\n"
+ "\n"
+ " </script>\n"
+ " <xsl:variable name=\"target\">\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </xsl:variable>\n"
+ " <div class=\"pie\" id=\"chart_rescode_{$thisview2}_{$target}\">[no data to display]</div>\n"
+ " </xsl:if>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"counters[@type=&quot;rcode&quot;]/counter[.&gt;0 and @name != &quot;QryAuthAns&quot;]\">\n"
+ " <xsl:sort select=\".\"/>\n"
+ " <xsl:variable name=\"css-class11\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class11}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"@name\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " </xsl:for-each>\n"
+ " </xsl:for-each>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"socketmgr/sockets/socket\">\n"
+ " <h2>Network Status</h2>\n"
+ " <table class=\"netstat\">\n"
+ " <tr>\n"
+ " <th>ID</th>\n"
+ " <th>Name</th>\n"
+ " <th>Type</th>\n"
+ " <th>References</th>\n"
+ " <th>LocalAddress</th>\n"
+ " <th>PeerAddress</th>\n"
+ " <th>State</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"socketmgr/sockets/socket\">\n"
+ " <xsl:sort select=\"id\"/>\n"
+ " <xsl:variable name=\"css-class12\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class12}\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"id\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"type\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"references\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"local-address\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"peer-address\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:for-each select=\"states\">\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </xsl:for-each>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"taskmgr/thread-model/type\">\n"
+ " <h2>Task Manager Configuration</h2>\n"
+ " <table class=\"counters\">\n"
+ " <tr>\n"
+ " <th class=\"even\">Thread-Model</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/type\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"odd\">\n"
+ " <th>Worker Threads</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/worker-threads\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"even\">\n"
+ " <th>Default Quantum</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/default-quantum\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"odd\">\n"
+ " <th>Tasks Running</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/tasks-running\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"even\">\n"
+ " <th>Tasks Ready</th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/tasks-ready\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"taskmgr/tasks/task\">\n"
+ " <h2>Tasks</h2>\n"
+ " <table class=\"tasks\">\n"
+ " <tr>\n"
+ " <th>ID</th>\n"
+ " <th>Name</th>\n"
+ " <th>References</th>\n"
+ " <th>State</th>\n"
+ " <th>Quantum</th>\n"
+ " <th>Events</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"taskmgr/tasks/task\">\n"
+ " <xsl:sort select=\"name\"/>\n"
+ " <xsl:variable name=\"css-class14\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class14}\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"id\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"references\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"state\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"quantum\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"events\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"memory/summary\">\n"
+ " <h2>Memory Usage Summary</h2>\n"
+ " <table class=\"counters\">\n"
+ " <xsl:for-each select=\"memory/summary/*\">\n"
+ " <xsl:variable name=\"css-class13\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class13}\">\n"
+ " <th>\n"
+ " <xsl:value-of select=\"name()\"/>\n"
+ " </th>\n"
+ " <td>\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"memory/contexts/context\">\n"
+ " <h2>Memory Contexts</h2>\n"
+ " <table class=\"mctx\">\n"
+ " <tr>\n"
+ " <th>ID</th>\n"
+ " <th>Name</th>\n"
+ " <th>References</th>\n"
+ " <th>TotalUse</th>\n"
+ " <th>InUse</th>\n"
+ " <th>MaxUse</th>\n"
+ " <th>BlockSize</th>\n"
+ " <th>Pools</th>\n"
+ " <th>HiWater</th>\n"
+ " <th>LoWater</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"memory/contexts/context\">\n"
+ " <xsl:sort select=\"total\" data-type=\"number\" order=\"descending\"/>\n"
+ " <xsl:variable name=\"css-class14\">\n"
+ " <xsl:choose>\n"
+ " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n"
+ " <xsl:otherwise>odd</xsl:otherwise>\n"
+ " </xsl:choose>\n"
+ " </xsl:variable>\n"
+ " <tr class=\"{$css-class14}\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"id\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"references\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"total\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"inuse\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"maxinuse\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"blocksize\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"pools\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"hiwater\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"lowater\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " </xsl:if>\n"
+ " <hr/>\n"
+ " <p class=\"footer\">Internet Systems Consortium Inc.<br/><a href=\"http://www.isc.org\">http://www.isc.org</a></p>\n"
+ " </body>\n"
+ " </html>\n"
+ " </xsl:template>\n"
+ "</xsl:stylesheet>\n";
diff --git a/bin/named/builtin.c b/bin/named/builtin.c
new file mode 100644
index 0000000..d6562ee
--- /dev/null
+++ b/bin/named/builtin.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file
+ * \brief
+ * The built-in "version", "hostname", "id", "authors" and "empty" databases.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+#include <dns/sdb.h>
+
+#include <named/builtin.h>
+#include <named/globals.h>
+#include <named/server.h>
+#include <named/os.h>
+
+typedef struct builtin builtin_t;
+
+static isc_result_t do_version_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_dns64_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 version_builtin = { do_version_lookup, NULL, NULL };
+static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
+static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
+static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
+static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
+static builtin_t dns64_builtin = { do_dns64_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*/
+};
+
+const unsigned char decimal[] = "0123456789";
+
+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);
+ }
+ 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 (ns_g_server->version_set) {
+ if (ns_g_server->version == NULL)
+ return (ISC_R_SUCCESS);
+ else
+ return (put_txt(lookup, ns_g_server->version));
+ } else {
+ return (put_txt(lookup, ns_g_version));
+ }
+}
+
+static isc_result_t
+do_hostname_lookup(dns_sdblookup_t *lookup) {
+ if (ns_g_server->hostname_set) {
+ if (ns_g_server->hostname == NULL)
+ return (ISC_R_SUCCESS);
+ else
+ return (put_txt(lookup, ns_g_server->hostname));
+ } else {
+ char buf[256];
+ isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ 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 (ns_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 (ns_g_server->server_usehostname) {
+ char buf[256];
+ isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (put_txt(lookup, buf));
+ }
+
+ if (ns_g_server->server_id == NULL)
+ return (ISC_R_SUCCESS);
+ else
+ return (put_txt(lookup, ns_g_server->server_id));
+}
+
+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
+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], "empty") == 0 || strcmp(argv[0], "dns64") == 0) {
+ if (argc != 3)
+ return (DNS_R_SYNTAX);
+ } else if (argc != 1)
+ return (DNS_R_SYNTAX);
+
+ if (strcmp(argv[0], "version") == 0)
+ *dbdata = &version_builtin;
+ else if (strcmp(argv[0], "hostname") == 0)
+ *dbdata = &hostname_builtin;
+ else if (strcmp(argv[0], "authors") == 0)
+ *dbdata = &authors_builtin;
+ else if (strcmp(argv[0], "id") == 0)
+ *dbdata = &id_builtin;
+ else if (strcmp(argv[0], "empty") == 0 ||
+ strcmp(argv[0], "dns64") == 0) {
+ builtin_t *empty;
+ char *server;
+ char *contact;
+ /*
+ * We don't want built-in zones to fail. Fallback to
+ * the static configuration if memory allocation fails.
+ */
+ empty = isc_mem_get(ns_g_mctx, sizeof(*empty));
+ server = isc_mem_strdup(ns_g_mctx, argv[1]);
+ contact = isc_mem_strdup(ns_g_mctx, argv[2]);
+ if (empty == NULL || server == NULL || contact == NULL) {
+ if (strcmp(argv[0], "empty") == 0)
+ *dbdata = &empty_builtin;
+ else
+ *dbdata = &dns64_builtin;
+ if (server != NULL)
+ isc_mem_free(ns_g_mctx, server);
+ if (contact != NULL)
+ isc_mem_free(ns_g_mctx, contact);
+ if (empty != NULL)
+ isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
+ } else {
+ if (strcmp(argv[0], "empty") == 0)
+ memmove(empty, &empty_builtin,
+ sizeof (empty_builtin));
+ else
+ memmove(empty, &dns64_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 == &version_builtin || *dbdata == &hostname_builtin ||
+ *dbdata == &authors_builtin || *dbdata == &id_builtin ||
+ *dbdata == &empty_builtin || *dbdata == &dns64_builtin)
+ return;
+
+ isc_mem_free(ns_g_mctx, b->server);
+ isc_mem_free(ns_g_mctx, b->contact);
+ isc_mem_put(ns_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
+ns_builtin_init(void) {
+ RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL,
+ DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA,
+ ns_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,
+ ns_g_mctx, &dns64_impl)
+ == ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_builtin_deinit(void) {
+ dns_sdb_unregister(&builtin_impl);
+ dns_sdb_unregister(&dns64_impl);
+}
diff --git a/bin/named/client.c b/bin/named/client.c
new file mode 100644
index 0000000..4d26eff
--- /dev/null
+++ b/bin/named/client.c
@@ -0,0 +1,3964 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/aes.h>
+#include <isc/formatcheck.h>
+#include <isc/hmacsha.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/queue.h>
+#include <isc/random.h>
+#include <isc/safe.h>
+#include <isc/serial.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/db.h>
+#include <dns/dispatch.h>
+#include <dns/dnstap.h>
+#include <dns/cache.h>
+#include <dns/edns.h>
+#include <dns/events.h>
+#include <dns/message.h>
+#include <dns/peer.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/stats.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include <named/fuzz.h>
+#include <named/interfacemgr.h>
+#include <named/log.h>
+#include <named/notify.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/update.h>
+
+/***
+ *** Client
+ ***/
+
+/*! \file
+ * Client Routines
+ *
+ * Important note!
+ *
+ * All client state changes, other than that from idle to listening, occur
+ * as a result of events. This guarantees serialization and avoids the
+ * need for locking.
+ *
+ * If a routine is ever created that allows someone other than the client's
+ * task to change the client, then the client will have to be locked.
+ */
+
+#define NS_CLIENT_TRACE
+#ifdef NS_CLIENT_TRACE
+#define CTRACE(m) ns_client_log(client, \
+ NS_LOGCATEGORY_CLIENT, \
+ NS_LOGMODULE_CLIENT, \
+ ISC_LOG_DEBUG(3), \
+ "%s", (m))
+#define MTRACE(m) isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_CLIENT, \
+ ISC_LOG_DEBUG(3), \
+ "clientmgr @%p: %s", manager, (m))
+#else
+#define CTRACE(m) ((void)(m))
+#define MTRACE(m) ((void)(m))
+#endif
+
+#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
+
+#define TCP_BUFFER_SIZE (65535 + 2)
+#define SEND_BUFFER_SIZE 4096
+#define RECV_BUFFER_SIZE 4096
+
+#ifdef ISC_PLATFORM_USETHREADS
+#define NMCTXS 100
+/*%<
+ * Number of 'mctx pools' for clients. (Should this be configurable?)
+ * When enabling threads, we use a pool of memory contexts shared by
+ * client objects, since concurrent access to a shared context would cause
+ * heavy contentions. The above constant is expected to be enough for
+ * completely avoiding contentions among threads for an authoritative-only
+ * server.
+ */
+#else
+#define NMCTXS 0
+/*%<
+ * If named with built without thread, simply share manager's context. Using
+ * a separate context in this case would simply waste memory.
+ */
+#endif
+
+#define COOKIE_SIZE 24U /* 8 + 4 + 4 + 8 */
+#define ECS_SIZE 20U /* 2 + 1 + 1 + [0..16] */
+
+#define WANTNSID(x) (((x)->attributes & NS_CLIENTATTR_WANTNSID) != 0)
+#define WANTEXPIRE(x) (((x)->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0)
+
+/*% nameserver client manager structure */
+struct ns_clientmgr {
+ /* Unlocked. */
+ unsigned int magic;
+
+ /* The queue object has its own locks */
+ client_queue_t inactive; /*%< To be recycled */
+
+ isc_mem_t * mctx;
+ isc_taskmgr_t * taskmgr;
+ isc_timermgr_t * timermgr;
+
+ /* Lock covers manager state. */
+ isc_mutex_t lock;
+ bool exiting;
+
+ /* Lock covers the clients list */
+ isc_mutex_t listlock;
+ client_list_t clients; /*%< All active clients */
+
+ /* Lock covers the recursing list */
+ isc_mutex_t reclock;
+ client_list_t recursing; /*%< Recursing clients */
+
+#if NMCTXS > 0
+ /*%< mctx pool for clients. */
+ unsigned int nextmctx;
+ isc_mem_t * mctxpool[NMCTXS];
+#endif
+};
+
+#define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
+#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
+
+/*!
+ * Client object states. Ordering is significant: higher-numbered
+ * states are generally "more active", meaning that the client can
+ * have more dynamically allocated data, outstanding events, etc.
+ * In the list below, any such properties listed for state N
+ * also apply to any state > N.
+ *
+ * To force the client into a less active state, set client->newstate
+ * to that state and call exit_check(). This will cause any
+ * activities defined for higher-numbered states to be aborted.
+ */
+
+#define NS_CLIENTSTATE_FREED 0
+/*%<
+ * The client object no longer exists.
+ */
+
+#define NS_CLIENTSTATE_INACTIVE 1
+/*%<
+ * The client object exists and has a task and timer.
+ * Its "query" struct and sendbuf are initialized.
+ * It is on the client manager's list of inactive clients.
+ * It has a message and OPT, both in the reset state.
+ */
+
+#define NS_CLIENTSTATE_READY 2
+/*%<
+ * The client object is either a TCP or a UDP one, and
+ * it is associated with a network interface. It is on the
+ * client manager's list of active clients.
+ *
+ * If it is a TCP client object, it has a TCP listener socket
+ * and an outstanding TCP listen request.
+ *
+ * If it is a UDP client object, it has a UDP listener socket
+ * and an outstanding UDP receive request.
+ */
+
+#define NS_CLIENTSTATE_READING 3
+/*%<
+ * The client object is a TCP client object that has received
+ * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
+ * outstanding TCP read request. This state is not used for
+ * UDP client objects.
+ */
+
+#define NS_CLIENTSTATE_WORKING 4
+/*%<
+ * The client object has received a request and is working
+ * on it. It has a view, and it may have any of a non-reset OPT,
+ * recursion quota, and an outstanding write request.
+ */
+
+#define NS_CLIENTSTATE_RECURSING 5
+/*%<
+ * The client object is recursing. It will be on the 'recursing'
+ * list.
+ */
+
+#define NS_CLIENTSTATE_MAX 9
+/*%<
+ * Sentinel value used to indicate "no state". When client->newstate
+ * has this value, we are not attempting to exit the current state.
+ * Must be greater than any valid state.
+ */
+
+/*
+ * Enable ns_client_dropport() by default.
+ */
+#ifndef NS_CLIENT_DROPPORT
+#define NS_CLIENT_DROPPORT 1
+#endif
+
+unsigned int ns_client_requests;
+
+static void client_read(ns_client_t *client);
+static void client_accept(ns_client_t *client);
+static void client_udprecv(ns_client_t *client);
+static void clientmgr_destroy(ns_clientmgr_t *manager);
+static bool exit_check(ns_client_t *client);
+static void ns_client_endrequest(ns_client_t *client);
+static void client_start(isc_task_t *task, isc_event_t *event);
+static void client_request(isc_task_t *task, isc_event_t *event);
+static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
+static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
+ dns_dispatch_t *disp, bool tcp);
+static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp,
+ isc_socket_t *sock);
+static inline bool
+allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr,
+ uint8_t ecs_addrlen, uint8_t *ecs_scope, dns_acl_t *acl);
+static void compute_cookie(ns_client_t *client, uint32_t when,
+ uint32_t nonce, const unsigned char *secret,
+ isc_buffer_t *buf);
+
+void
+ns_client_recursing(ns_client_t *client) {
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
+
+ LOCK(&client->manager->reclock);
+ client->newstate = client->state = NS_CLIENTSTATE_RECURSING;
+ ISC_LIST_APPEND(client->manager->recursing, client, rlink);
+ UNLOCK(&client->manager->reclock);
+}
+
+void
+ns_client_killoldestquery(ns_client_t *client) {
+ ns_client_t *oldest;
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ LOCK(&client->manager->reclock);
+ oldest = ISC_LIST_HEAD(client->manager->recursing);
+ if (oldest != NULL) {
+ ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
+ UNLOCK(&client->manager->reclock);
+ ns_query_cancel(oldest);
+ } else
+ UNLOCK(&client->manager->reclock);
+}
+
+void
+ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
+ isc_result_t result;
+ isc_interval_t interval;
+
+ isc_interval_set(&interval, seconds, 0);
+ result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
+ &interval, false);
+ client->timerset = true;
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
+ "setting timeout: %s",
+ isc_result_totext(result));
+ /* Continue anyway. */
+ }
+}
+
+/*%
+ * Check for a deactivation or shutdown request and take appropriate
+ * action. Returns true if either is in progress; in this case
+ * the caller must no longer use the client object as it may have been
+ * freed.
+ */
+static bool
+exit_check(ns_client_t *client) {
+ bool destroy_manager = false;
+ ns_clientmgr_t *manager = NULL;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ manager = client->manager;
+
+ if (client->state <= client->newstate)
+ return (false); /* Business as usual. */
+
+ INSIST(client->newstate < NS_CLIENTSTATE_RECURSING);
+
+ /*
+ * We need to detach from the view early when shutting down
+ * the server to break the following vicious circle:
+ *
+ * - The resolver will not shut down until the view refcount is zero
+ * - The view refcount does not go to zero until all clients detach
+ * - The client does not detach from the view until references is zero
+ * - references does not go to zero until the resolver has shut down
+ *
+ * Keep the view attached until any outstanding updates complete.
+ */
+ if (client->nupdates == 0 &&
+ client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
+ dns_view_detach(&client->view);
+
+ if (client->state == NS_CLIENTSTATE_WORKING ||
+ client->state == NS_CLIENTSTATE_RECURSING)
+ {
+ INSIST(client->newstate <= NS_CLIENTSTATE_READING);
+ /*
+ * Let the update processing complete.
+ */
+ if (client->nupdates > 0)
+ return (true);
+
+ /*
+ * We are trying to abort request processing.
+ */
+ if (client->nsends > 0) {
+ isc_socket_t *sock;
+ if (TCP_CLIENT(client))
+ sock = client->tcpsocket;
+ else
+ sock = client->udpsocket;
+ isc_socket_cancel(sock, client->task,
+ ISC_SOCKCANCEL_SEND);
+ }
+
+ if (! (client->nsends == 0 && client->nrecvs == 0 &&
+ client->references == 0))
+ {
+ /*
+ * Still waiting for I/O cancel completion.
+ * or lingering references.
+ */
+ return (true);
+ }
+
+ /*
+ * I/O cancel is complete. Burn down all state
+ * related to the current request. Ensure that
+ * the client is no longer on the recursing list.
+ *
+ * We need to check whether the client is still linked,
+ * because it may already have been removed from the
+ * recursing list by ns_client_killoldestquery()
+ */
+ if (client->state == NS_CLIENTSTATE_RECURSING) {
+ LOCK(&manager->reclock);
+ if (ISC_LINK_LINKED(client, rlink))
+ ISC_LIST_UNLINK(manager->recursing,
+ client, rlink);
+ UNLOCK(&manager->reclock);
+ }
+ ns_client_endrequest(client);
+
+ client->state = NS_CLIENTSTATE_READING;
+ INSIST(client->recursionquota == NULL);
+
+ if (NS_CLIENTSTATE_READING == client->newstate) {
+ if (!client->pipelined) {
+ client_read(client);
+ client->newstate = NS_CLIENTSTATE_MAX;
+ return (true); /* We're done. */
+ } else if (client->mortal) {
+ client->newstate = NS_CLIENTSTATE_INACTIVE;
+ } else
+ return (false);
+ }
+ }
+
+ if (client->state == NS_CLIENTSTATE_READING) {
+ /*
+ * We are trying to abort the current TCP connection,
+ * if any.
+ */
+ INSIST(client->recursionquota == NULL);
+ INSIST(client->newstate <= NS_CLIENTSTATE_READY);
+ if (client->nreads > 0)
+ dns_tcpmsg_cancelread(&client->tcpmsg);
+ if (client->nreads != 0) {
+ /* Still waiting for read cancel completion. */
+ return (true);
+ }
+
+ if (client->tcpmsg_valid) {
+ dns_tcpmsg_invalidate(&client->tcpmsg);
+ client->tcpmsg_valid = false;
+ }
+ if (client->tcpsocket != NULL) {
+ CTRACE("closetcp");
+ isc_socket_detach(&client->tcpsocket);
+ }
+
+ if (client->tcpquota != NULL)
+ isc_quota_detach(&client->tcpquota);
+
+ if (client->timerset) {
+ (void)isc_timer_reset(client->timer,
+ isc_timertype_inactive,
+ NULL, NULL, true);
+ client->timerset = false;
+ }
+
+ client->pipelined = false;
+
+ client->peeraddr_valid = false;
+
+ client->state = NS_CLIENTSTATE_READY;
+ INSIST(client->recursionquota == NULL);
+
+ /*
+ * Now the client is ready to accept a new TCP connection
+ * or UDP request, but we may have enough clients doing
+ * that already. Check whether this client needs to remain
+ * active and force it to go inactive if not.
+ *
+ * UDP clients go inactive at this point, but TCP clients
+ * may remain active if we have fewer active TCP client
+ * objects than desired due to an earlier quota exhaustion.
+ */
+ if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {
+ LOCK(&client->interface->lock);
+ if (client->interface->ntcpcurrent <
+ client->interface->ntcptarget)
+ client->mortal = false;
+ UNLOCK(&client->interface->lock);
+ }
+
+ /*
+ * We don't need the client; send it to the inactive
+ * queue for recycling.
+ */
+ if (client->mortal) {
+ if (client->newstate > NS_CLIENTSTATE_INACTIVE)
+ client->newstate = NS_CLIENTSTATE_INACTIVE;
+ }
+
+ if (NS_CLIENTSTATE_READY == client->newstate) {
+ if (TCP_CLIENT(client)) {
+ client_accept(client);
+ } else
+ client_udprecv(client);
+ client->newstate = NS_CLIENTSTATE_MAX;
+ return (true);
+ }
+ }
+
+ if (client->state == NS_CLIENTSTATE_READY) {
+ INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
+
+ /*
+ * We are trying to enter the inactive state.
+ */
+ if (client->naccepts > 0)
+ isc_socket_cancel(client->tcplistener, client->task,
+ ISC_SOCKCANCEL_ACCEPT);
+
+ /* Still waiting for accept cancel completion. */
+ if (! (client->naccepts == 0))
+ return (true);
+
+ /* Accept cancel is complete. */
+ if (client->nrecvs > 0)
+ isc_socket_cancel(client->udpsocket, client->task,
+ ISC_SOCKCANCEL_RECV);
+
+ /* Still waiting for recv cancel completion. */
+ if (! (client->nrecvs == 0))
+ return (true);
+
+ /* Still waiting for control event to be delivered */
+ if (client->nctls > 0)
+ return (true);
+
+ /* Deactivate the client. */
+ if (client->interface)
+ ns_interface_detach(&client->interface);
+
+ INSIST(client->naccepts == 0);
+ INSIST(client->recursionquota == NULL);
+ if (client->tcplistener != NULL)
+ isc_socket_detach(&client->tcplistener);
+
+ if (client->udpsocket != NULL)
+ isc_socket_detach(&client->udpsocket);
+
+ if (client->dispatch != NULL)
+ dns_dispatch_detach(&client->dispatch);
+
+ client->attributes = 0;
+ client->mortal = false;
+
+ if (client->keytag != NULL) {
+ isc_mem_put(client->mctx, client->keytag,
+ client->keytag_len);
+ client->keytag_len = 0;
+ }
+
+ /*
+ * Put the client on the inactive list. If we are aiming for
+ * the "freed" state, it will be removed from the inactive
+ * list shortly, and we need to keep the manager locked until
+ * that has been done, lest the manager decide to reactivate
+ * the dying client inbetween.
+ */
+ client->state = NS_CLIENTSTATE_INACTIVE;
+ INSIST(client->recursionquota == NULL);
+
+ if (client->state == client->newstate) {
+ client->newstate = NS_CLIENTSTATE_MAX;
+ if (!ns_g_clienttest && manager != NULL &&
+ !manager->exiting)
+ ISC_QUEUE_PUSH(manager->inactive, client,
+ ilink);
+ if (client->needshutdown)
+ isc_task_shutdown(client->task);
+ return (true);
+ }
+ }
+
+ if (client->state == NS_CLIENTSTATE_INACTIVE) {
+ INSIST(client->newstate == NS_CLIENTSTATE_FREED);
+ /*
+ * We are trying to free the client.
+ *
+ * When "shuttingdown" is true, either the task has received
+ * its shutdown event or no shutdown event has ever been
+ * set up. Thus, we have no outstanding shutdown
+ * event at this point.
+ */
+ REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
+
+ INSIST(client->recursionquota == NULL);
+ INSIST(!ISC_QLINK_LINKED(client, ilink));
+
+ if (manager != NULL) {
+ LOCK(&manager->listlock);
+ ISC_LIST_UNLINK(manager->clients, client, link);
+ LOCK(&manager->lock);
+ if (manager->exiting &&
+ ISC_LIST_EMPTY(manager->clients))
+ destroy_manager = true;
+ UNLOCK(&manager->lock);
+ UNLOCK(&manager->listlock);
+ }
+
+ ns_query_free(client);
+ isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
+ isc_event_free((isc_event_t **)&client->sendevent);
+ isc_event_free((isc_event_t **)&client->recvevent);
+ isc_timer_detach(&client->timer);
+ if (client->delaytimer != NULL)
+ isc_timer_detach(&client->delaytimer);
+
+ if (client->tcpbuf != NULL)
+ isc_mem_put(client->mctx, client->tcpbuf,
+ TCP_BUFFER_SIZE);
+ if (client->opt != NULL) {
+ INSIST(dns_rdataset_isassociated(client->opt));
+ dns_rdataset_disassociate(client->opt);
+ dns_message_puttemprdataset(client->message,
+ &client->opt);
+ }
+ if (client->keytag != NULL) {
+ isc_mem_put(client->mctx, client->keytag,
+ client->keytag_len);
+ client->keytag_len = 0;
+ }
+
+ dns_message_destroy(&client->message);
+
+ /*
+ * Detaching the task must be done after unlinking from
+ * the manager's lists because the manager accesses
+ * client->task.
+ */
+ if (client->task != NULL)
+ isc_task_detach(&client->task);
+
+ CTRACE("free");
+ client->magic = 0;
+
+ /*
+ * Check that there are no other external references to
+ * the memory context.
+ */
+ if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
+ isc_mem_stats(client->mctx, stderr);
+ INSIST(0);
+ }
+
+ /*
+ * Destroy the fetchlock mutex that was created in
+ * ns_query_init().
+ */
+ DESTROYLOCK(&client->query.fetchlock);
+
+ isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
+ }
+
+ if (destroy_manager && manager != NULL)
+ clientmgr_destroy(manager);
+
+ return (true);
+}
+
+/*%
+ * The client's task has received the client's control event
+ * as part of the startup process.
+ */
+static void
+client_start(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client = (ns_client_t *) event->ev_arg;
+
+ INSIST(task == client->task);
+
+ UNUSED(task);
+
+ INSIST(client->nctls == 1);
+ client->nctls--;
+
+ if (exit_check(client))
+ return;
+
+ if (TCP_CLIENT(client)) {
+ if (client->pipelined) {
+ client_read(client);
+ } else {
+ client_accept(client);
+ }
+ } else {
+ client_udprecv(client);
+ }
+}
+
+
+/*%
+ * The client's task has received a shutdown event.
+ */
+static void
+client_shutdown(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+
+ UNUSED(task);
+
+ CTRACE("shutdown");
+
+ isc_event_free(&event);
+
+ if (client->shutdown != NULL) {
+ (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
+ client->shutdown = NULL;
+ client->shutdown_arg = NULL;
+ }
+
+ if (ISC_QLINK_LINKED(client, ilink))
+ ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink);
+
+ client->newstate = NS_CLIENTSTATE_FREED;
+ client->needshutdown = false;
+ (void)exit_check(client);
+}
+
+static void
+ns_client_endrequest(ns_client_t *client) {
+ INSIST(client->naccepts == 0);
+ INSIST(client->nreads == 0);
+ INSIST(client->nsends == 0);
+ INSIST(client->nrecvs == 0);
+ INSIST(client->nupdates == 0);
+ INSIST(client->state == NS_CLIENTSTATE_WORKING ||
+ client->state == NS_CLIENTSTATE_RECURSING);
+
+ CTRACE("endrequest");
+
+ if (client->next != NULL) {
+ (client->next)(client);
+ client->next = NULL;
+ }
+
+ if (client->view != NULL) {
+#ifdef ENABLE_AFL
+ if (ns_g_fuzz_type == ns_fuzz_resolver) {
+ dns_cache_clean(client->view->cache, INT_MAX);
+ dns_adb_flush(client->view->adb);
+ }
+#endif
+ dns_view_detach(&client->view);
+ }
+ if (client->opt != NULL) {
+ INSIST(dns_rdataset_isassociated(client->opt));
+ dns_rdataset_disassociate(client->opt);
+ dns_message_puttemprdataset(client->message, &client->opt);
+ }
+
+ client->signer = NULL;
+ client->udpsize = 512;
+ client->extflags = 0;
+ client->ednsversion = -1;
+ dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
+
+ if (client->recursionquota != NULL) {
+ isc_quota_detach(&client->recursionquota);
+ isc_stats_decrement(ns_g_server->nsstats,
+ dns_nsstatscounter_recursclients);
+ }
+
+ /*
+ * Clear all client attributes that are specific to
+ * the request; that's all except the TCP flag.
+ */
+ client->attributes &= NS_CLIENTATTR_TCP;
+#ifdef ENABLE_AFL
+ if (ns_g_fuzz_type == ns_fuzz_client ||
+ ns_g_fuzz_type == ns_fuzz_tcpclient ||
+ ns_g_fuzz_type == ns_fuzz_resolver) {
+ named_fuzz_notify();
+ }
+#endif /* ENABLE_AFL */
+
+}
+
+void
+ns_client_next(ns_client_t *client, isc_result_t result) {
+ int newstate;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
+ client->state == NS_CLIENTSTATE_RECURSING ||
+ client->state == NS_CLIENTSTATE_READING);
+
+ CTRACE("next");
+
+ if (result != ISC_R_SUCCESS)
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request failed: %s", isc_result_totext(result));
+
+ /*
+ * An error processing a TCP request may have left
+ * the connection out of sync. To be safe, we always
+ * sever the connection when result != ISC_R_SUCCESS.
+ */
+ if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
+ newstate = NS_CLIENTSTATE_READING;
+ else
+ newstate = NS_CLIENTSTATE_READY;
+
+ if (client->newstate > newstate)
+ client->newstate = newstate;
+ (void)exit_check(client);
+}
+
+
+static void
+client_senddone(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+ isc_socketevent_t *sevent = (isc_socketevent_t *) event;
+
+ REQUIRE(sevent != NULL);
+ REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
+ client = sevent->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(sevent == client->sendevent);
+
+ UNUSED(task);
+
+ CTRACE("senddone");
+
+ if (sevent->result != ISC_R_SUCCESS)
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
+ "error sending response: %s",
+ isc_result_totext(sevent->result));
+
+ INSIST(client->nsends > 0);
+ client->nsends--;
+
+ if (client->tcpbuf != NULL) {
+ INSIST(TCP_CLIENT(client));
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ client->tcpbuf = NULL;
+ }
+
+ ns_client_next(client, ISC_R_SUCCESS);
+}
+
+/*%
+ * We only want to fail with ISC_R_NOSPACE when called from
+ * ns_client_sendraw() and not when called from ns_client_send(),
+ * tcpbuffer is NULL when called from ns_client_sendraw() and
+ * length != 0. tcpbuffer != NULL when called from ns_client_send()
+ * and length == 0.
+ */
+
+static isc_result_t
+client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
+ isc_buffer_t *tcpbuffer, uint32_t length,
+ unsigned char *sendbuf, unsigned char **datap)
+{
+ unsigned char *data;
+ uint32_t bufsize;
+ isc_result_t result;
+
+ INSIST(datap != NULL);
+ INSIST((tcpbuffer == NULL && length != 0) ||
+ (tcpbuffer != NULL && length == 0));
+
+ if (TCP_CLIENT(client)) {
+ INSIST(client->tcpbuf == NULL);
+ if (length + 2 > TCP_BUFFER_SIZE) {
+ result = ISC_R_NOSPACE;
+ goto done;
+ }
+ client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
+ if (client->tcpbuf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto done;
+ }
+ data = client->tcpbuf;
+ if (tcpbuffer != NULL) {
+ isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
+ isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
+ } else {
+ isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
+ INSIST(length <= 0xffff);
+ isc_buffer_putuint16(buffer, (uint16_t)length);
+ }
+ } else {
+ data = sendbuf;
+ if ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) == 0) {
+ if (client->view != NULL)
+ bufsize = client->view->nocookieudp;
+ else
+ bufsize = 512;
+ } else
+ bufsize = client->udpsize;
+ if (bufsize > client->udpsize)
+ bufsize = client->udpsize;
+ if (bufsize > SEND_BUFFER_SIZE)
+ bufsize = SEND_BUFFER_SIZE;
+ if (length > bufsize) {
+ result = ISC_R_NOSPACE;
+ goto done;
+ }
+ isc_buffer_init(buffer, data, bufsize);
+ }
+ *datap = data;
+ result = ISC_R_SUCCESS;
+
+ done:
+ return (result);
+}
+
+static isc_result_t
+client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
+ struct in6_pktinfo *pktinfo;
+ isc_result_t result;
+ isc_region_t r;
+ isc_sockaddr_t *address;
+ isc_socket_t *sock;
+ isc_netaddr_t netaddr;
+ int match;
+ unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
+ isc_dscp_t dispdscp = -1;
+
+ if (TCP_CLIENT(client)) {
+ sock = client->tcpsocket;
+ address = NULL;
+ } else {
+ sock = client->udpsocket;
+ address = &client->peeraddr;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ if (ns_g_server->blackholeacl != NULL &&
+ dns_acl_match(&netaddr, NULL,
+ ns_g_server->blackholeacl,
+ &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ return (DNS_R_BLACKHOLED);
+ sockflags |= ISC_SOCKFLAG_NORETRY;
+ }
+
+ if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
+ (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
+ pktinfo = &client->pktinfo;
+ else
+ pktinfo = NULL;
+
+ if (client->dispatch != NULL) {
+ dispdscp = dns_dispatch_getdscp(client->dispatch);
+ if (dispdscp != -1)
+ client->dscp = dispdscp;
+ }
+
+ if (client->dscp == -1) {
+ client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
+ client->sendevent->dscp = 0;
+ } else {
+ client->sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
+ client->sendevent->dscp = client->dscp;
+ }
+
+ isc_buffer_usedregion(buffer, &r);
+
+ /*
+ * If this is a UDP client and the IPv6 packet can't be
+ * encapsulated without generating a PTB on a 1500 octet
+ * MTU link force fragmentation at 1280 if it is a IPv6
+ * response.
+ */
+ client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_USEMINMTU;
+ if (!TCP_CLIENT(client) && r.length > 1432)
+ client->sendevent->attributes |= ISC_SOCKEVENTATTR_USEMINMTU;
+
+ CTRACE("sendto");
+
+ result = isc_socket_sendto2(sock, &r, client->task,
+ address, pktinfo,
+ client->sendevent, sockflags);
+ if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
+ client->nsends++;
+ if (result == ISC_R_SUCCESS)
+ client_senddone(client->task,
+ (isc_event_t *)client->sendevent);
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+void
+ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
+ isc_result_t result;
+ unsigned char *data;
+ isc_buffer_t buffer;
+ isc_region_t r;
+ isc_region_t *mr;
+ unsigned char sendbuf[SEND_BUFFER_SIZE];
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE("sendraw");
+
+ mr = dns_message_getrawmessage(message);
+ if (mr == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto done;
+ }
+
+ result = client_allocsendbuf(client, &buffer, NULL, mr->length,
+ sendbuf, &data);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ /*
+ * Copy message to buffer and fixup id.
+ */
+ isc_buffer_availableregion(&buffer, &r);
+ result = isc_buffer_copyregion(&buffer, mr);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ r.base[0] = (client->message->id >> 8) & 0xff;
+ r.base[1] = client->message->id & 0xff;
+
+ result = client_sendpkg(client, &buffer);
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ done:
+ if (client->tcpbuf != NULL) {
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ client->tcpbuf = NULL;
+ }
+ ns_client_next(client, result);
+}
+
+static void
+client_send(ns_client_t *client) {
+ isc_result_t result;
+ unsigned char *data;
+ isc_buffer_t buffer;
+ isc_buffer_t tcpbuffer;
+ isc_region_t r;
+ dns_compress_t cctx;
+ bool cleanup_cctx = false;
+ unsigned char sendbuf[SEND_BUFFER_SIZE];
+ unsigned int render_opts;
+ unsigned int preferred_glue;
+ bool opt_included = false;
+ size_t respsize;
+#ifdef HAVE_DNSTAP
+ unsigned char zone[DNS_NAME_MAXWIRE];
+ dns_dtmsgtype_t dtmsgtype;
+ isc_region_t zr;
+#endif /* HAVE_DNSTAP */
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE("send");
+
+ if (client->message->opcode == dns_opcode_query &&
+ (client->attributes & NS_CLIENTATTR_RA) != 0)
+ client->message->flags |= DNS_MESSAGEFLAG_RA;
+
+ if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
+ render_opts = 0;
+ else
+ render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
+
+ preferred_glue = 0;
+ if (client->view != NULL) {
+ if (client->view->preferred_glue == dns_rdatatype_a)
+ preferred_glue = DNS_MESSAGERENDER_PREFER_A;
+ else if (client->view->preferred_glue == dns_rdatatype_aaaa)
+ preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
+ }
+ if (preferred_glue == 0) {
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET)
+ preferred_glue = DNS_MESSAGERENDER_PREFER_A;
+ else
+ preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
+ }
+
+#ifdef ALLOW_FILTER_AAAA
+ /*
+ * filter-aaaa-on-v4 yes or break-dnssec option to suppress
+ * AAAA records.
+ *
+ * We already know that request came via IPv4,
+ * that we have both AAAA and A records,
+ * and that we either have no signatures that the client wants
+ * or we are supposed to break DNSSEC.
+ *
+ * Override preferred glue if necessary.
+ */
+ if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
+ render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
+ if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
+ preferred_glue = DNS_MESSAGERENDER_PREFER_A;
+ }
+#endif
+
+ /*
+ * Create an OPT for our reply.
+ */
+ if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
+ result = ns_client_addopt(client, client->message,
+ &client->opt);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+
+ /*
+ * XXXRTH The following doesn't deal with TCP buffer resizing.
+ */
+ result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
+ sendbuf, &data);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ result = dns_compress_init(&cctx, -1, client->mctx);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ if (client->peeraddr_valid && client->view != NULL) {
+ isc_netaddr_t netaddr;
+ dns_name_t *name = NULL;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ if (client->message->tsigkey != NULL)
+ name = &client->message->tsigkey->name;
+
+ if (client->view->nocasecompress == NULL ||
+ !allowed(&netaddr, name, NULL, 0, NULL,
+ client->view->nocasecompress))
+ {
+ dns_compress_setsensitive(&cctx, true);
+ }
+
+ if (client->view->msgcompression == false) {
+ dns_compress_disable(&cctx);
+ }
+ }
+ cleanup_cctx = true;
+
+ result = dns_message_renderbegin(client->message, &cctx, &buffer);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ if (client->opt != NULL) {
+ result = dns_message_setopt(client->message, client->opt);
+ opt_included = true;
+ client->opt = NULL;
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_QUESTION, 0);
+ if (result == ISC_R_NOSPACE) {
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ goto renderend;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ /*
+ * Stop after the question if TC was set for rate limiting.
+ */
+ if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
+ goto renderend;
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_ANSWER,
+ DNS_MESSAGERENDER_PARTIAL |
+ render_opts);
+ if (result == ISC_R_NOSPACE) {
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ goto renderend;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_AUTHORITY,
+ DNS_MESSAGERENDER_PARTIAL |
+ render_opts);
+ if (result == ISC_R_NOSPACE) {
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ goto renderend;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_ADDITIONAL,
+ preferred_glue | render_opts);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
+ goto done;
+ renderend:
+ result = dns_message_renderend(client->message);
+
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+#ifdef HAVE_DNSTAP
+ memset(&zr, 0, sizeof(zr));
+ if (((client->message->flags & DNS_MESSAGEFLAG_AA) != 0) &&
+ (client->query.authzone != NULL))
+ {
+ isc_buffer_t b;
+ dns_name_t *zo =
+ dns_zone_getorigin(client->query.authzone);
+
+ isc_buffer_init(&b, zone, sizeof(zone));
+ dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE);
+ result = dns_name_towire(zo, &cctx, &b);
+ if (result == ISC_R_SUCCESS)
+ isc_buffer_usedregion(&b, &zr);
+ }
+
+ if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0)
+ dtmsgtype = DNS_DTTYPE_CR;
+ else
+ dtmsgtype = DNS_DTTYPE_AR;
+#endif /* HAVE_DNSTAP */
+
+ if (cleanup_cctx) {
+ dns_compress_invalidate(&cctx);
+ cleanup_cctx = false;
+ }
+
+ if (TCP_CLIENT(client)) {
+ isc_buffer_usedregion(&buffer, &r);
+ isc_buffer_putuint16(&tcpbuffer, (uint16_t) r.length);
+ isc_buffer_add(&tcpbuffer, r.length);
+#ifdef HAVE_DNSTAP
+ if (client->view != NULL) {
+ dns_dt_send(client->view, dtmsgtype,
+ &client->peeraddr, &client->destsockaddr,
+ true, &zr, &client->requesttime, NULL,
+ &buffer);
+ }
+#endif /* HAVE_DNSTAP */
+
+ /* don't count the 2-octet length header */
+ respsize = isc_buffer_usedlength(&tcpbuffer) - 2;
+ result = client_sendpkg(client, &tcpbuffer);
+
+ switch (isc_sockaddr_pf(&client->peeraddr)) {
+ case AF_INET:
+ isc_stats_increment(ns_g_server->tcpoutstats4,
+ ISC_MIN((int)respsize / 16, 256));
+ break;
+ case AF_INET6:
+ isc_stats_increment(ns_g_server->tcpoutstats6,
+ ISC_MIN((int)respsize / 16, 256));
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+ } else {
+ respsize = isc_buffer_usedlength(&buffer);
+ result = client_sendpkg(client, &buffer);
+#ifdef HAVE_DNSTAP
+ if (client->view != NULL) {
+ dns_dt_send(client->view, dtmsgtype,
+ &client->peeraddr,
+ &client->destsockaddr,
+ false, &zr,
+ &client->requesttime, NULL, &buffer);
+ }
+#endif /* HAVE_DNSTAP */
+
+ switch (isc_sockaddr_pf(&client->peeraddr)) {
+ case AF_INET:
+ isc_stats_increment(ns_g_server->udpoutstats4,
+ ISC_MIN((int)respsize / 16, 256));
+ break;
+ case AF_INET6:
+ isc_stats_increment(ns_g_server->udpoutstats6,
+ ISC_MIN((int)respsize / 16, 256));
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+ }
+
+ /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
+ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
+
+ dns_rcodestats_increment(ns_g_server->rcodestats,
+ client->message->rcode);
+ if (opt_included) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_edns0out);
+ }
+ if (client->message->tsigkey != NULL) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_tsigout);
+ }
+ if (client->message->sig0key != NULL) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_sig0out);
+ }
+ if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_truncatedresp);
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ done:
+ if (client->tcpbuf != NULL) {
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ client->tcpbuf = NULL;
+ }
+
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+
+ ns_client_next(client, result);
+}
+
+/*
+ * Completes the sending of a delayed client response.
+ */
+static void
+client_delay(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
+ event->ev_type == ISC_TIMEREVENT_IDLE);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(client->delaytimer != NULL);
+
+ UNUSED(task);
+
+ CTRACE("client_delay");
+
+ isc_event_free(&event);
+ isc_timer_detach(&client->delaytimer);
+
+ client_send(client);
+ ns_client_detach(&client);
+}
+
+void
+ns_client_send(ns_client_t *client) {
+
+ /*
+ * Delay the response by ns_g_delay ms.
+ */
+ if (ns_g_delay != 0) {
+ ns_client_t *dummy = NULL;
+ isc_result_t result;
+ isc_interval_t interval;
+
+ /*
+ * Replace ourselves if we have not already been replaced.
+ */
+ if (!client->mortal) {
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS)
+ goto nodelay;
+ }
+
+ ns_client_attach(client, &dummy);
+ if (ns_g_delay >= 1000)
+ isc_interval_set(&interval, ns_g_delay / 1000,
+ (ns_g_delay % 1000) * 1000000);
+ else
+ isc_interval_set(&interval, 0, ns_g_delay * 1000000);
+ result = isc_timer_create(client->manager->timermgr,
+ isc_timertype_once, NULL, &interval,
+ client->task, client_delay,
+ client, &client->delaytimer);
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ ns_client_detach(&dummy);
+ }
+
+ nodelay:
+ client_send(client);
+}
+
+#if NS_CLIENT_DROPPORT
+#define DROPPORT_NO 0
+#define DROPPORT_REQUEST 1
+#define DROPPORT_RESPONSE 2
+/*%
+ * ns_client_dropport determines if certain requests / responses
+ * should be dropped based on the port number.
+ *
+ * Returns:
+ * \li 0: Don't drop.
+ * \li 1: Drop request.
+ * \li 2: Drop (error) response.
+ */
+static int
+ns_client_dropport(in_port_t port) {
+ switch (port) {
+ case 7: /* echo */
+ case 13: /* daytime */
+ case 19: /* chargen */
+ case 37: /* time */
+ return (DROPPORT_REQUEST);
+ case 464: /* kpasswd */
+ return (DROPPORT_RESPONSE);
+ }
+ return (DROPPORT_NO);
+}
+#endif
+
+void
+ns_client_error(ns_client_t *client, isc_result_t result) {
+ dns_rcode_t rcode;
+ dns_message_t *message;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE("error");
+
+ message = client->message;
+ rcode = dns_result_torcode(result);
+
+#if NS_CLIENT_DROPPORT
+ /*
+ * Don't send FORMERR to ports on the drop port list.
+ */
+ if (rcode == dns_rcode_formerr &&
+ ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
+ DROPPORT_NO) {
+ char buf[64];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, buf, sizeof(buf) - 1);
+ if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
+ isc_buffer_putstr(&b, "UNKNOWN RCODE");
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "dropped error (%.*s) response: suspicious port",
+ (int)isc_buffer_usedlength(&b), buf);
+ ns_client_next(client, ISC_R_SUCCESS);
+ return;
+ }
+#endif
+
+ /*
+ * Try to rate limit error responses.
+ */
+ if (client->view != NULL && client->view->rrl != NULL) {
+ bool wouldlog;
+ char log_buf[DNS_RRL_LOG_BUF_LEN];
+ dns_rrl_result_t rrl_result;
+ int loglevel;
+
+ INSIST(rcode != dns_rcode_noerror &&
+ rcode != dns_rcode_nxdomain);
+ if (ns_g_server->log_queries)
+ loglevel = DNS_RRL_LOG_DROP;
+ else
+ loglevel = ISC_LOG_DEBUG(1);
+ wouldlog = isc_log_wouldlog(ns_g_lctx, loglevel);
+ rrl_result = dns_rrl(client->view, &client->peeraddr,
+ TCP_CLIENT(client),
+ dns_rdataclass_in, dns_rdatatype_none,
+ NULL, result, client->now,
+ wouldlog, log_buf, sizeof(log_buf));
+ if (rrl_result != DNS_RRL_RESULT_OK) {
+ /*
+ * Log dropped errors in the query category
+ * so that they are not lost in silence.
+ * Starts of rate-limited bursts are logged in
+ * NS_LOGCATEGORY_RRL.
+ */
+ if (wouldlog) {
+ ns_client_log(client,
+ NS_LOGCATEGORY_QUERY_ERRORS,
+ NS_LOGMODULE_CLIENT,
+ loglevel,
+ "%s", log_buf);
+ }
+ /*
+ * Some error responses cannot be 'slipped',
+ * so don't try to slip any error responses.
+ */
+ if (!client->view->rrl->log_only) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_ratedropped);
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_dropped);
+ ns_client_next(client, DNS_R_DROP);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Message may be an in-progress reply that we had trouble
+ * with, in which case QR will be set. We need to clear QR before
+ * calling dns_message_reply() to avoid triggering an assertion.
+ */
+ message->flags &= ~DNS_MESSAGEFLAG_QR;
+ /*
+ * AA and AD shouldn't be set.
+ */
+ message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
+ result = dns_message_reply(message, true);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * It could be that we've got a query with a good header,
+ * but a bad question section, so we try again with
+ * want_question_section set to false.
+ */
+ result = dns_message_reply(message, false);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_next(client, result);
+ return;
+ }
+ }
+ message->rcode = rcode;
+
+ if (rcode == dns_rcode_formerr) {
+ /*
+ * FORMERR loop avoidance: If we sent a FORMERR message
+ * with the same ID to the same client less than two
+ * seconds ago, assume that we are in an infinite error
+ * packet dialog with a server for some protocol whose
+ * error responses look enough like DNS queries to
+ * elicit a FORMERR response. Drop a packet to break
+ * the loop.
+ */
+ if (isc_sockaddr_equal(&client->peeraddr,
+ &client->formerrcache.addr) &&
+ message->id == client->formerrcache.id &&
+ (isc_time_seconds(&client->requesttime) -
+ client->formerrcache.time) < 2)
+ {
+ /* Drop packet. */
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "possible error packet loop, "
+ "FORMERR dropped");
+ ns_client_next(client, result);
+ return;
+ }
+ client->formerrcache.addr = client->peeraddr;
+ client->formerrcache.time =
+ isc_time_seconds(&client->requesttime);
+ client->formerrcache.id = message->id;
+ } else if (rcode == dns_rcode_servfail && client->query.qname != NULL &&
+ client->view != NULL && client->view->fail_ttl != 0 &&
+ ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0))
+ {
+ /*
+ * SERVFAIL caching: store qname/qtype of failed queries
+ */
+ isc_time_t expire;
+ isc_interval_t i;
+ uint32_t flags = 0;
+
+ if ((message->flags & DNS_MESSAGEFLAG_CD) != 0)
+ flags = NS_FAILCACHE_CD;
+
+ isc_interval_set(&i, client->view->fail_ttl, 0);
+ result = isc_time_nowplusinterval(&expire, &i);
+ if (result == ISC_R_SUCCESS)
+ dns_badcache_add(client->view->failcache,
+ client->query.qname,
+ client->query.qtype,
+ true, flags, &expire);
+ }
+ ns_client_send(client);
+}
+
+isc_result_t
+ns_client_addopt(ns_client_t *client, dns_message_t *message,
+ dns_rdataset_t **opt)
+{
+ unsigned char ecs[ECS_SIZE];
+ char nsid[BUFSIZ], *nsidp;
+ unsigned char cookie[COOKIE_SIZE];
+ isc_result_t result;
+ dns_view_t *view;
+ dns_resolver_t *resolver;
+ uint16_t udpsize;
+ dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
+ int count = 0;
+ unsigned int flags;
+ unsigned char expire[4];
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(opt != NULL && *opt == NULL);
+ REQUIRE(message != NULL);
+
+ view = client->view;
+ resolver = (view != NULL) ? view->resolver : NULL;
+ if (resolver != NULL)
+ udpsize = dns_resolver_getudpsize(resolver);
+ else
+ udpsize = ns_g_udpsize;
+
+ flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
+
+ /* Set EDNS options if applicable */
+ if (WANTNSID(client) &&
+ (ns_g_server->server_id != NULL ||
+ ns_g_server->server_usehostname)) {
+ if (ns_g_server->server_usehostname) {
+ result = ns_os_gethostname(nsid, sizeof(nsid));
+ if (result != ISC_R_SUCCESS) {
+ goto no_nsid;
+ }
+ nsidp = nsid;
+ } else
+ nsidp = ns_g_server->server_id;
+
+ INSIST(count < DNS_EDNSOPTIONS);
+ ednsopts[count].code = DNS_OPT_NSID;
+ ednsopts[count].length = (uint16_t)strlen(nsidp);
+ ednsopts[count].value = (unsigned char *)nsidp;
+ count++;
+ }
+ no_nsid:
+ if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) {
+ isc_buffer_t buf;
+ isc_stdtime_t now;
+ uint32_t nonce;
+
+ isc_buffer_init(&buf, cookie, sizeof(cookie));
+ isc_stdtime_get(&now);
+ isc_random_get(&nonce);
+
+ compute_cookie(client, now, nonce, ns_g_server->secret, &buf);
+
+ INSIST(count < DNS_EDNSOPTIONS);
+ ednsopts[count].code = DNS_OPT_COOKIE;
+ ednsopts[count].length = COOKIE_SIZE;
+ ednsopts[count].value = cookie;
+ count++;
+ }
+ if ((client->attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) {
+ isc_buffer_t buf;
+
+ INSIST(count < DNS_EDNSOPTIONS);
+
+ isc_buffer_init(&buf, expire, sizeof(expire));
+ isc_buffer_putuint32(&buf, client->expire);
+ ednsopts[count].code = DNS_OPT_EXPIRE;
+ ednsopts[count].length = 4;
+ ednsopts[count].value = expire;
+ count++;
+ }
+ if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
+ (client->ecs_addr.family == AF_INET ||
+ client->ecs_addr.family == AF_INET6 ||
+ client->ecs_addr.family == AF_UNSPEC))
+ {
+ isc_buffer_t buf;
+ uint8_t addr[16];
+ uint32_t plen, addrl;
+ uint16_t family;
+
+ /* Add CLIENT-SUBNET option. */
+
+ plen = client->ecs_addrlen;
+
+ /* Round up prefix len to a multiple of 8 */
+ addrl = (plen + 7) / 8;
+
+ switch (client->ecs_addr.family) {
+ case AF_UNSPEC:
+ INSIST(plen == 0);
+ family = 0;
+ break;
+ case AF_INET:
+ INSIST(plen <= 32);
+ family = 1;
+ memmove(addr, &client->ecs_addr.type, addrl);
+ break;
+ case AF_INET6:
+ INSIST(plen <= 128);
+ family = 2;
+ memmove(addr, &client->ecs_addr.type, addrl);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ isc_buffer_init(&buf, ecs, sizeof(ecs));
+ /* family */
+ isc_buffer_putuint16(&buf, family);
+ /* source prefix-length */
+ isc_buffer_putuint8(&buf, client->ecs_addrlen);
+ /* scope prefix-length */
+ isc_buffer_putuint8(&buf, client->ecs_scope);
+
+ /* address */
+ if (addrl > 0) {
+ /* Mask off last address byte */
+ if ((plen % 8) != 0)
+ addr[addrl - 1] &=
+ ~0U << (8 - (plen % 8));
+ isc_buffer_putmem(&buf, addr,
+ (unsigned) addrl);
+ }
+
+ ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
+ ednsopts[count].length = addrl + 4;
+ ednsopts[count].value = ecs;
+ count++;
+ }
+
+ result = dns_message_buildopt(message, opt, 0, udpsize, flags,
+ ednsopts, count);
+ return (result);
+}
+
+static inline bool
+allowed(isc_netaddr_t *addr, dns_name_t *signer,
+ isc_netaddr_t *ecs_addr, uint8_t ecs_addrlen,
+ uint8_t *ecs_scope, dns_acl_t *acl)
+{
+ int match;
+ isc_result_t result;
+
+ if (acl == NULL)
+ return (true);
+ result = dns_acl_match2(addr, signer, ecs_addr, ecs_addrlen, ecs_scope,
+ acl, &ns_g_server->aclenv, &match, NULL);
+ if (result == ISC_R_SUCCESS && match > 0)
+ return (true);
+ return (false);
+}
+
+/*
+ * 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.
+ */
+bool
+ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
+ dns_rdataclass_t rdclass, void *arg)
+{
+ dns_view_t *view;
+ dns_tsigkey_t *key = NULL;
+ dns_name_t *tsig = NULL;
+ isc_netaddr_t netsrc;
+ isc_netaddr_t netdst;
+
+ UNUSED(arg);
+
+ /*
+ * ns_g_server->interfacemgr is task exclusive locked.
+ */
+ if (ns_g_server->interfacemgr == NULL)
+ return (true);
+
+ if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
+ return (false);
+
+ isc_netaddr_fromsockaddr(&netsrc, srcaddr);
+ isc_netaddr_fromsockaddr(&netdst, dstaddr);
+
+ for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+
+ 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 (allowed(&netsrc, tsig, NULL, 0, NULL,
+ view->matchclients) &&
+ allowed(&netdst, tsig, NULL, 0, NULL,
+ view->matchdestinations))
+ break;
+ }
+ return (view == myview);
+}
+
+static void
+compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
+ const unsigned char *secret, isc_buffer_t *buf)
+{
+ switch (ns_g_server->cookiealg) {
+#if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES)
+ case ns_cookiealg_aes: {
+ unsigned char digest[ISC_AES_BLOCK_LENGTH];
+ unsigned char input[4 + 4 + 16];
+ isc_netaddr_t netaddr;
+ unsigned char *cp;
+ unsigned int i;
+
+ memset(input, 0, sizeof(input));
+ cp = isc_buffer_used(buf);
+ isc_buffer_putmem(buf, client->cookie, 8);
+ isc_buffer_putuint32(buf, nonce);
+ isc_buffer_putuint32(buf, when);
+ memmove(input, cp, 16);
+ isc_aes128_crypt(secret, input, digest);
+ for (i = 0; i < 8; i++)
+ input[i] = digest[i] ^ digest[i + 8];
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (netaddr.family) {
+ case AF_INET:
+ cp = (unsigned char *)&netaddr.type.in;
+ memmove(input + 8, cp, 4);
+ memset(input + 12, 0, 4);
+ isc_aes128_crypt(secret, input, digest);
+ break;
+ case AF_INET6:
+ cp = (unsigned char *)&netaddr.type.in6;
+ memmove(input + 8, cp, 16);
+ isc_aes128_crypt(secret, input, digest);
+ for (i = 0; i < 8; i++)
+ input[i + 8] = digest[i] ^ digest[i + 8];
+ isc_aes128_crypt(ns_g_server->secret, input + 8,
+ digest);
+ break;
+ }
+ for (i = 0; i < 8; i++)
+ digest[i] ^= digest[i + 8];
+ isc_buffer_putmem(buf, digest, 8);
+ break;
+ }
+#endif
+
+ case ns_cookiealg_sha1: {
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+ isc_netaddr_t netaddr;
+ unsigned char *cp;
+ isc_hmacsha1_t hmacsha1;
+ unsigned int length;
+
+ cp = isc_buffer_used(buf);
+ isc_buffer_putmem(buf, client->cookie, 8);
+ isc_buffer_putuint32(buf, nonce);
+ isc_buffer_putuint32(buf, when);
+
+ isc_hmacsha1_init(&hmacsha1, secret, ISC_SHA1_DIGESTLENGTH);
+ isc_hmacsha1_update(&hmacsha1, cp, 16);
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (netaddr.family) {
+ case AF_INET:
+ cp = (unsigned char *)&netaddr.type.in;
+ length = 4;
+ break;
+ case AF_INET6:
+ cp = (unsigned char *)&netaddr.type.in6;
+ length = 16;
+ break;
+ default:
+ INSIST(0);
+ }
+ isc_hmacsha1_update(&hmacsha1, cp, length);
+ isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest));
+ isc_buffer_putmem(buf, digest, 8);
+ isc_hmacsha1_invalidate(&hmacsha1);
+ break;
+ }
+
+ case ns_cookiealg_sha256: {
+ unsigned char digest[ISC_SHA256_DIGESTLENGTH];
+ isc_netaddr_t netaddr;
+ unsigned char *cp;
+ isc_hmacsha256_t hmacsha256;
+ unsigned int length;
+
+ cp = isc_buffer_used(buf);
+ isc_buffer_putmem(buf, client->cookie, 8);
+ isc_buffer_putuint32(buf, nonce);
+ isc_buffer_putuint32(buf, when);
+
+ isc_hmacsha256_init(&hmacsha256, secret,
+ ISC_SHA256_DIGESTLENGTH);
+ isc_hmacsha256_update(&hmacsha256, cp, 16);
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (netaddr.family) {
+ case AF_INET:
+ cp = (unsigned char *)&netaddr.type.in;
+ length = 4;
+ break;
+ case AF_INET6:
+ cp = (unsigned char *)&netaddr.type.in6;
+ length = 16;
+ break;
+ default:
+ INSIST(0);
+ }
+ isc_hmacsha256_update(&hmacsha256, cp, length);
+ isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest));
+ isc_buffer_putmem(buf, digest, 8);
+ isc_hmacsha256_invalidate(&hmacsha256);
+ break;
+ }
+ default:
+ INSIST(0);
+ }
+}
+
+static void
+process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
+ ns_altsecret_t *altsecret;
+ unsigned char dbuf[COOKIE_SIZE];
+ unsigned char *old;
+ isc_stdtime_t now;
+ uint32_t when;
+ uint32_t nonce;
+ isc_buffer_t db;
+
+ /*
+ * If we have already seen a cookie option skip this cookie option.
+ */
+ if ((!ns_g_server->answercookie) ||
+ (client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
+ {
+ isc_buffer_forward(buf, (unsigned int)optlen);
+ return;
+ }
+
+ client->attributes |= NS_CLIENTATTR_WANTCOOKIE;
+
+ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookiein);
+
+ if (optlen != COOKIE_SIZE) {
+ /*
+ * Not our token.
+ */
+ INSIST(optlen >= 8U);
+ memmove(client->cookie, isc_buffer_current(buf), 8);
+ isc_buffer_forward(buf, (unsigned int)optlen);
+
+ if (optlen == 8U)
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_cookienew);
+ else
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_cookiebadsize);
+ return;
+ }
+
+ /*
+ * Process all of the incoming buffer.
+ */
+ old = isc_buffer_current(buf);
+ memmove(client->cookie, old, 8);
+ isc_buffer_forward(buf, 8);
+ nonce = isc_buffer_getuint32(buf);
+ when = isc_buffer_getuint32(buf);
+ isc_buffer_forward(buf, 8);
+
+ /*
+ * Allow for a 5 minute clock skew between servers sharing a secret.
+ * Only accept COOKIE if we have talked to the client in the last hour.
+ */
+ isc_stdtime_get(&now);
+ if (isc_serial_gt(when, (now + 300)) || /* In the future. */
+ isc_serial_lt(when, (now - 3600))) { /* In the past. */
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_cookiebadtime);
+ return;
+ }
+
+ isc_buffer_init(&db, dbuf, sizeof(dbuf));
+ compute_cookie(client, when, nonce, ns_g_server->secret, &db);
+
+ if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_cookiematch);
+ client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
+ return;
+ }
+
+ for (altsecret = ISC_LIST_HEAD(ns_g_server->altsecrets);
+ altsecret != NULL;
+ altsecret = ISC_LIST_NEXT(altsecret, link))
+ {
+ isc_buffer_init(&db, dbuf, sizeof(dbuf));
+ compute_cookie(client, when, nonce, altsecret->secret, &db);
+ if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_cookiematch);
+ client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
+ return;
+ }
+ }
+
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_cookienomatch);
+}
+
+static isc_result_t
+process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
+ uint16_t family;
+ uint8_t addrlen, addrbytes, scope, *paddr;
+ isc_netaddr_t caddr;
+
+ /*
+ * If we have already seen a ECS option skip this ECS option.
+ */
+ if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
+ isc_buffer_forward(buf, (unsigned int)optlen);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * XXXMUKS: Is there any need to repeat these checks here
+ * (except query's scope length) when they are done in the OPT
+ * RDATA fromwire code?
+ */
+
+ if (optlen < 4U) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option too short");
+ return (DNS_R_FORMERR);
+ }
+
+ family = isc_buffer_getuint16(buf);
+ addrlen = isc_buffer_getuint8(buf);
+ scope = isc_buffer_getuint8(buf);
+ optlen -= 4;
+
+ if (scope != 0U) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option: invalid scope");
+ return (DNS_R_OPTERR);
+ }
+
+ memset(&caddr, 0, sizeof(caddr));
+ switch (family) {
+ case 0:
+ /*
+ * XXXMUKS: In queries, if FAMILY is set to 0, SOURCE
+ * PREFIX-LENGTH must be 0 and ADDRESS should not be
+ * present as the address and prefix lengths don't make
+ * sense because the family is unknown.
+ */
+ if (addrlen != 0U) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option: invalid "
+ "address length (%u) for FAMILY=0",
+ addrlen);
+ return (DNS_R_OPTERR);
+ }
+ caddr.family = AF_UNSPEC;
+ break;
+ case 1:
+ if (addrlen > 32U) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option: invalid "
+ "address length (%u) for IPv4",
+ addrlen);
+ return (DNS_R_OPTERR);
+ }
+ caddr.family = AF_INET;
+ break;
+ case 2:
+ if (addrlen > 128U) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option: invalid "
+ "address length (%u) for IPv6",
+ addrlen);
+ return (DNS_R_OPTERR);
+ }
+ caddr.family = AF_INET6;
+ break;
+ default:
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option: invalid family");
+ return (DNS_R_OPTERR);
+ }
+
+ addrbytes = (addrlen + 7) / 8;
+ if (isc_buffer_remaininglength(buf) < addrbytes) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "EDNS client-subnet option: address too short");
+ return (DNS_R_OPTERR);
+ }
+
+ paddr = (uint8_t *) &caddr.type;
+ if (addrbytes != 0U) {
+ memmove(paddr, isc_buffer_current(buf), addrbytes);
+ isc_buffer_forward(buf, addrbytes);
+ optlen -= addrbytes;
+
+ if ((addrlen % 8) != 0) {
+ uint8_t bits = ~0U << (8 - (addrlen % 8));
+ bits &= paddr[addrbytes - 1];
+ if (bits != paddr[addrbytes - 1])
+ return (DNS_R_OPTERR);
+ }
+ }
+
+ memmove(&client->ecs_addr, &caddr, sizeof(caddr));
+ client->ecs_addrlen = addrlen;
+ client->ecs_scope = 0;
+ client->attributes |= NS_CLIENTATTR_HAVEECS;
+
+ isc_buffer_forward(buf, (unsigned int)optlen);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+process_keytag(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
+
+ if (optlen == 0 || (optlen % 2) != 0) {
+ isc_buffer_forward(buf, (unsigned int)optlen);
+ return (DNS_R_OPTERR);
+ }
+
+ /* Silently drop additional keytag options. */
+ if (client->keytag != NULL) {
+ isc_buffer_forward(buf, (unsigned int)optlen);
+ return (ISC_R_SUCCESS);
+ }
+
+ client->keytag = isc_mem_get(client->mctx, optlen);
+ if (client->keytag != NULL) {
+ client->keytag_len = (uint16_t)optlen;
+ memmove(client->keytag, isc_buffer_current(buf), optlen);
+ }
+ isc_buffer_forward(buf, (unsigned int)optlen);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+process_opt(ns_client_t *client, dns_rdataset_t *opt) {
+ dns_rdata_t rdata;
+ isc_buffer_t optbuf;
+ isc_result_t result;
+ uint16_t optcode;
+ uint16_t optlen;
+
+ /*
+ * Set the client's UDP buffer size.
+ */
+ client->udpsize = opt->rdclass;
+
+ /*
+ * If the requested UDP buffer size is less than 512,
+ * ignore it and use 512.
+ */
+ if (client->udpsize < 512)
+ client->udpsize = 512;
+
+ /*
+ * Get the flags out of the OPT record.
+ */
+ client->extflags = (uint16_t)(opt->ttl & 0xFFFF);
+
+ /*
+ * Do we understand this version of EDNS?
+ *
+ * XXXRTH need library support for this!
+ */
+ client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
+ if (client->ednsversion > DNS_EDNS_VERSION) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_badednsver);
+ result = ns_client_addopt(client, client->message,
+ &client->opt);
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_BADVERS;
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+
+ /* Check for NSID request */
+ 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_NSID:
+ if (!WANTNSID(client))
+ isc_stats_increment(
+ ns_g_server->nsstats,
+ dns_nsstatscounter_nsidopt);
+ client->attributes |= NS_CLIENTATTR_WANTNSID;
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ case DNS_OPT_COOKIE:
+ process_cookie(client, &optbuf, optlen);
+ break;
+ case DNS_OPT_EXPIRE:
+ if (!WANTEXPIRE(client))
+ isc_stats_increment(
+ ns_g_server->nsstats,
+ dns_nsstatscounter_expireopt);
+ client->attributes |= NS_CLIENTATTR_WANTEXPIRE;
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ case DNS_OPT_CLIENT_SUBNET:
+ result = process_ecs(client, &optbuf, optlen);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_ecsopt);
+ break;
+ case DNS_OPT_KEY_TAG:
+ result = process_keytag(client, &optbuf,
+ optlen);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_error(client, result);
+ return (result);
+ }
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_keytagopt);
+ break;
+ default:
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_otheropt);
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ }
+ }
+
+ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0in);
+ client->attributes |= NS_CLIENTATTR_WANTOPT;
+
+ cleanup:
+ return (result);
+}
+
+/*
+ * Handle an incoming request event from the socket (UDP case)
+ * or tcpmsg (TCP case).
+ */
+static void
+client_request(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+ isc_socketevent_t *sevent;
+ isc_result_t result;
+ isc_result_t sigresult = ISC_R_SUCCESS;
+ isc_buffer_t *buffer;
+ isc_buffer_t tbuffer;
+ dns_view_t *view;
+ dns_rdataset_t *opt;
+ dns_name_t *signame;
+ bool ra; /* Recursion available. */
+ isc_netaddr_t netaddr;
+ int match;
+ dns_messageid_t id;
+ unsigned int flags;
+ bool notimp;
+ size_t reqsize;
+#ifdef HAVE_DNSTAP
+ dns_dtmsgtype_t dtmsgtype;
+#endif
+
+ REQUIRE(event != NULL);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+
+ INSIST(client->recursionquota == NULL);
+
+ INSIST(client->state == (TCP_CLIENT(client) ?
+ NS_CLIENTSTATE_READING :
+ NS_CLIENTSTATE_READY));
+
+ ns_client_requests++;
+
+ if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
+ INSIST(!TCP_CLIENT(client));
+ sevent = (isc_socketevent_t *)event;
+ REQUIRE(sevent == client->recvevent);
+ isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
+ isc_buffer_add(&tbuffer, sevent->n);
+ buffer = &tbuffer;
+ result = sevent->result;
+ if (result == ISC_R_SUCCESS) {
+ client->peeraddr = sevent->address;
+ client->peeraddr_valid = true;
+ }
+ if ((sevent->attributes & ISC_SOCKEVENTATTR_DSCP) != 0) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(90),
+ "received DSCP %d", sevent->dscp);
+ if (client->dscp == -1)
+ client->dscp = sevent->dscp;
+ }
+ if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
+ client->attributes |= NS_CLIENTATTR_PKTINFO;
+ client->pktinfo = sevent->pktinfo;
+ }
+ if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
+ client->attributes |= NS_CLIENTATTR_MULTICAST;
+ client->nrecvs--;
+ } else {
+ INSIST(TCP_CLIENT(client));
+ REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
+ REQUIRE(event->ev_sender == &client->tcpmsg);
+ buffer = &client->tcpmsg.buffer;
+ result = client->tcpmsg.result;
+ INSIST(client->nreads == 1);
+ /*
+ * client->peeraddr was set when the connection was accepted.
+ */
+ client->nreads--;
+ }
+
+ reqsize = isc_buffer_usedlength(buffer);
+ /* don't count the length header */
+ if (TCP_CLIENT(client))
+ reqsize -= 2;
+
+ if (exit_check(client))
+ goto cleanup;
+ client->state = client->newstate = NS_CLIENTSTATE_WORKING;
+
+ isc_task_getcurrenttimex(task, &client->requesttime);
+ client->tnow = client->requesttime;
+ client->now = isc_time_seconds(&client->tnow);
+
+ if (result != ISC_R_SUCCESS) {
+ if (TCP_CLIENT(client)) {
+ ns_client_next(client, result);
+ } else {
+ if (result != ISC_R_CANCELED)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT,
+ ISC_LOG_ERROR,
+ "UDP client handler shutting "
+ "down due to fatal receive "
+ "error: %s",
+ isc_result_totext(result));
+ isc_task_shutdown(client->task);
+ }
+ goto cleanup;
+ }
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+#if NS_CLIENT_DROPPORT
+ if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
+ DROPPORT_REQUEST) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "dropped request: suspicious port");
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+#endif
+
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "%s request",
+ TCP_CLIENT(client) ? "TCP" : "UDP");
+
+ /*
+ * Check the blackhole ACL for UDP only, since TCP is done in
+ * client_newconn.
+ */
+ if (!TCP_CLIENT(client)) {
+ if (ns_g_server->blackholeacl != NULL &&
+ dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
+ &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "blackholed UDP datagram");
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Silently drop multicast requests for the present.
+ * XXXMPA revisit this as mDNS spec was published.
+ */
+ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "dropping multicast request");
+ ns_client_next(client, DNS_R_REFUSED);
+ goto cleanup;
+ }
+
+ result = dns_message_peekheader(buffer, &id, &flags);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * There isn't enough header to determine whether
+ * this was a request or a response. Drop it.
+ */
+ ns_client_next(client, result);
+ goto cleanup;
+ }
+
+ /*
+ * The client object handles requests, not responses.
+ * If this is a UDP response, forward it to the dispatcher.
+ * If it's a TCP response, discard it here.
+ */
+ if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
+ if (TCP_CLIENT(client)) {
+ CTRACE("unexpected response");
+ ns_client_next(client, DNS_R_FORMERR);
+ goto cleanup;
+ } else {
+ dns_dispatch_importrecv(client->dispatch, event);
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Update some statistics counters. Don't count responses.
+ */
+ if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_requestv4);
+ } else {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_requestv6);
+ }
+ if (TCP_CLIENT(client)) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_requesttcp);
+ switch (isc_sockaddr_pf(&client->peeraddr)) {
+ case AF_INET:
+ isc_stats_increment(ns_g_server->tcpinstats4,
+ ISC_MIN((int)reqsize / 16, 18));
+ break;
+ case AF_INET6:
+ isc_stats_increment(ns_g_server->tcpinstats6,
+ ISC_MIN((int)reqsize / 16, 18));
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+ } else {
+ switch (isc_sockaddr_pf(&client->peeraddr)) {
+ case AF_INET:
+ isc_stats_increment(ns_g_server->udpinstats4,
+ ISC_MIN((int)reqsize / 16, 18));
+ break;
+ case AF_INET6:
+ isc_stats_increment(ns_g_server->udpinstats6,
+ ISC_MIN((int)reqsize / 16, 18));
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+ }
+
+ /*
+ * It's a request. Parse it.
+ */
+ result = dns_message_parse(client->message, buffer, 0);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Parsing the request failed. Send a response
+ * (typically FORMERR or SERVFAIL).
+ */
+ if (result == DNS_R_OPTERR)
+ (void)ns_client_addopt(client, client->message,
+ &client->opt);
+
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "message parsing failed: %s",
+ isc_result_totext(result));
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+
+ /*
+ * Pipeline TCP query processing.
+ */
+ if (client->message->opcode != dns_opcode_query)
+ client->pipelined = false;
+ if (TCP_CLIENT(client) && client->pipelined) {
+ result = isc_quota_reserve(&ns_g_server->tcpquota);
+ if (result == ISC_R_SUCCESS)
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
+ "no more TCP clients(read): %s",
+ isc_result_totext(result));
+ client->pipelined = false;
+ }
+ }
+
+ dns_opcodestats_increment(ns_g_server->opcodestats,
+ client->message->opcode);
+ switch (client->message->opcode) {
+ case dns_opcode_query:
+ case dns_opcode_update:
+ case dns_opcode_notify:
+ notimp = false;
+ break;
+ case dns_opcode_iquery:
+ default:
+ notimp = true;
+ break;
+ }
+
+ client->message->rcode = dns_rcode_noerror;
+
+ /* RFC1123 section 6.1.3.2 */
+ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
+ client->message->flags &= ~DNS_MESSAGEFLAG_RD;
+
+ /*
+ * Deal with EDNS.
+ */
+ if (ns_g_noedns)
+ opt = NULL;
+ else
+ opt = dns_message_getopt(client->message);
+
+ client->ecs_addrlen = 0;
+ client->ecs_scope = 0;
+
+ if (opt != NULL) {
+ /*
+ * Are we dropping all EDNS queries?
+ */
+ if (ns_g_dropedns) {
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ result = process_opt(client, opt);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ if (client->message->rdclass == 0) {
+ if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
+ client->message->opcode == dns_opcode_query &&
+ client->message->counts[DNS_SECTION_QUESTION] == 0U)
+ {
+ result = dns_message_reply(client->message, true);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_error(client, result);
+ return;
+ }
+ if (notimp)
+ client->message->rcode = dns_rcode_notimp;
+ ns_client_send(client);
+ return;
+ }
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "message class could not be determined");
+ ns_client_dumpmessage(client,
+ "message class could not be determined");
+ ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
+ goto cleanup;
+ }
+
+ /*
+ * Determine the destination address. If the receiving interface is
+ * bound to a specific address, we simply use it regardless of the
+ * address family. All IPv4 queries should fall into this case.
+ * Otherwise, if this is a TCP query, get the address from the
+ * receiving socket (this needs a system call and can be heavy).
+ * For IPv6 UDP queries, we get this from the pktinfo structure (if
+ * supported).
+ * If all the attempts fail (this can happen due to memory shortage,
+ * etc), we regard this as an error for safety.
+ */
+ if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
+ isc_netaddr_fromsockaddr(&client->destaddr,
+ &client->interface->addr);
+ else {
+ isc_sockaddr_t sockaddr;
+ result = ISC_R_FAILURE;
+
+ if (TCP_CLIENT(client))
+ result = isc_socket_getsockname(client->tcpsocket,
+ &sockaddr);
+ if (result == ISC_R_SUCCESS)
+ isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
+ if (result != ISC_R_SUCCESS &&
+ client->interface->addr.type.sa.sa_family == AF_INET6 &&
+ (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
+ /*
+ * XXXJT technically, we should convert the receiving
+ * interface ID to a proper scope zone ID. However,
+ * due to the fact there is no standard API for this,
+ * we only handle link-local addresses and use the
+ * interface index as link ID. Despite the assumption,
+ * it should cover most typical cases.
+ */
+ isc_netaddr_fromin6(&client->destaddr,
+ &client->pktinfo.ipi6_addr);
+ if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
+ isc_netaddr_setzone(&client->destaddr,
+ client->pktinfo.ipi6_ifindex);
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "failed to get request's "
+ "destination: %s",
+ isc_result_totext(result));
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ }
+
+ isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0);
+
+ /*
+ * Find a view that matches the client's source address.
+ */
+ for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (client->message->rdclass == view->rdclass ||
+ client->message->rdclass == dns_rdataclass_any)
+ {
+ dns_name_t *tsig = NULL;
+ isc_netaddr_t *addr = NULL;
+ uint8_t *scope = NULL;
+
+ sigresult = dns_message_rechecksig(client->message,
+ view);
+ if (sigresult == ISC_R_SUCCESS) {
+ dns_tsigkey_t *tsigkey;
+
+ tsigkey = client->message->tsigkey;
+ tsig = dns_tsigkey_identity(tsigkey);
+ }
+
+ if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
+ addr = &client->ecs_addr;
+ scope = &client->ecs_scope;
+ }
+
+ if (allowed(&netaddr, tsig, addr, client->ecs_addrlen,
+ scope, view->matchclients) &&
+ allowed(&client->destaddr, tsig, NULL,
+ 0, NULL, view->matchdestinations) &&
+ !(view->matchrecursiveonly &&
+ (client->message->flags & DNS_MESSAGEFLAG_RD) == 0))
+ {
+ dns_view_attach(view, &client->view);
+ break;
+ }
+ }
+ }
+
+ if (view == NULL) {
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+
+ /*
+ * Do a dummy TSIG verification attempt so that the
+ * response will have a TSIG if the query did, as
+ * required by RFC2845.
+ */
+ isc_buffer_t b;
+ isc_region_t *r;
+
+ dns_message_resetsig(client->message);
+
+ r = dns_message_getrawmessage(client->message);
+ isc_buffer_init(&b, r->base, r->length);
+ isc_buffer_add(&b, r->length);
+ (void)dns_tsig_verify(&b, client->message, NULL, NULL);
+
+ dns_rdataclass_format(client->message->rdclass, classname,
+ sizeof(classname));
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "no matching view in class '%s'", classname);
+ ns_client_dumpmessage(client, "no matching view in class");
+ ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
+ goto cleanup;
+ }
+
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
+ "using view '%s'", view->name);
+
+ /*
+ * Check for a signature. We log bad signatures regardless of
+ * whether they ultimately cause the request to be rejected or
+ * not. We do not log the lack of a signature unless we are
+ * debugging.
+ */
+ client->signer = NULL;
+ dns_name_init(&client->signername, NULL);
+ result = dns_message_signer(client->message, &client->signername);
+ if (result != ISC_R_NOTFOUND) {
+ signame = NULL;
+ if (dns_message_gettsig(client->message, &signame) != NULL) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_tsigin);
+ } else {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_sig0in);
+ }
+
+ }
+ if (result == ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(&client->signername, namebuf, sizeof(namebuf));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request has valid signature: %s", namebuf);
+ client->signer = &client->signername;
+ } else if (result == ISC_R_NOTFOUND) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request is not signed");
+ } else if (result == DNS_R_NOIDENTITY) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request is signed by a nonauthoritative key");
+ } else {
+ char tsigrcode[64];
+ isc_buffer_t b;
+ dns_rcode_t status;
+ isc_result_t tresult;
+
+ /* There is a signature, but it is bad. */
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_invalidsig);
+ signame = NULL;
+ if (dns_message_gettsig(client->message, &signame) != NULL) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char cnamebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(signame, namebuf, sizeof(namebuf));
+ status = client->message->tsigstatus;
+ isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
+ tresult = dns_tsigrcode_totext(status, &b);
+ INSIST(tresult == ISC_R_SUCCESS);
+ tsigrcode[isc_buffer_usedlength(&b)] = '\0';
+ if (client->message->tsigkey->generated) {
+ dns_name_format(client->message->tsigkey->creator,
+ cnamebuf, sizeof(cnamebuf));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT,
+ ISC_LOG_ERROR,
+ "request has invalid signature: "
+ "TSIG %s (%s): %s (%s)", namebuf,
+ cnamebuf,
+ isc_result_totext(result),
+ tsigrcode);
+ } else {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT,
+ ISC_LOG_ERROR,
+ "request has invalid signature: "
+ "TSIG %s: %s (%s)", namebuf,
+ isc_result_totext(result),
+ tsigrcode);
+ }
+ } else {
+ status = client->message->sig0status;
+ isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
+ tresult = dns_tsigrcode_totext(status, &b);
+ INSIST(tresult == ISC_R_SUCCESS);
+ tsigrcode[isc_buffer_usedlength(&b)] = '\0';
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
+ "request has invalid signature: %s (%s)",
+ isc_result_totext(result), tsigrcode);
+ }
+ /*
+ * Accept update messages signed by unknown keys so that
+ * update forwarding works transparently through slaves
+ * that don't have all the same keys as the master.
+ */
+ if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
+ client->message->opcode == dns_opcode_update)) {
+ ns_client_error(client, sigresult);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Decide whether recursive service is available to this client.
+ * We do this here rather than in the query code so that we can
+ * set the RA bit correctly on all kinds of responses, not just
+ * responses to ordinary queries. Note if you can't query the
+ * cache there is no point in setting RA.
+ */
+ ra = false;
+ if (client->view->resolver != NULL &&
+ client->view->recursion == true &&
+ ns_client_checkaclsilent(client, NULL,
+ client->view->recursionacl,
+ true) == ISC_R_SUCCESS &&
+ ns_client_checkaclsilent(client, NULL,
+ client->view->cacheacl,
+ true) == ISC_R_SUCCESS &&
+ ns_client_checkaclsilent(client, &client->destaddr,
+ client->view->recursiononacl,
+ true) == ISC_R_SUCCESS &&
+ ns_client_checkaclsilent(client, &client->destaddr,
+ client->view->cacheonacl,
+ true) == ISC_R_SUCCESS)
+ ra = true;
+
+ if (ra == true)
+ client->attributes |= NS_CLIENTATTR_RA;
+
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
+ ISC_LOG_DEBUG(3), ra ? "recursion available" :
+ "recursion not available");
+
+ /*
+ * Adjust maximum UDP response size for this client.
+ */
+ if (client->udpsize > 512) {
+ dns_peer_t *peer = NULL;
+ uint16_t udpsize = view->maxudp;
+ (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
+ if (peer != NULL)
+ dns_peer_getmaxudp(peer, &udpsize);
+ if (client->udpsize > udpsize)
+ client->udpsize = udpsize;
+ }
+
+ /*
+ * Dispatch the request.
+ */
+ switch (client->message->opcode) {
+ case dns_opcode_query:
+ CTRACE("query");
+#ifdef HAVE_DNSTAP
+ if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0)
+ dtmsgtype = DNS_DTTYPE_CQ;
+ else
+ dtmsgtype = DNS_DTTYPE_AQ;
+
+ dns_dt_send(view, dtmsgtype, &client->peeraddr,
+ &client->destsockaddr, TCP_CLIENT(client), NULL,
+ &client->requesttime, NULL, buffer);
+#endif /* HAVE_DNSTAP */
+
+ ns_query_start(client);
+ break;
+ case dns_opcode_update:
+ CTRACE("update");
+ ns_client_settimeout(client, 60);
+ ns_update_start(client, sigresult);
+ break;
+ case dns_opcode_notify:
+ CTRACE("notify");
+ ns_client_settimeout(client, 60);
+ ns_notify_start(client);
+ break;
+ case dns_opcode_iquery:
+ CTRACE("iquery");
+ ns_client_error(client, DNS_R_NOTIMP);
+ break;
+ default:
+ CTRACE("unknown opcode");
+ ns_client_error(client, DNS_R_NOTIMP);
+ }
+
+ cleanup:
+ return;
+}
+
+static void
+client_timeout(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
+ event->ev_type == ISC_TIMEREVENT_IDLE);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(client->timer != NULL);
+
+ UNUSED(task);
+
+ CTRACE("timeout");
+
+ isc_event_free(&event);
+
+ if (client->shutdown != NULL) {
+ (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
+ client->shutdown = NULL;
+ client->shutdown_arg = NULL;
+ }
+
+ if (client->newstate > NS_CLIENTSTATE_READY)
+ client->newstate = NS_CLIENTSTATE_READY;
+ (void)exit_check(client);
+}
+
+static isc_result_t
+get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
+ isc_mem_t *clientmctx;
+ isc_result_t result;
+#if NMCTXS > 0
+ unsigned int nextmctx;
+#endif
+
+ MTRACE("clientmctx");
+
+ /*
+ * Caller must be holding the manager lock.
+ */
+ if (ns_g_clienttest) {
+ result = isc_mem_create(0, 0, mctxp);
+ if (result == ISC_R_SUCCESS)
+ isc_mem_setname(*mctxp, "client", NULL);
+ return (result);
+ }
+#if NMCTXS > 0
+ nextmctx = manager->nextmctx++;
+ if (manager->nextmctx == NMCTXS)
+ manager->nextmctx = 0;
+
+ INSIST(nextmctx < NMCTXS);
+
+ clientmctx = manager->mctxpool[nextmctx];
+ if (clientmctx == NULL) {
+ result = isc_mem_create(0, 0, &clientmctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_mem_setname(clientmctx, "client", NULL);
+
+ manager->mctxpool[nextmctx] = clientmctx;
+ }
+#else
+ clientmctx = manager->mctx;
+#endif
+
+ isc_mem_attach(clientmctx, mctxp);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
+ ns_client_t *client;
+ isc_result_t result;
+ isc_mem_t *mctx = NULL;
+
+ /*
+ * Caller must be holding the manager lock.
+ *
+ * Note: creating a client does not add the client to the
+ * manager's client list or set the client's manager pointer.
+ * The caller is responsible for that.
+ */
+
+ REQUIRE(clientp != NULL && *clientp == NULL);
+
+ result = get_clientmctx(manager, &mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ client = isc_mem_get(mctx, sizeof(*client));
+ if (client == NULL) {
+ isc_mem_detach(&mctx);
+ return (ISC_R_NOMEMORY);
+ }
+ client->mctx = mctx;
+
+ client->task = NULL;
+ result = isc_task_create(manager->taskmgr, 0, &client->task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_client;
+ isc_task_setname(client->task, "client", client);
+
+ client->timer = NULL;
+ result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
+ NULL, NULL, client->task, client_timeout,
+ client, &client->timer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_task;
+ client->timerset = false;
+
+ client->delaytimer = NULL;
+
+ client->message = NULL;
+ result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
+ &client->message);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_timer;
+
+ /* XXXRTH Hardwired constants */
+
+ client->sendevent = isc_socket_socketevent(client->mctx, client,
+ ISC_SOCKEVENT_SENDDONE,
+ client_senddone, client);
+ if (client->sendevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_message;
+ }
+
+ client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
+ if (client->recvbuf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_sendevent;
+ }
+
+ client->recvevent = isc_socket_socketevent(client->mctx, client,
+ ISC_SOCKEVENT_RECVDONE,
+ client_request, client);
+ if (client->recvevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_recvbuf;
+ }
+
+ client->magic = NS_CLIENT_MAGIC;
+ client->manager = NULL;
+ client->state = NS_CLIENTSTATE_INACTIVE;
+ client->newstate = NS_CLIENTSTATE_MAX;
+ client->naccepts = 0;
+ client->nreads = 0;
+ client->nsends = 0;
+ client->nrecvs = 0;
+ client->nupdates = 0;
+ client->nctls = 0;
+ client->references = 0;
+ client->attributes = 0;
+ client->view = NULL;
+ client->dispatch = NULL;
+ client->udpsocket = NULL;
+ client->tcplistener = NULL;
+ client->tcpsocket = NULL;
+ client->tcpmsg_valid = false;
+ client->tcpbuf = NULL;
+ client->opt = NULL;
+ client->udpsize = 512;
+ client->dscp = -1;
+ client->extflags = 0;
+ client->ednsversion = -1;
+ client->next = NULL;
+ client->shutdown = NULL;
+ client->shutdown_arg = NULL;
+ client->signer = NULL;
+ dns_name_init(&client->signername, NULL);
+ client->mortal = false;
+ client->pipelined = false;
+ client->tcpquota = NULL;
+ client->recursionquota = NULL;
+ client->interface = NULL;
+ client->peeraddr_valid = false;
+ client->ecs_addrlen = 0;
+ client->ecs_scope = 0;
+#ifdef ALLOW_FILTER_AAAA
+ client->filter_aaaa = dns_aaaa_ok;
+#endif
+ client->needshutdown = ns_g_clienttest;
+
+ ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
+ NS_EVENT_CLIENTCONTROL, client_start, client, client,
+ NULL, NULL);
+ /*
+ * Initialize FORMERR cache to sentinel value that will not match
+ * any actual FORMERR response.
+ */
+ isc_sockaddr_any(&client->formerrcache.addr);
+ client->formerrcache.time = 0;
+ client->formerrcache.id = 0;
+ ISC_LINK_INIT(client, link);
+ ISC_LINK_INIT(client, rlink);
+ ISC_QLINK_INIT(client, ilink);
+ client->keytag = NULL;
+ client->keytag_len = 0;
+
+ /*
+ * We call the init routines for the various kinds of client here,
+ * after we have created an otherwise valid client, because some
+ * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
+ */
+ result = ns_query_init(client);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_recvevent;
+
+ result = isc_task_onshutdown(client->task, client_shutdown, client);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_query;
+
+ CTRACE("create");
+
+ *clientp = client;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_query:
+ ns_query_free(client);
+
+ cleanup_recvevent:
+ isc_event_free((isc_event_t **)&client->recvevent);
+
+ cleanup_recvbuf:
+ isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
+
+ cleanup_sendevent:
+ isc_event_free((isc_event_t **)&client->sendevent);
+
+ client->magic = 0;
+
+ cleanup_message:
+ dns_message_destroy(&client->message);
+
+ cleanup_timer:
+ isc_timer_detach(&client->timer);
+
+ cleanup_task:
+ isc_task_detach(&client->task);
+
+ cleanup_client:
+ isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
+
+ return (result);
+}
+
+static void
+client_read(ns_client_t *client) {
+ isc_result_t result;
+
+ CTRACE("read");
+
+ result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
+ client_request, client);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /*
+ * Set a timeout to limit the amount of time we will wait
+ * for a request on this TCP connection.
+ */
+ ns_client_settimeout(client, 30);
+
+ client->state = client->newstate = NS_CLIENTSTATE_READING;
+ INSIST(client->nreads == 0);
+ INSIST(client->recursionquota == NULL);
+ client->nreads++;
+
+ return;
+ fail:
+ ns_client_next(client, result);
+}
+
+static void
+client_newconn(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client = event->ev_arg;
+ isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
+ isc_result_t result;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(client->task == task);
+
+ UNUSED(task);
+
+ INSIST(client->state == NS_CLIENTSTATE_READY);
+
+ INSIST(client->naccepts == 1);
+ client->naccepts--;
+
+ LOCK(&client->interface->lock);
+ INSIST(client->interface->ntcpcurrent > 0);
+ client->interface->ntcpcurrent--;
+ UNLOCK(&client->interface->lock);
+
+ /*
+ * We must take ownership of the new socket before the exit
+ * check to make sure it gets destroyed if we decide to exit.
+ */
+ if (nevent->result == ISC_R_SUCCESS) {
+ client->tcpsocket = nevent->newsocket;
+ isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
+ client->state = NS_CLIENTSTATE_READING;
+ INSIST(client->recursionquota == NULL);
+
+ (void)isc_socket_getpeername(client->tcpsocket,
+ &client->peeraddr);
+ client->peeraddr_valid = true;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "new TCP connection");
+ } else {
+ /*
+ * XXXRTH What should we do? We're trying to accept but
+ * it didn't work. If we just give up, then TCP
+ * service may eventually stop.
+ *
+ * For now, we just go idle.
+ *
+ * Going idle is probably the right thing if the
+ * I/O was canceled.
+ */
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "accept failed: %s",
+ isc_result_totext(nevent->result));
+ }
+
+ if (exit_check(client))
+ goto freeevent;
+
+ if (nevent->result == ISC_R_SUCCESS) {
+ int match;
+ isc_netaddr_t netaddr;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+ if (ns_g_server->blackholeacl != NULL &&
+ dns_acl_match(&netaddr, NULL,
+ ns_g_server->blackholeacl,
+ &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "blackholed connection attempt");
+ client->newstate = NS_CLIENTSTATE_READY;
+ (void)exit_check(client);
+ goto freeevent;
+ }
+
+ INSIST(client->tcpmsg_valid == false);
+ dns_tcpmsg_init(client->mctx, client->tcpsocket,
+ &client->tcpmsg);
+ client->tcpmsg_valid = true;
+
+ /*
+ * Let a new client take our place immediately, before
+ * we wait for a request packet. If we don't,
+ * telnetting to port 53 (once per CPU) will
+ * deny service to legitimate TCP clients.
+ */
+ client->pipelined = false;
+ result = isc_quota_attach(&ns_g_server->tcpquota,
+ &client->tcpquota);
+ if (result == ISC_R_SUCCESS)
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
+ "no more TCP clients(accept): %s",
+ isc_result_totext(result));
+ } else if (ns_g_server->keepresporder == NULL ||
+ !allowed(&netaddr, NULL, NULL, 0, NULL,
+ ns_g_server->keepresporder)) {
+ client->pipelined = true;
+ }
+
+ client_read(client);
+ }
+
+ freeevent:
+ isc_event_free(&event);
+}
+
+static void
+client_accept(ns_client_t *client) {
+ isc_result_t result;
+
+ CTRACE("accept");
+
+ result = isc_socket_accept(client->tcplistener, client->task,
+ client_newconn, client);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_accept() failed: %s",
+ isc_result_totext(result));
+ /*
+ * XXXRTH What should we do? We're trying to accept but
+ * it didn't work. If we just give up, then TCP
+ * service may eventually stop.
+ *
+ * For now, we just go idle.
+ */
+ return;
+ }
+ INSIST(client->naccepts == 0);
+ client->naccepts++;
+ LOCK(&client->interface->lock);
+ client->interface->ntcpcurrent++;
+ UNLOCK(&client->interface->lock);
+}
+
+static void
+client_udprecv(ns_client_t *client) {
+ isc_result_t result;
+ isc_region_t r;
+
+ CTRACE("udprecv");
+
+ r.base = client->recvbuf;
+ r.length = RECV_BUFFER_SIZE;
+ result = isc_socket_recv2(client->udpsocket, &r, 1,
+ client->task, client->recvevent, 0);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_recv2() failed: %s",
+ isc_result_totext(result));
+ /*
+ * This cannot happen in the current implementation, since
+ * isc_socket_recv2() cannot fail if flags == 0.
+ *
+ * If this does fail, we just go idle.
+ */
+ return;
+ }
+ INSIST(client->nrecvs == 0);
+ client->nrecvs++;
+}
+
+void
+ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
+ REQUIRE(NS_CLIENT_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ source->references++;
+ ns_client_log(source, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "ns_client_attach: ref = %d", source->references);
+ *targetp = source;
+}
+
+void
+ns_client_detach(ns_client_t **clientp) {
+ ns_client_t *client = *clientp;
+
+ client->references--;
+ INSIST(client->references >= 0);
+ *clientp = NULL;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "ns_client_detach: ref = %d", client->references);
+ (void)exit_check(client);
+}
+
+bool
+ns_client_shuttingdown(ns_client_t *client) {
+ return (client->newstate == NS_CLIENTSTATE_FREED);
+}
+
+isc_result_t
+ns_client_replace(ns_client_t *client) {
+ isc_result_t result;
+ bool tcp;
+
+ CTRACE("replace");
+
+ REQUIRE(client != NULL);
+ REQUIRE(client->manager != NULL);
+
+ tcp = TCP_CLIENT(client);
+ if (tcp && client->pipelined) {
+ result = get_worker(client->manager, client->interface,
+ client->tcpsocket);
+ } else {
+ result = get_client(client->manager, client->interface,
+ client->dispatch, tcp);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * The responsibility for listening for new requests is hereby
+ * transferred to the new client. Therefore, the old client
+ * should refrain from listening for any more requests.
+ */
+ client->mortal = true;
+
+ return (ISC_R_SUCCESS);
+}
+
+/***
+ *** Client Manager
+ ***/
+
+static void
+clientmgr_destroy(ns_clientmgr_t *manager) {
+#if NMCTXS > 0
+ int i;
+#endif
+
+ REQUIRE(ISC_LIST_EMPTY(manager->clients));
+
+ MTRACE("clientmgr_destroy");
+
+#if NMCTXS > 0
+ for (i = 0; i < NMCTXS; i++) {
+ if (manager->mctxpool[i] != NULL)
+ isc_mem_detach(&manager->mctxpool[i]);
+ }
+#endif
+
+ ISC_QUEUE_DESTROY(manager->inactive);
+ DESTROYLOCK(&manager->lock);
+ DESTROYLOCK(&manager->listlock);
+ DESTROYLOCK(&manager->reclock);
+ manager->magic = 0;
+ isc_mem_put(manager->mctx, manager, sizeof(*manager));
+}
+
+isc_result_t
+ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
+{
+ ns_clientmgr_t *manager;
+ isc_result_t result;
+#if NMCTXS > 0
+ int i;
+#endif
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_manager;
+
+ result = isc_mutex_init(&manager->listlock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ result = isc_mutex_init(&manager->reclock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_listlock;
+
+ manager->mctx = mctx;
+ manager->taskmgr = taskmgr;
+ manager->timermgr = timermgr;
+ manager->exiting = false;
+ ISC_LIST_INIT(manager->clients);
+ ISC_LIST_INIT(manager->recursing);
+ ISC_QUEUE_INIT(manager->inactive, ilink);
+#if NMCTXS > 0
+ manager->nextmctx = 0;
+ for (i = 0; i < NMCTXS; i++)
+ manager->mctxpool[i] = NULL; /* will be created on-demand */
+#endif
+ manager->magic = MANAGER_MAGIC;
+
+ MTRACE("create");
+
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_listlock:
+ (void) isc_mutex_destroy(&manager->listlock);
+
+ cleanup_lock:
+ (void) isc_mutex_destroy(&manager->lock);
+
+ cleanup_manager:
+ isc_mem_put(manager->mctx, manager, sizeof(*manager));
+
+ return (result);
+}
+
+void
+ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
+ isc_result_t result;
+ ns_clientmgr_t *manager;
+ ns_client_t *client;
+ bool need_destroy = false, unlock = false;
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+ MTRACE("destroy");
+
+ /*
+ * Check for success because we may already be task-exclusive
+ * at this point. Only if we succeed at obtaining an exclusive
+ * lock now will we need to relinquish it later.
+ */
+ result = isc_task_beginexclusive(ns_g_server->task);
+ if (result == ISC_R_SUCCESS)
+ unlock = true;
+
+ manager->exiting = true;
+
+ for (client = ISC_LIST_HEAD(manager->clients);
+ client != NULL;
+ client = ISC_LIST_NEXT(client, link))
+ isc_task_shutdown(client->task);
+
+ if (ISC_LIST_EMPTY(manager->clients))
+ need_destroy = true;
+
+ if (unlock)
+ isc_task_endexclusive(ns_g_server->task);
+
+ if (need_destroy)
+ clientmgr_destroy(manager);
+
+ *managerp = NULL;
+}
+
+static isc_result_t
+get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
+ dns_dispatch_t *disp, bool tcp)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_event_t *ev;
+ ns_client_t *client;
+ MTRACE("get client");
+
+ REQUIRE(manager != NULL);
+
+ if (manager->exiting)
+ return (ISC_R_SHUTTINGDOWN);
+
+ /*
+ * Allocate a client. First try to get a recycled one;
+ * if that fails, make a new one.
+ */
+ client = NULL;
+ if (!ns_g_clienttest)
+ ISC_QUEUE_POP(manager->inactive, ilink, client);
+
+ if (client != NULL)
+ MTRACE("recycle");
+ else {
+ MTRACE("create new");
+
+ LOCK(&manager->lock);
+ result = client_create(manager, &client);
+ UNLOCK(&manager->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ LOCK(&manager->listlock);
+ ISC_LIST_APPEND(manager->clients, client, link);
+ UNLOCK(&manager->listlock);
+ }
+
+ client->manager = manager;
+ ns_interface_attach(ifp, &client->interface);
+ client->state = NS_CLIENTSTATE_READY;
+ INSIST(client->recursionquota == NULL);
+
+ client->dscp = ifp->dscp;
+
+ if (tcp) {
+ client->attributes |= NS_CLIENTATTR_TCP;
+ isc_socket_attach(ifp->tcpsocket,
+ &client->tcplistener);
+ } else {
+ isc_socket_t *sock;
+
+ dns_dispatch_attach(disp, &client->dispatch);
+ sock = dns_dispatch_getsocket(client->dispatch);
+ isc_socket_attach(sock, &client->udpsocket);
+ }
+
+ INSIST(client->nctls == 0);
+ client->nctls++;
+ ev = &client->ctlevent;
+ isc_task_send(client->task, &ev);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_event_t *ev;
+ ns_client_t *client;
+ MTRACE("get worker");
+
+ REQUIRE(manager != NULL);
+
+ if (manager->exiting)
+ return (ISC_R_SHUTTINGDOWN);
+
+ /*
+ * Allocate a client. First try to get a recycled one;
+ * if that fails, make a new one.
+ */
+ client = NULL;
+ if (!ns_g_clienttest)
+ ISC_QUEUE_POP(manager->inactive, ilink, client);
+
+ if (client != NULL)
+ MTRACE("recycle");
+ else {
+ MTRACE("create new");
+
+ LOCK(&manager->lock);
+ result = client_create(manager, &client);
+ UNLOCK(&manager->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ LOCK(&manager->listlock);
+ ISC_LIST_APPEND(manager->clients, client, link);
+ UNLOCK(&manager->listlock);
+ }
+
+ client->manager = manager;
+ ns_interface_attach(ifp, &client->interface);
+ client->newstate = client->state = NS_CLIENTSTATE_WORKING;
+ INSIST(client->recursionquota == NULL);
+ client->tcpquota = &ns_g_server->tcpquota;
+
+ client->dscp = ifp->dscp;
+
+ client->attributes |= NS_CLIENTATTR_TCP;
+ client->pipelined = true;
+ client->mortal = true;
+
+ isc_socket_attach(ifp->tcpsocket, &client->tcplistener);
+ isc_socket_attach(sock, &client->tcpsocket);
+ isc_socket_setname(client->tcpsocket, "worker-tcp", NULL);
+ (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr);
+ client->peeraddr_valid = true;
+
+ INSIST(client->tcpmsg_valid == false);
+ dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg);
+ client->tcpmsg_valid = true;
+
+ INSIST(client->nctls == 0);
+ client->nctls++;
+ ev = &client->ctlevent;
+ isc_task_send(client->task, &ev);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
+ ns_interface_t *ifp, bool tcp)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned int disp;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(n > 0);
+
+ MTRACE("createclients");
+
+ for (disp = 0; disp < n; disp++) {
+ result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+
+ return (result);
+}
+
+isc_sockaddr_t *
+ns_client_getsockaddr(ns_client_t *client) {
+ return (&client->peeraddr);
+}
+
+isc_sockaddr_t *
+ns_client_getdestaddr(ns_client_t *client) {
+ return (&client->destsockaddr);
+}
+
+isc_result_t
+ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
+ dns_acl_t *acl, bool default_allow)
+{
+ isc_result_t result;
+ isc_netaddr_t tmpnetaddr;
+ isc_netaddr_t *ecs_addr = NULL;
+ uint8_t ecs_addrlen = 0;
+ int match;
+
+ if (acl == NULL) {
+ if (default_allow)
+ goto allow;
+ else
+ goto deny;
+ }
+
+ if (netaddr == NULL) {
+ isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
+ netaddr = &tmpnetaddr;
+ }
+
+ if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
+ ecs_addr = &client->ecs_addr;
+ ecs_addrlen = client->ecs_addrlen;
+ }
+
+ result = dns_acl_match2(netaddr, client->signer,
+ ecs_addr, ecs_addrlen, NULL, acl,
+ &ns_g_server->aclenv, &match, NULL);
+
+ if (result != ISC_R_SUCCESS)
+ goto deny; /* Internal error, already logged. */
+
+ if (match > 0)
+ goto allow;
+ goto deny; /* Negative match or no match. */
+
+ allow:
+ return (ISC_R_SUCCESS);
+
+ deny:
+ return (DNS_R_REFUSED);
+}
+
+isc_result_t
+ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
+ const char *opname, dns_acl_t *acl,
+ bool default_allow, int log_level)
+{
+ isc_result_t result;
+ isc_netaddr_t netaddr;
+
+ if (sockaddr != NULL)
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+
+ result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
+ acl, default_allow);
+
+ if (result == ISC_R_SUCCESS)
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "%s approved", opname);
+ else
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT,
+ log_level, "%s denied", opname);
+ return (result);
+}
+
+static void
+ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
+ if (client->peeraddr_valid)
+ isc_sockaddr_format(&client->peeraddr, peerbuf,
+ (unsigned int)len);
+ else
+ snprintf(peerbuf, len, "@%p", client);
+}
+
+void
+ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, va_list ap)
+{
+ char msgbuf[4096];
+ char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ const char *viewname = "";
+ const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
+ const char *signer = "", *qname = "";
+ dns_name_t *q = NULL;
+
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+
+ if (client->signer != NULL) {
+ dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
+ sep1 = "/key ";
+ signer = signerbuf;
+ }
+
+ q = client->query.origqname != NULL
+ ? client->query.origqname : client->query.qname;
+ if (q != NULL) {
+ dns_name_format(q, qnamebuf, sizeof(qnamebuf));
+ sep2 = " (";
+ sep3 = ")";
+ qname = qnamebuf;
+ }
+
+ if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
+ strcmp(client->view->name, "_default") != 0) {
+ sep4 = ": view ";
+ viewname = client->view->name;
+ }
+
+ if (client->peeraddr_valid) {
+ isc_sockaddr_format(&client->peeraddr,
+ peerbuf, sizeof(peerbuf));
+ } else {
+ snprintf(peerbuf, sizeof(peerbuf), "(no-peer)");
+ }
+
+ isc_log_write(ns_g_lctx, category, module, level,
+ "client @%p %s%s%s%s%s%s%s%s: %s",
+ client, peerbuf, sep1, signer, sep2, qname, sep3,
+ sep4, viewname, msgbuf);
+}
+
+void
+ns_client_log(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (! isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ ns_client_logv(client, category, module, level, fmt, ap);
+ va_end(ap);
+}
+
+void
+ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataclass_t rdclass, char *buf, size_t len)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+ dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
+ (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
+ classbuf);
+}
+
+static void
+ns_client_dumpmessage(ns_client_t *client, const char *reason) {
+ isc_buffer_t buffer;
+ char *buf = NULL;
+ int len = 1024;
+ isc_result_t result;
+
+ if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)))
+ return;
+
+ /*
+ * Note that these are multiline debug messages. We want a newline
+ * to appear in the log after each message.
+ */
+
+ do {
+ buf = isc_mem_get(client->mctx, len);
+ if (buf == NULL)
+ break;
+ isc_buffer_init(&buffer, buf, len);
+ result = dns_message_totext(client->message,
+ &dns_master_style_debug,
+ 0, &buffer);
+ if (result == ISC_R_NOSPACE) {
+ isc_mem_put(client->mctx, buf, len);
+ len += 1024;
+ } else if (result == ISC_R_SUCCESS)
+ ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "%s\n%.*s", reason,
+ (int)isc_buffer_usedlength(&buffer),
+ buf);
+ } while (result == ISC_R_NOSPACE);
+
+ if (buf != NULL)
+ isc_mem_put(client->mctx, buf, len);
+}
+
+void
+ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
+ ns_client_t *client;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char original[DNS_NAME_FORMATSIZE];
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ const char *name;
+ const char *sep;
+ const char *origfor;
+ dns_rdataset_t *rdataset;
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&manager->reclock);
+ client = ISC_LIST_HEAD(manager->recursing);
+ while (client != NULL) {
+ INSIST(client->state == NS_CLIENTSTATE_RECURSING);
+
+ ns_client_name(client, peerbuf, sizeof(peerbuf));
+ if (client->view != NULL &&
+ strcmp(client->view->name, "_bind") != 0 &&
+ strcmp(client->view->name, "_default") != 0) {
+ name = client->view->name;
+ sep = ": view ";
+ } else {
+ name = "";
+ sep = "";
+ }
+
+ LOCK(&client->query.fetchlock);
+ INSIST(client->query.qname != NULL);
+ dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
+ if (client->query.qname != client->query.origqname &&
+ client->query.origqname != NULL) {
+ origfor = " for ";
+ dns_name_format(client->query.origqname, original,
+ sizeof(original));
+ } else {
+ origfor = "";
+ original[0] = '\0';
+ }
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ if (rdataset == NULL && client->query.origqname != NULL)
+ rdataset = ISC_LIST_HEAD(client->query.origqname->list);
+ if (rdataset != NULL) {
+ dns_rdatatype_format(rdataset->type, typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(rdataset->rdclass, classbuf,
+ sizeof(classbuf));
+ } else {
+ strlcpy(typebuf, "-", sizeof(typebuf));
+ strlcpy(classbuf, "-", sizeof(classbuf));
+ }
+ UNLOCK(&client->query.fetchlock);
+ fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
+ "requesttime %u\n", peerbuf, sep, name,
+ client->message->id, namebuf, typebuf, classbuf,
+ origfor, original,
+ isc_time_seconds(&client->requesttime));
+ client = ISC_LIST_NEXT(client, rlink);
+ }
+ UNLOCK(&manager->reclock);
+}
+
+void
+ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
+ LOCK(&client->query.fetchlock);
+ if (client->query.restarts > 0) {
+ /*
+ * client->query.qname was dynamically allocated.
+ */
+ dns_message_puttempname(client->message,
+ &client->query.qname);
+ }
+ client->query.qname = name;
+ client->query.attributes &= ~NS_QUERYATTR_REDIRECT;
+ UNLOCK(&client->query.fetchlock);
+}
+
+isc_result_t
+ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
+ ns_client_t *client = (ns_client_t *) ci->data;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(addrp != NULL);
+
+ *addrp = &client->peeraddr;
+ return (ISC_R_SUCCESS);
+}
diff --git a/bin/named/config.c b/bin/named/config.c
new file mode 100644
index 0000000..2732a8f
--- /dev/null
+++ b/bin/named/config.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.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 <pk11/site.h>
+
+#include <isccfg/grammar.h>
+#include <isccfg/namedconf.h>
+
+#include <dns/fixedname.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 <named/config.h>
+#include <named/globals.h>
+
+#include <bind.keys.h>
+
+/*% default configuration */
+static char defaultconf[] = "\
+options {\n\
+ answer-cookie true;\n\
+ automatic-interface-scan yes;\n\
+ bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
+# blackhole {none;};\n"
+#if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES)
+" cookie-algorithm aes;\n"
+#else
+" cookie-algorithm sha256;\n"
+#endif
+#ifndef WIN32
+" coresize default;\n\
+ datasize default;\n"
+#endif
+"\
+# deallocate-on-exit <obsolete>;\n\
+# directory <none>\n\
+ dump-file \"named_dump.db\";\n\
+ edns-udp-size 4096;\n\
+# fake-iquery <obsolete>;\n"
+#ifndef WIN32
+" files unlimited;\n"
+#endif
+"\
+# has-old-clients <obsolete>;\n\
+ heartbeat-interval 60;\n\
+# host-statistics <obsolete>;\n\
+ interface-interval 60;\n\
+# keep-response-order {none;};\n\
+ listen-on {any;};\n\
+ listen-on-v6 {any;};\n\
+# lock-file \"" NS_LOCALSTATEDIR "/run/named/named.lock\";\n\
+ match-mapped-addresses no;\n\
+ max-rsa-exponent-size 0; /* no limit */\n\
+ max-udp-size 4096;\n\
+ memstatistics-file \"named.memstats\";\n\
+# multiple-cnames <obsolete>;\n\
+# named-xfer <obsolete>;\n\
+ nocookie-udp-size 4096;\n\
+ notify-rate 20;\n\
+ nta-lifetime 3600;\n\
+ nta-recheck 300;\n\
+# pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
+ port 53;\n\
+ prefetch 2 9;\n"
+#ifdef PATH_RANDOMDEV
+" random-device \"" PATH_RANDOMDEV "\";\n"
+#endif
+" 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-queries <obsolete>;\n\
+ serial-query-rate 20;\n\
+ server-id none;\n\
+ session-keyalg hmac-sha256;\n\
+# session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\
+ session-keyname local-ddns;\n"
+#ifndef WIN32
+" stacksize default;\n"
+#endif
+" startup-notify-rate 20;\n\
+ statistics-file \"named.stats\";\n\
+# statistics-interval <obsolete>;\n\
+ tcp-clients 150;\n\
+ tcp-listen-queue 10;\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\
+# treat-cr-as-space <obsolete>;\n\
+ trust-anchor-telemetry yes;\n\
+# use-id-pool <obsolete>;\n\
+# use-ixfr <obsolete>;\n\
+\n\
+ /* view */\n\
+ acache-cleaning-interval 60;\n\
+ acache-enable no;\n\
+ additional-from-auth true;\n\
+ additional-from-cache true;\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\
+# allow-v6-synthesis <obsolete>;\n\
+ auth-nxdomain false;\n\
+ check-dup-records warn;\n\
+ check-mx warn;\n\
+ check-names master fail;\n\
+ check-names response ignore;\n\
+ check-names slave warn;\n\
+ check-spf warn;\n\
+ cleaning-interval 0; /* now meaningless */\n\
+ clients-per-query 10;\n\
+ dnssec-accept-expired no;\n\
+ dnssec-enable yes;\n\
+ dnssec-validation yes; \n"
+#ifdef HAVE_DNSTAP
+" dnstap-identity hostname;\n"
+#endif
+"\
+# fetch-glue <obsolete>;\n\
+ fetch-quota-params 100 0.1 0.3 0.7;\n\
+ fetches-per-server 0;\n\
+ fetches-per-zone 0;\n"
+#ifdef ALLOW_FILTER_AAAA
+" filter-aaaa-on-v4 no;\n\
+ filter-aaaa-on-v6 no;\n\
+ filter-aaaa { any; };\n"
+#endif
+#ifdef HAVE_GEOIP
+" geoip-use-ecs yes;\n"
+#endif
+" lame-ttl 600;\n"
+#ifdef HAVE_LMDB
+" lmdb-mapsize 32M;\n"
+#endif
+" max-acache-size 16M;\n\
+ 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 75;\n\
+ message-compression yes;\n\
+# min-roots <obsolete>;\n\
+ minimal-any false;\n\
+ minimal-responses false;\n\
+ notify-source *;\n\
+ notify-source-v6 *;\n\
+ nsec3-test-zone no;\n\
+ provide-ixfr true;\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\
+# rfc2308-type1 <obsolete>;\n\
+ root-key-sentinel yes;\n\
+ servfail-ttl 1;\n\
+# sortlist <none>\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 no;\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\
+# maintain-ixfr-base <obsolete>;\n\
+# max-ixfr-log-size <obsolete>\n\
+ max-journal-size unlimited;\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\
+ 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\
+\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 master;\n\
+ database \"_builtin version\";\n\
+ };\n\
+\n\
+ zone \"hostname.bind\" chaos {\n\
+ type master;\n\
+ database \"_builtin hostname\";\n\
+ };\n\
+\n\
+ zone \"authors.bind\" chaos {\n\
+ type master;\n\
+ database \"_builtin authors\";\n\
+ };\n\
+\n\
+ zone \"id.server\" chaos {\n\
+ type master;\n\
+ database \"_builtin id\";\n\
+ };\n\
+};\n\
+"
+"#\n\
+# Default trusted key(s), used if \n\
+# \"dnssec-validation auto;\" is set and\n\
+# sysconfdir/bind.keys doesn't exist).\n\
+#\n\
+# BEGIN MANAGED KEYS\n"
+
+/* Imported from bind.keys.h: */
+MANAGED_KEYS
+
+"# END MANAGED KEYS\n\
+";
+
+isc_result_t
+ns_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_buffer4(parser, &b, __FILE__, 0,
+ &cfg_type_namedconf,
+ CFG_PCTX_NODEPRECATED, conf));
+}
+
+isc_result_t
+ns_config_get(cfg_obj_t const * const *maps, const char *name,
+ const cfg_obj_t **obj)
+{
+ int i;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_R_NOTFOUND);
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+ }
+}
+
+isc_result_t
+ns_checknames_get(const cfg_obj_t **maps, const char *which,
+ 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;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_R_NOTFOUND);
+ 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");
+ if (strcasecmp(cfg_obj_asstring(type),
+ which) == 0) {
+ *obj = cfg_tuple_get(value, "mode");
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ }
+ }
+}
+
+int
+ns_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
+ns_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, ns_g_lctx, ISC_LOG_ERROR,
+ "unknown class '%s'", r.base);
+ return (result);
+}
+
+isc_result_t
+ns_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, ns_g_lctx, ISC_LOG_ERROR,
+ "unknown type '%s'", r.base);
+ return (result);
+}
+
+dns_zonetype_t
+ns_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, "master") == 0)
+ ztype = dns_zone_master;
+ else if (strcasecmp(str, "slave") == 0)
+ ztype = dns_zone_slave;
+ 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
+ INSIST(0);
+ return (ztype);
+}
+
+isc_result_t
+ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
+ in_port_t defport, isc_mem_t *mctx,
+ isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
+ uint32_t *countp)
+{
+ int count, i = 0;
+ const cfg_obj_t *addrlist;
+ const cfg_obj_t *portobj, *dscpobj;
+ const cfg_listelt_t *element;
+ isc_sockaddr_t *addrs;
+ in_port_t port;
+ isc_dscp_t dscp = -1, *dscps = NULL;
+ isc_result_t result;
+
+ INSIST(addrsp != NULL && *addrsp == NULL);
+ INSIST(dscpsp == NULL || *dscpsp == NULL);
+ INSIST(countp != NULL);
+
+ addrlist = cfg_tuple_get(list, "addresses");
+ count = ns_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, ns_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 = ns_config_getport(config, &port);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ if (dscpsp != NULL) {
+ dscpobj = cfg_tuple_get(list, "dscp");
+ if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
+ if (cfg_obj_asuint32(dscpobj) > 63) {
+ cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+ "dscp value '%u' is out of range",
+ cfg_obj_asuint32(dscpobj));
+ return (ISC_R_RANGE);
+ }
+ dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+ }
+
+ dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t));
+ if (dscps == NULL)
+ return (ISC_R_NOMEMORY);
+ }
+
+ addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
+ if (addrs == NULL) {
+ if (dscps != NULL)
+ isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
+ return (ISC_R_NOMEMORY);
+ }
+
+ 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 (dscpsp != NULL) {
+ isc_dscp_t innerdscp;
+ innerdscp = cfg_obj_getdscp(addr);
+ if (innerdscp == -1)
+ innerdscp = dscp;
+ dscps[i] = innerdscp;
+ }
+ if (isc_sockaddr_getport(&addrs[i]) == 0)
+ isc_sockaddr_setport(&addrs[i], port);
+ }
+ INSIST(i == count);
+
+ *addrsp = addrs;
+ *countp = count;
+
+ if (dscpsp != NULL)
+ *dscpsp = dscps;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ isc_dscp_t **dscpsp, uint32_t count)
+{
+ INSIST(addrsp != NULL && *addrsp != NULL);
+ INSIST(dscpsp == NULL || *dscpsp != NULL);
+
+ isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
+ *addrsp = NULL;
+
+ if (dscpsp != NULL) {
+ isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
+ *dscpsp = NULL;
+ }
+}
+
+static isc_result_t
+get_masters_def(const cfg_obj_t *cctx, const char *name,
+ const cfg_obj_t **ret)
+{
+ isc_result_t result;
+ const cfg_obj_t *masters = NULL;
+ const cfg_listelt_t *elt;
+
+ result = cfg_map_get(cctx, "masters", &masters);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (elt = cfg_list_first(masters);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *list;
+ const char *listname;
+
+ list = cfg_listelt_value(elt);
+ listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+ if (strcasecmp(listname, name) == 0) {
+ *ret = list;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
+ isc_mem_t *mctx, dns_ipkeylist_t *ipkl)
+{
+ uint32_t addrcount = 0, dscpcount = 0, keycount = 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;
+ const cfg_obj_t *dscpobj;
+ in_port_t port;
+ isc_dscp_t dscp = -1;
+ dns_fixedname_t fname;
+ isc_sockaddr_t *addrs = NULL;
+ isc_dscp_t *dscps = NULL;
+ dns_name_t **keys = NULL;
+ struct { const char *name; } *lists = NULL;
+ struct {
+ const cfg_listelt_t *element;
+ in_port_t port;
+ isc_dscp_t dscp;
+ } *stack = NULL;
+
+ REQUIRE(ipkl != NULL);
+ REQUIRE(ipkl->count == 0);
+ REQUIRE(ipkl->addrs == NULL);
+ REQUIRE(ipkl->keys == NULL);
+ REQUIRE(ipkl->dscps == NULL);
+ REQUIRE(ipkl->labels == NULL);
+ REQUIRE(ipkl->allocated == 0);
+
+ /*
+ * Get system defaults.
+ */
+ result = ns_config_getport(config, &port);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = ns_config_getdscp(config, &dscp);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ newlist:
+ addrlist = cfg_tuple_get(list, "addresses");
+ portobj = cfg_tuple_get(list, "port");
+ dscpobj = cfg_tuple_get(list, "dscp");
+
+ if (cfg_obj_isuint32(portobj)) {
+ uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ port = (in_port_t) val;
+ }
+
+ if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
+ if (cfg_obj_asuint32(dscpobj) > 63) {
+ cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+ "dscp value '%u' is out of range",
+ cfg_obj_asuint32(dscpobj));
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+ }
+
+ 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 char *keystr;
+ isc_buffer_t b;
+
+ addr = cfg_tuple_get(cfg_listelt_value(element),
+ "masterselement");
+ key = cfg_tuple_get(cfg_listelt_value(element), "key");
+
+ if (!cfg_obj_issockaddr(addr)) {
+ const char *listname = cfg_obj_asstring(addr);
+ isc_result_t tresult;
+
+ /* Grow lists? */
+ if (listcount == l) {
+ void * tmp;
+ uint32_t newlen = listcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*lists);
+ oldsize = listcount * sizeof(*lists);
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ if (listcount != 0) {
+ memmove(tmp, lists, oldsize);
+ isc_mem_put(mctx, lists, oldsize);
+ }
+ lists = tmp;
+ listcount = newlen;
+ }
+ /* Seen? */
+ for (j = 0; j < l; j++)
+ if (strcasecmp(lists[j].name, listname) == 0)
+ break;
+ if (j < l)
+ continue;
+ tresult = get_masters_def(config, listname, &list);
+ if (tresult == ISC_R_NOTFOUND) {
+ cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
+ "masters \"%s\" not found", listname);
+
+ result = tresult;
+ goto cleanup;
+ }
+ if (tresult != ISC_R_SUCCESS)
+ goto cleanup;
+ lists[l++].name = listname;
+ /* Grow stack? */
+ if (stackcount == pushed) {
+ void * tmp;
+ uint32_t newlen = stackcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*stack);
+ oldsize = stackcount * sizeof(*stack);
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ if (stackcount != 0) {
+ memmove(tmp, stack, oldsize);
+ isc_mem_put(mctx, stack, oldsize);
+ }
+ stack = tmp;
+ stackcount = newlen;
+ }
+ /*
+ * We want to resume processing this list on the
+ * next element.
+ */
+ stack[pushed].element = cfg_list_next(element);
+ stack[pushed].port = port;
+ stack[pushed].dscp = dscp;
+ pushed++;
+ goto newlist;
+ }
+
+ if (i == addrcount) {
+ void * tmp;
+ uint32_t newlen = addrcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(isc_sockaddr_t);
+ oldsize = addrcount * sizeof(isc_sockaddr_t);
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ if (addrcount != 0) {
+ memmove(tmp, addrs, oldsize);
+ isc_mem_put(mctx, addrs, oldsize);
+ }
+ addrs = tmp;
+ addrcount = newlen;
+
+ newsize = newlen * sizeof(isc_dscp_t);
+ oldsize = dscpcount * sizeof(isc_dscp_t);
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ if (dscpcount != 0) {
+ memmove(tmp, dscps, oldsize);
+ isc_mem_put(mctx, dscps, oldsize);
+ }
+ dscps = tmp;
+ dscpcount = newlen;
+
+ newsize = newlen * sizeof(dns_name_t *);
+ oldsize = keycount * sizeof(dns_name_t *);
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ if (keycount != 0) {
+ memmove(tmp, keys, oldsize);
+ isc_mem_put(mctx, keys, oldsize);
+ }
+ keys = tmp;
+ keycount = newlen;
+ }
+
+ addrs[i] = *cfg_obj_assockaddr(addr);
+ if (isc_sockaddr_getport(&addrs[i]) == 0)
+ isc_sockaddr_setport(&addrs[i], port);
+ dscps[i] = cfg_obj_getdscp(addr);
+ if (dscps[i] == -1)
+ dscps[i] = dscp;
+ keys[i] = NULL;
+ i++; /* Increment here so that cleanup on error works. */
+ if (!cfg_obj_isstring(key))
+ continue;
+ keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (keys[i - 1] == NULL)
+ goto cleanup;
+ dns_name_init(keys[i - 1], NULL);
+
+ keystr = cfg_obj_asstring(key);
+ isc_buffer_constinit(&b, keystr, strlen(keystr));
+ isc_buffer_add(&b, strlen(keystr));
+ dns_fixedname_init(&fname);
+ result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
+ dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_name_dup(dns_fixedname_name(&fname), mctx,
+ keys[i - 1]);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ if (pushed != 0) {
+ pushed--;
+ element = stack[pushed].element;
+ port = stack[pushed].port;
+ dscp = stack[pushed].dscp;
+ goto resume;
+ }
+ if (i < addrcount) {
+ void * tmp;
+ size_t newsize, oldsize;
+
+ newsize = i * sizeof(isc_sockaddr_t);
+ oldsize = addrcount * sizeof(isc_sockaddr_t);
+ if (i != 0) {
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ memmove(tmp, addrs, newsize);
+ } else
+ tmp = NULL;
+ isc_mem_put(mctx, addrs, oldsize);
+ addrs = tmp;
+ addrcount = i;
+
+ newsize = i * sizeof(isc_dscp_t);
+ oldsize = dscpcount * sizeof(isc_dscp_t);
+ if (i != 0) {
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ memmove(tmp, dscps, newsize);
+ } else
+ tmp = NULL;
+ isc_mem_put(mctx, dscps, oldsize);
+ dscps = tmp;
+ dscpcount = i;
+
+ newsize = i * sizeof(dns_name_t *);
+ oldsize = keycount * sizeof(dns_name_t *);
+ if (i != 0) {
+ tmp = isc_mem_get(mctx, newsize);
+ if (tmp == NULL)
+ goto cleanup;
+ memmove(tmp, keys, newsize);
+ } else
+ tmp = NULL;
+ isc_mem_put(mctx, keys, oldsize);
+ keys = tmp;
+ keycount = i;
+ }
+
+ if (lists != NULL)
+ isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+
+ INSIST(keycount == addrcount);
+
+ ipkl->addrs = addrs;
+ ipkl->dscps = dscps;
+ ipkl->keys = keys;
+ ipkl->count = addrcount;
+ ipkl->allocated = addrcount;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (addrs != NULL)
+ isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
+ if (dscps != NULL)
+ isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t));
+ 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(dns_name_t));
+ }
+ isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
+ }
+ if (lists != NULL)
+ isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+ return (result);
+}
+
+isc_result_t
+ns_config_getport(const cfg_obj_t *config, 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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ result = ns_config_get(maps, "port", &portobj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_asuint32(portobj) >= UINT16_MAX) {
+ cfg_obj_log(portobj, ns_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);
+}
+
+isc_result_t
+ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) {
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *dscpobj = NULL;
+ isc_result_t result;
+
+ (void)cfg_map_get(config, "options", &options);
+ if (options == NULL)
+ return (ISC_R_SUCCESS);
+
+ result = cfg_map_get(options, "dscp", &dscpobj);
+ if (result != ISC_R_SUCCESS || dscpobj == NULL) {
+ *dscpp = -1;
+ return (ISC_R_SUCCESS);
+ }
+ if (cfg_obj_asuint32(dscpobj) >= 64) {
+ cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+ "dscp '%u' out of range",
+ cfg_obj_asuint32(dscpobj));
+ return (ISC_R_RANGE);
+ }
+ *dscpp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+ 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[] = {
+#ifndef PK11_MD5_DISABLE
+ { "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 },
+#endif
+ { "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
+ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
+ uint16_t *digestbits)
+{
+ return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits));
+}
+
+isc_result_t
+ns_config_getkeyalgorithm2(const char *str, 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) {
+#ifndef PK11_MD5_DISABLE
+ case hmacmd5: *name = dns_tsig_hmacmd5_name; break;
+#endif
+ 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:
+ INSIST(0);
+ }
+ }
+ 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..c53d8d0
--- /dev/null
+++ b/bin/named/control.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <isc/app.h>
+#include <isc/event.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+
+#include <isccc/alist.h>
+#include <isccc/cc.h>
+#include <isccc/result.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/ns_smf_globals.h>
+#endif
+
+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 inline 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
+ns_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
+ ns_smf_want_disable = 0;
+#endif
+
+ 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(ns_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, NS_COMMAND_NULL) ||
+ command_compare(command, NS_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, NS_COMMAND_NTA) &&
+ !command_compare(command, NS_COMMAND_NULL) &&
+ !command_compare(command, NS_COMMAND_STATUS) &&
+ !command_compare(command, NS_COMMAND_SHOWZONE) &&
+ !command_compare(command, NS_COMMAND_TESTGEN) &&
+ !command_compare(command, NS_COMMAND_ZONESTATUS))
+ {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, log_level,
+ "rejecting restricted control channel "
+ "command '%s'", cmdline);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, log_level,
+ "received control channel command '%s'",
+ cmdline);
+
+ if (command_compare(command, NS_COMMAND_RELOAD)) {
+ result = ns_server_reloadcommand(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_RECONFIG)) {
+ result = ns_server_reconfigcommand(ns_g_server);
+ } else if (command_compare(command, NS_COMMAND_REFRESH)) {
+ result = ns_server_refreshcommand(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_RETRANSFER)) {
+ result = ns_server_retransfercommand(ns_g_server,
+ lex, text);
+ } else if (command_compare(command, NS_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 (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
+ result = ns_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 (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
+ ns_smf_want_disable = 1;
+ /*
+ * If ns_smf_got_instance = 0, ns_smf_chroot
+ * is not relevant and we fall through to
+ * isc_app_shutdown below.
+ */
+#endif
+ /* Do not flush master files */
+ ns_server_flushonshutdown(ns_g_server, false);
+ ns_os_shutdownmsg(cmdline, *text);
+ isc_app_shutdown();
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_STOP)) {
+ /*
+ * "stop" is the same as "halt" except it does
+ * flush master files.
+ */
+#ifdef HAVE_LIBSCF
+ if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
+ result = ns_smf_add_message(text);
+ goto cleanup;
+ }
+ if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
+ ns_smf_want_disable = 1;
+#endif
+ ns_server_flushonshutdown(ns_g_server, true);
+ ns_os_shutdownmsg(cmdline, *text);
+ isc_app_shutdown();
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_DUMPSTATS)) {
+ result = ns_server_dumpstats(ns_g_server);
+ } else if (command_compare(command, NS_COMMAND_QUERYLOG)) {
+ result = ns_server_togglequerylog(ns_g_server, lex);
+ } else if (command_compare(command, NS_COMMAND_DUMPDB)) {
+ ns_server_dumpdb(ns_g_server, lex, text);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_SECROOTS)) {
+ result = ns_server_dumpsecroots(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_TRACE)) {
+ result = ns_server_setdebuglevel(ns_g_server, lex);
+ } else if (command_compare(command, NS_COMMAND_NOTRACE)) {
+ ns_g_debuglevel = 0;
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_FLUSH)) {
+ result = ns_server_flushcache(ns_g_server, lex);
+ } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) {
+ result = ns_server_flushnode(ns_g_server, lex, false);
+ } else if (command_compare(command, NS_COMMAND_FLUSHTREE)) {
+ result = ns_server_flushnode(ns_g_server, lex, true);
+ } else if (command_compare(command, NS_COMMAND_STATUS)) {
+ result = ns_server_status(ns_g_server, text);
+ } else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
+ result = ns_server_tsiglist(ns_g_server, text);
+ } else if (command_compare(command, NS_COMMAND_TSIGDELETE)) {
+ result = ns_server_tsigdelete(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_FREEZE)) {
+ result = ns_server_freeze(ns_g_server, true, lex,
+ text);
+ } else if (command_compare(command, NS_COMMAND_UNFREEZE) ||
+ command_compare(command, NS_COMMAND_THAW)) {
+ result = ns_server_freeze(ns_g_server, false, lex,
+ text);
+ } else if (command_compare(command, NS_COMMAND_SCAN)) {
+ result = ISC_R_SUCCESS;
+ ns_server_scan_interfaces(ns_g_server);
+ } else if (command_compare(command, NS_COMMAND_SYNC)) {
+ result = ns_server_sync(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_RECURSING)) {
+ result = ns_server_dumprecursing(ns_g_server);
+ } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) {
+ result = ISC_R_SUCCESS;
+ isc_timermgr_poke(ns_g_timermgr);
+ } else if (command_compare(command, NS_COMMAND_NULL)) {
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_NOTIFY)) {
+ result = ns_server_notifycommand(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_VALIDATION)) {
+ result = ns_server_validation(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_SIGN) ||
+ command_compare(command, NS_COMMAND_LOADKEYS)) {
+ result = ns_server_rekey(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_ADDZONE) ||
+ command_compare(command, NS_COMMAND_MODZONE)) {
+ result = ns_server_changezone(ns_g_server, cmdline, text);
+ } else if (command_compare(command, NS_COMMAND_DELZONE)) {
+ result = ns_server_delzone(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_SHOWZONE)) {
+ result = ns_server_showzone(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_SIGNING)) {
+ result = ns_server_signing(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_ZONESTATUS)) {
+ result = ns_server_zonestatus(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_NTA)) {
+ result = ns_server_nta(ns_g_server, lex, readonly, text);
+ } else if (command_compare(command, NS_COMMAND_TESTGEN)) {
+ result = ns_server_testgen(lex, text);
+ } else if (command_compare(command, NS_COMMAND_MKEYS)) {
+ result = ns_server_mkeys(ns_g_server, lex, text);
+ } else if (command_compare(command, NS_COMMAND_DNSTAP) ||
+ command_compare(command, NS_COMMAND_DNSTAPREOPEN)) {
+ result = ns_server_dnstap(ns_g_server, lex, text);
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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..d955c2f
--- /dev/null
+++ b/bin/named/controlconf.c
@@ -0,0 +1,1530 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <isccc/alist.h>
+#include <isccc/cc.h>
+#include <isccc/ccmsg.h>
+#include <isccc/events.h>
+#include <isccc/result.h>
+#include <isccc/sexpr.h>
+#include <isccc/symtab.h>
+#include <isccc/util.h>
+
+#include <dns/result.h>
+
+#include <named/config.h>
+#include <named/control.h>
+#include <named/log.h>
+#include <named/server.h>
+
+/*
+ * Note: Listeners and connections are not locked. All event handlers are
+ * executed by the server task, and all callers of exported routines must
+ * be running under the server task.
+ */
+
+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_socket_t * sock;
+ isccc_ccmsg_t ccmsg;
+ bool ccmsg_valid;
+ bool sending;
+ isc_timer_t * timer;
+ isc_buffer_t * buffer;
+ controllistener_t * listener;
+ uint32_t nonce;
+ ISC_LINK(controlconnection_t) link;
+};
+
+struct controllistener {
+ ns_controls_t * controls;
+ isc_mem_t * mctx;
+ isc_task_t * task;
+ isc_sockaddr_t address;
+ isc_socket_t * sock;
+ dns_acl_t * acl;
+ bool listening;
+ bool exiting;
+ controlkeylist_t keys;
+ controlconnectionlist_t connections;
+ isc_sockettype_t type;
+ uint32_t perm;
+ uint32_t owner;
+ uint32_t group;
+ bool readonly;
+ ISC_LINK(controllistener_t) link;
+};
+
+struct ns_controls {
+ ns_server_t *server;
+ controllistenerlist_t listeners;
+ bool shuttingdown;
+ isccc_symtab_t *symtab;
+};
+
+static void control_newconn(isc_task_t *task, isc_event_t *event);
+static void control_recvmessage(isc_task_t *task, isc_event_t *event);
+
+#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(!listener->listening);
+ INSIST(ISC_LIST_EMPTY(listener->connections));
+
+ if (listener->sock != NULL)
+ isc_socket_detach(&listener->sock);
+
+ free_controlkeylist(&listener->keys, listener->mctx);
+
+ if (listener->acl != NULL)
+ dns_acl_detach(&listener->acl);
+
+ isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
+}
+
+static void
+maybe_free_listener(controllistener_t *listener) {
+ if (listener->exiting &&
+ !listener->listening &&
+ ISC_LIST_EMPTY(listener->connections))
+ free_listener(listener);
+}
+
+static void
+maybe_free_connection(controlconnection_t *conn) {
+ controllistener_t *listener = conn->listener;
+
+ if (conn->buffer != NULL)
+ isc_buffer_free(&conn->buffer);
+
+ if (conn->timer != NULL)
+ isc_timer_detach(&conn->timer);
+
+ if (conn->ccmsg_valid) {
+ isccc_ccmsg_cancelread(&conn->ccmsg);
+ return;
+ }
+
+ if (conn->sending) {
+ isc_socket_cancel(conn->sock, listener->task,
+ ISC_SOCKCANCEL_SEND);
+ return;
+ }
+
+ ISC_LIST_UNLINK(listener->connections, conn, link);
+#ifdef ENABLE_AFL
+ if (ns_g_fuzz_type == ns_fuzz_rndc) {
+ named_fuzz_notify();
+ }
+#endif
+ isc_mem_put(listener->mctx, conn, sizeof(*conn));
+}
+
+static void
+shutdown_listener(controllistener_t *listener) {
+ controlconnection_t *conn;
+ controlconnection_t *next;
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "stopping command channel on %s", socktext);
+ if (listener->type == isc_sockettype_unix)
+ isc_socket_cleanunix(&listener->address, true);
+ listener->exiting = true;
+ }
+
+ for (conn = ISC_LIST_HEAD(listener->connections);
+ conn != NULL;
+ conn = next)
+ {
+ next = ISC_LIST_NEXT(conn, link);
+ maybe_free_connection(conn);
+ }
+
+ if (listener->listening)
+ isc_socket_cancel(listener->sock, listener->task,
+ ISC_SOCKCANCEL_ACCEPT);
+
+ maybe_free_listener(listener);
+}
+
+static bool
+address_ok(isc_sockaddr_t *sockaddr, dns_acl_t *acl) {
+ isc_netaddr_t netaddr;
+ isc_result_t result;
+ int match;
+
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+
+ result = dns_acl_match(&netaddr, NULL, acl,
+ &ns_g_server->aclenv, &match, NULL);
+
+ if (result != ISC_R_SUCCESS || match <= 0)
+ return (false);
+ else
+ return (true);
+}
+
+static isc_result_t
+control_accept(controllistener_t *listener) {
+ isc_result_t result;
+ result = isc_socket_accept(listener->sock,
+ listener->task,
+ control_newconn, listener);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_accept() failed: %s",
+ isc_result_totext(result));
+ else
+ listener->listening = true;
+ return (result);
+}
+
+static isc_result_t
+control_listen(controllistener_t *listener) {
+ isc_result_t result;
+
+ result = isc_socket_listen(listener->sock, 0);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_listen() failed: %s",
+ isc_result_totext(result));
+ return (result);
+}
+
+static void
+control_next(controllistener_t *listener) {
+ (void)control_accept(listener);
+}
+
+static void
+control_senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *) event;
+ controlconnection_t *conn = event->ev_arg;
+ controllistener_t *listener = conn->listener;
+ isc_socket_t *sock = (isc_socket_t *)sevent->ev_sender;
+ isc_result_t result;
+
+ REQUIRE(conn->sending);
+
+ UNUSED(task);
+
+ conn->sending = false;
+
+ if (sevent->result != ISC_R_SUCCESS &&
+ sevent->result != ISC_R_CANCELED)
+ {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t peeraddr;
+
+ (void)isc_socket_getpeername(sock, &peeraddr);
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "error sending command response to %s: %s",
+ socktext, isc_result_totext(sevent->result));
+ }
+ isc_event_free(&event);
+
+ result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
+ control_recvmessage, conn);
+ if (result != ISC_R_SUCCESS) {
+ isc_socket_detach(&conn->sock);
+ maybe_free_connection(conn);
+ maybe_free_listener(listener);
+ }
+}
+
+static inline void
+log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t peeraddr;
+
+ (void)isc_socket_getpeername(ccmsg->sock, &peeraddr);
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_ERROR,
+ "invalid command from %s: %s",
+ socktext, isc_result_totext(result));
+}
+
+static void
+control_recvmessage(isc_task_t *task, isc_event_t *event) {
+ controlconnection_t *conn;
+ controllistener_t *listener;
+ controlkey_t *key;
+ isccc_sexpr_t *request = NULL;
+ isccc_sexpr_t *response = NULL;
+ uint32_t algorithm;
+ isccc_region_t secret;
+ isc_stdtime_t now;
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_buffer_t *text;
+ isc_result_t result;
+ isc_result_t eresult;
+ isccc_sexpr_t *_ctrl;
+ isccc_time_t sent;
+ isccc_time_t exp;
+ uint32_t nonce;
+ isccc_sexpr_t *data;
+
+ REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);
+
+ conn = event->ev_arg;
+ listener = conn->listener;
+ algorithm = DST_ALG_UNKNOWN;
+ secret.rstart = NULL;
+ text = NULL;
+
+ /* Is the server shutting down? */
+ if (listener->controls->shuttingdown)
+ goto cleanup;
+
+ if (conn->ccmsg.result != ISC_R_SUCCESS) {
+ if (conn->ccmsg.result != ISC_R_CANCELED &&
+ conn->ccmsg.result != ISC_R_EOF)
+ log_invalid(&conn->ccmsg, conn->ccmsg.result);
+ goto cleanup;
+ }
+
+ request = NULL;
+
+ 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);
+ secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
+ if (secret.rstart == NULL)
+ goto cleanup;
+ memmove(secret.rstart, key->secret.base, key->secret.length);
+ secret.rend = secret.rstart + key->secret.length;
+ algorithm = key->algorithm;
+ result = isccc_cc_fromwire(&ccregion, &request,
+ algorithm, &secret);
+ if (result == ISC_R_SUCCESS)
+ break;
+ isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
+ if (result != ISCCC_R_BADAUTH) {
+ log_invalid(&conn->ccmsg, result);
+ goto cleanup;
+ }
+ }
+
+ if (key == NULL) {
+ log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
+ goto cleanup;
+ }
+
+ /* We shouldn't be getting a reply. */
+ if (isccc_cc_isreply(request)) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+
+ isc_stdtime_get(&now);
+
+ /*
+ * Limit exposure to replay attacks.
+ */
+ _ctrl = isccc_alist_lookup(request, "_ctrl");
+ if (!isccc_alist_alistp(_ctrl)) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+
+ if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
+ if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
+ log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
+ goto cleanup_request;
+ }
+ } else {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+
+ /*
+ * Expire messages that are too old.
+ */
+ if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
+ now > exp) {
+ log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
+ goto cleanup_request;
+ }
+
+ /*
+ * Duplicate suppression (required for UDP).
+ */
+ isccc_cc_cleansymtab(listener->controls->symtab, now);
+ result = isccc_cc_checkdup(listener->controls->symtab, request, now);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_EXISTS)
+ result = ISCCC_R_DUPLICATE;
+ log_invalid(&conn->ccmsg, result);
+ goto cleanup_request;
+ }
+
+ if (conn->nonce != 0 &&
+ (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
+ conn->nonce != nonce)) {
+ log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
+ goto cleanup_request;
+ }
+
+ result = isc_buffer_allocate(listener->mctx, &text, 2 * 2048);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_request;
+
+ /*
+ * Establish nonce.
+ */
+ if (conn->nonce == 0) {
+ while (conn->nonce == 0)
+ isc_random_get(&conn->nonce);
+ eresult = ISC_R_SUCCESS;
+ } else
+ eresult = ns_control_docommand(request, listener->readonly, &text);
+
+ result = isccc_cc_createresponse(request, now, now + 60, &response);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_request;
+
+ data = isccc_alist_lookup(response, "_data");
+ if (data != NULL) {
+ if (isccc_cc_defineuint32(data, "result", eresult) == NULL)
+ goto cleanup_response;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ if (data != NULL) {
+ const char *estr = isc_result_totext(eresult);
+ if (isccc_cc_definestring(data, "err", estr) == NULL)
+ goto cleanup_response;
+ }
+ }
+
+ if (isc_buffer_usedlength(text) > 0) {
+ if (data != NULL) {
+ char *str = (char *)isc_buffer_base(text);
+ if (isccc_cc_definestring(data, "text", str) == NULL)
+ goto cleanup_response;
+ }
+ }
+
+ _ctrl = isccc_alist_lookup(response, "_ctrl");
+ if (_ctrl == NULL ||
+ isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
+ goto cleanup_response;
+
+ if (conn->buffer == NULL) {
+ result = isc_buffer_allocate(listener->mctx,
+ &conn->buffer, 2 * 2048);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_response;
+ }
+
+ isc_buffer_clear(conn->buffer);
+ /* Skip the length field (4 bytes) */
+ isc_buffer_add(conn->buffer, 4);
+
+ result = isccc_cc_towire(response, &conn->buffer, algorithm, &secret);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_response;
+
+ 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;
+
+ result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_response;
+ conn->sending = true;
+
+ isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
+ isccc_sexpr_free(&request);
+ isccc_sexpr_free(&response);
+ isc_buffer_free(&text);
+ return;
+
+ cleanup_response:
+ isccc_sexpr_free(&response);
+
+ cleanup_request:
+ isccc_sexpr_free(&request);
+ isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
+ if (text != NULL)
+ isc_buffer_free(&text);
+
+ cleanup:
+ isc_socket_detach(&conn->sock);
+ isccc_ccmsg_invalidate(&conn->ccmsg);
+ conn->ccmsg_valid = false;
+ maybe_free_connection(conn);
+ maybe_free_listener(listener);
+}
+
+static void
+control_timeout(isc_task_t *task, isc_event_t *event) {
+ controlconnection_t *conn = event->ev_arg;
+
+ UNUSED(task);
+
+ isc_timer_detach(&conn->timer);
+ maybe_free_connection(conn);
+
+ isc_event_free(&event);
+}
+
+static isc_result_t
+newconnection(controllistener_t *listener, isc_socket_t *sock) {
+ controlconnection_t *conn;
+ isc_interval_t interval;
+ isc_result_t result;
+
+ conn = isc_mem_get(listener->mctx, sizeof(*conn));
+ if (conn == NULL)
+ return (ISC_R_NOMEMORY);
+
+ conn->sock = sock;
+ isccc_ccmsg_init(listener->mctx, sock, &conn->ccmsg);
+
+ /* Set a 32 KiB upper limit on incoming message. */
+ isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768);
+
+ conn->ccmsg_valid = true;
+ conn->sending = false;
+ conn->buffer = NULL;
+ conn->timer = NULL;
+ isc_interval_set(&interval, 60, 0);
+ result = isc_timer_create(ns_g_timermgr, isc_timertype_once,
+ NULL, &interval, listener->task,
+ control_timeout, conn, &conn->timer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ conn->listener = listener;
+ conn->nonce = 0;
+ ISC_LINK_INIT(conn, link);
+
+ result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
+ control_recvmessage, conn);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ISC_LIST_APPEND(listener->connections, conn, link);
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (conn->buffer != NULL)
+ isc_buffer_free(&conn->buffer);
+ isccc_ccmsg_invalidate(&conn->ccmsg);
+ if (conn->timer != NULL)
+ isc_timer_detach(&conn->timer);
+ isc_mem_put(listener->mctx, conn, sizeof(*conn));
+#ifdef ENABLE_AFL
+ if (ns_g_fuzz_type == ns_fuzz_rndc) {
+ named_fuzz_notify();
+ }
+#endif
+ return (result);
+}
+
+static void
+control_newconn(isc_task_t *task, isc_event_t *event) {
+ isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
+ controllistener_t *listener = event->ev_arg;
+ isc_socket_t *sock;
+ isc_sockaddr_t peeraddr;
+ isc_result_t result;
+
+ UNUSED(task);
+
+ listener->listening = false;
+
+ if (nevent->result != ISC_R_SUCCESS) {
+ if (nevent->result == ISC_R_CANCELED) {
+ shutdown_listener(listener);
+ goto cleanup;
+ }
+ goto restart;
+ }
+
+ sock = nevent->newsocket;
+ isc_socket_setname(sock, "control", NULL);
+ (void)isc_socket_getpeername(sock, &peeraddr);
+ if (listener->type == isc_sockettype_tcp &&
+ !address_ok(&peeraddr, listener->acl)) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "rejected command channel message from %s",
+ socktext);
+ isc_socket_detach(&sock);
+ goto restart;
+ }
+
+ result = newconnection(listener, sock);
+ if (result != ISC_R_SUCCESS) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "dropped command channel from %s: %s",
+ socktext, isc_result_totext(result));
+ isc_socket_detach(&sock);
+ goto restart;
+ }
+
+ restart:
+ control_next(listener);
+ cleanup:
+ isc_event_free(&event);
+}
+
+static void
+controls_shutdown(ns_controls_t *controls) {
+ controllistener_t *listener;
+ controllistener_t *next;
+
+ 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
+ns_controls_shutdown(ns_controls_t *controls) {
+ controls_shutdown(controls);
+ 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;
+ const char *str;
+ const cfg_obj_t *obj;
+
+ 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 isc_result_t
+controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx,
+ controlkeylist_t *keyids)
+{
+ const cfg_listelt_t *element;
+ char *newstr = NULL;
+ const char *str;
+ const cfg_obj_t *obj;
+ controlkey_t *key;
+
+ 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);
+ if (newstr == NULL)
+ goto cleanup;
+ key = isc_mem_get(mctx, sizeof(*key));
+ if (key == NULL)
+ goto cleanup;
+ 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;
+ }
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (newstr != NULL)
+ isc_mem_free(mctx, newstr);
+ free_controlkeylist(keyids, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+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, *next;
+ const cfg_obj_t *keydef;
+ 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, ns_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);
+
+ if (ns_config_getkeyalgorithm2(algstr, NULL,
+ &algtype, NULL) != ISC_R_SUCCESS)
+ {
+ cfg_obj_log(control, ns_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, ns_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);
+ if (keyid->secret.base == NULL) {
+ cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't register key '%s': "
+ "out of memory", keyid->keyname);
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ break;
+ }
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_INFO,
+ "configuring command channel from '%s'",
+ ns_g_keyfile);
+ if (! isc_file_exists(ns_g_keyfile))
+ return (ISC_R_FILENOTFOUND);
+
+ CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx));
+ CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config));
+ CHECK(cfg_map_get(config, "key", &key));
+
+ keyid = isc_mem_get(mctx, sizeof(*keyid));
+ if (keyid == NULL)
+ CHECK(ISC_R_NOMEMORY);
+ 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, ns_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);
+
+ if (ns_config_getkeyalgorithm2(algstr, NULL,
+ &algtype, NULL) != ISC_R_SUCCESS) {
+ cfg_obj_log(key, ns_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, ns_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);
+ if (keyid->secret.base == NULL) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't register key '%s': "
+ "out of memory", keyid->keyname);
+ CHECK(ISC_R_NOMEMORY);
+ }
+ 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(ns_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_sockettype_t type)
+{
+ controllistener_t *listener;
+ const cfg_obj_t *allow;
+ 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);
+ result = controlkeylist_fromcfg(control_keylist,
+ listener->mctx, &keys);
+ if (result == ISC_R_SUCCESS) {
+ 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, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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_sockettype_tcp) {
+ allow = cfg_tuple_get(control, "allow");
+ result = cfg_acl_fromconfig(allow, config, ns_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;
+
+ 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, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+
+ if (result == ISC_R_SUCCESS && type == isc_sockettype_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, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't update ownership/permission for "
+ "command channel %s", socktext);
+ }
+
+ *listenerp = listener;
+}
+
+static void
+add_listener(ns_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_sockettype_t type)
+{
+ isc_mem_t *mctx = cp->server->mctx;
+ controllistener_t *listener;
+ const cfg_obj_t *allow;
+ 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;
+
+ listener = isc_mem_get(mctx, sizeof(*listener));
+ if (listener == NULL)
+ result = ISC_R_NOMEMORY;
+
+ if (result == ISC_R_SUCCESS) {
+ listener->mctx = NULL;
+ isc_mem_attach(mctx, &listener->mctx);
+ listener->controls = cp;
+ listener->task = cp->server->task;
+ listener->address = *addr;
+ listener->sock = NULL;
+ listener->listening = false;
+ listener->exiting = false;
+ listener->acl = NULL;
+ listener->type = type;
+ listener->perm = 0;
+ listener->owner = 0;
+ listener->group = 0;
+ listener->readonly = false;
+ ISC_LINK_INIT(listener, link);
+ ISC_LIST_INIT(listener->keys);
+ ISC_LIST_INIT(listener->connections);
+
+ /*
+ * Make the acl.
+ */
+ if (control != NULL && type == isc_sockettype_tcp) {
+ allow = cfg_tuple_get(control, "allow");
+ result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
+ aclconfctx, mctx, 0,
+ &new_acl);
+ } else {
+ result = dns_acl_any(mctx, &new_acl);
+ }
+ }
+
+ if ((result == ISC_R_SUCCESS) && (control != NULL)) {
+ const cfg_obj_t *readonly;
+
+ 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_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) {
+ result = controlkeylist_fromcfg(control_keylist,
+ listener->mctx,
+ &listener->keys);
+ if (result == ISC_R_SUCCESS)
+ 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, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ int pf = isc_sockaddr_pf(&listener->address);
+ if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
+#endif
+ (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+ result = ISC_R_FAMILYNOSUPPORT;
+ }
+
+ if (result == ISC_R_SUCCESS && type == isc_sockettype_unix)
+ isc_socket_cleanunix(&listener->address, false);
+
+ if (result == ISC_R_SUCCESS)
+ result = isc_socket_create(ns_g_socketmgr,
+ isc_sockaddr_pf(&listener->address),
+ type, &listener->sock);
+ if (result == ISC_R_SUCCESS)
+ isc_socket_setname(listener->sock, "control", NULL);
+
+#ifndef ISC_ALLOW_MAPPED
+ if (result == ISC_R_SUCCESS)
+ isc_socket_ipv6only(listener->sock, true);
+#endif
+
+ if (result == ISC_R_SUCCESS)
+ result = isc_socket_bind(listener->sock, &listener->address,
+ ISC_SOCKET_REUSEADDRESS);
+
+ if (result == ISC_R_SUCCESS && type == isc_sockettype_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);
+ }
+ if (result == ISC_R_SUCCESS)
+ result = control_listen(listener);
+
+ if (result == ISC_R_SUCCESS)
+ result = control_accept(listener);
+
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "command channel listening on %s", socktext);
+ *listenerp = listener;
+
+ } else {
+ if (listener != NULL) {
+ listener->exiting = true;
+ free_listener(listener);
+ }
+
+ if (control != NULL)
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't add command channel %s: %s",
+ socktext, isc_result_totext(result));
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx)
+{
+ controllistener_t *listener;
+ 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;
+ 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;
+ const cfg_obj_t *obj;
+ 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,
+ NS_CONTROL_PORT);
+
+ isc_sockaddr_format(&addr, socktext,
+ sizeof(socktext));
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "processing control channel %s",
+ socktext);
+
+ update_listener(cp, &listener, control, config,
+ &addr, aclconfctx, socktext,
+ isc_sockettype_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_sockettype_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;
+ const cfg_obj_t *unixcontrols = NULL;
+
+ controls = cfg_listelt_value(element);
+ (void)cfg_map_get(controls, "unix", &unixcontrols);
+ if (unixcontrols == NULL)
+ continue;
+
+ for (element2 = cfg_list_first(unixcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ const cfg_obj_t *control;
+ const cfg_obj_t *path;
+ 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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "control channel '%s': %s",
+ cfg_obj_asstring(path),
+ isc_result_totext(result));
+ continue;
+ }
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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_sockettype_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_sockettype_unix);
+
+ if (listener != NULL)
+ ISC_LIST_APPEND(new_listeners,
+ listener, link);
+ }
+ }
+ } 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, NS_CONTROL_PORT);
+
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+
+ update_listener(cp, &listener, NULL, NULL,
+ &addr, NULL, socktext,
+ isc_sockettype_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_sockettype_tcp);
+
+ if (listener != NULL)
+ ISC_LIST_APPEND(new_listeners,
+ listener, link);
+ }
+ }
+
+ /*
+ * ns_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
+ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp) {
+ isc_mem_t *mctx = server->mctx;
+ isc_result_t result;
+ ns_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
+
+ if (controls == NULL)
+ return (ISC_R_NOMEMORY);
+ controls->server = server;
+ ISC_LIST_INIT(controls->listeners);
+ controls->shuttingdown = false;
+ controls->symtab = NULL;
+ result = isccc_cc_createsymtab(&controls->symtab);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(server->mctx, controls, sizeof(*controls));
+ return (result);
+ }
+ *ctrlsp = controls;
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_controls_destroy(ns_controls_t **ctrlsp) {
+ ns_controls_t *controls = *ctrlsp;
+
+ REQUIRE(ISC_LIST_EMPTY(controls->listeners));
+
+ isccc_symtab_destroy(&controls->symtab);
+ isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
+ *ctrlsp = NULL;
+}
diff --git a/bin/named/convertxsl.pl b/bin/named/convertxsl.pl
new file mode 100755
index 0000000..8f78be3
--- /dev/null
+++ b/bin/named/convertxsl.pl
@@ -0,0 +1,51 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+my $rev = '$Id: convertxsl.pl,v 1.14 2008/07/17 23:43:26 jinmei Exp $';
+$rev =~ s/\$//g;
+$rev =~ s/,v//g;
+$rev =~ s/Id: //;
+
+my $xsl = "unknown";
+my $lines = '';
+
+while (<>) {
+ chomp;
+ # pickout the id for comment.
+ $xsl = $_ if (/<!-- .Id:.* -->/);
+ # convert Id string to a form not recognisable by cvs.
+ $_ =~ s/<!-- .Id:(.*). -->/<!-- \\045Id: $1\\045 -->/;
+ s/[\ \t]+/ /g;
+ s/\>\ \</\>\</g;
+ s/\"/\\\"/g;
+ s/^/\t\"/;
+ s/[\ \t]+$//g;
+ s/$/\\n\"/;
+ if ($lines eq "") {
+ $lines .= $_;
+ } else {
+ $lines .= "\n" . $_;
+ }
+}
+
+$xsl =~ s/\$//g;
+$xsl =~ s/<!-- Id: //;
+$xsl =~ s/ -->.*//;
+$xsl =~ s/,v//;
+
+print "/*\n * Generated by $rev \n * From $xsl\n */\n";
+print 'static char xslmsg[] =',"\n";
+print $lines;
+
+print ';', "\n";
diff --git a/bin/named/fuzz.c b/bin/named/fuzz.c
new file mode 100644
index 0000000..92f3f8b
--- /dev/null
+++ b/bin/named/fuzz.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include "config.h"
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <named/fuzz.h>
+
+#ifdef ENABLE_AFL
+#include <named/globals.h>
+#include <named/server.h>
+#include <sys/errno.h>
+
+#include <isc/app.h>
+#include <isc/condition.h>
+#include <isc/mutex.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <named/log.h>
+#include <dns/log.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#ifndef __AFL_LOOP
+#error To use American Fuzzy Lop you have to set CC to afl-clang-fast!!!
+#endif
+
+/*
+ * 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;
+
+
+static void *
+fuzz_main_client(void *arg) {
+ char *host;
+ char *port;
+ struct sockaddr_in servaddr;
+ int sockfd;
+ int loop;
+ 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(ns_g_fuzz_named_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. */
+ while (!ns_g_run_done) {
+ usleep(10000);
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ RUNTIME_CHECK(sockfd != -1);
+
+ buf = malloc(65536);
+ RUNTIME_CHECK(buf != NULL);
+
+ loop = 100000;
+ while (loop--) {
+ ssize_t length;
+
+ length = read(0, buf, 65536);
+ if (length <= 0) {
+ usleep(1000000);
+ continue;
+ }
+
+ if (length > 4096) {
+ if (getenv("AFL_CMIN")) {
+ ns_server_flushonshutdown(ns_g_server,
+ false);
+ isc_app_shutdown();
+ return (NULL);
+ }
+ raise(SIGSTOP);
+ continue;
+ }
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == ISC_R_SUCCESS);
+
+ ready = false;
+
+ ssize_t sent;
+
+ sent = sendto(sockfd, buf, length, 0,
+ (struct sockaddr *) &servaddr, sizeof(servaddr));
+ RUNTIME_CHECK(sent == length);
+
+ /* unclog */
+ recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL);
+
+ while (!ready)
+ pthread_cond_wait(&cond, &mutex);
+
+ RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == ISC_R_SUCCESS);
+ }
+
+ free(buf);
+ close(sockfd);
+
+ ns_server_flushonshutdown(ns_g_server, false);
+ isc_app_shutdown();
+
+ return (NULL);
+}
+
+static void *
+fuzz_main_resolver(void *arg) {
+ char *shost, *sport, *rhost, *rport;
+ /* Query for A? aaaaaaaaaa.example. */
+ char respacket[] =
+ "\0\0\1 \0\1\0\0\0\0\0\0\naaaaaaaaaa\7example\0\0\1\0\1";
+ struct sockaddr_in servaddr, recaddr, recvaddr;
+ int sockfd;
+ int listenfd;
+ int loop;
+ char *buf, *rbuf;
+
+ UNUSED(arg);
+
+ /*
+ * Parse named -A argument in the "laddress:sport:raddress:rport"
+ * syntax. Due to the syntax used, this only supports IPv4 addresses.
+ */
+
+ shost = strdup(ns_g_fuzz_named_addr);
+ RUNTIME_CHECK(shost != NULL);
+ 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++;
+
+ 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(shost);
+
+ /* Wait for named to start */
+ while (!ns_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);
+
+ loop = 100000;
+ while (loop--) {
+ ssize_t length;
+ memset(buf, 0, 16);
+ length = read(0, buf, 65536);
+ if (length <= 0) {
+ usleep(1000000);
+ continue;
+ }
+
+ if (length > 4096) {
+ if (getenv("AFL_CMIN")) {
+ ns_server_flushonshutdown(ns_g_server,
+ false);
+ isc_app_shutdown();
+ return (NULL);
+ }
+ raise(SIGSTOP);
+ continue;
+ }
+
+ if (length < 16) {
+ length = 16;
+ }
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == ISC_R_SUCCESS);
+
+ ready = false;
+
+ ssize_t sent;
+ /* Randomize query ID. */
+ int id = random();
+ respacket[0] = id >> 8;
+ respacket[1] = id & 0xff;
+
+ /* flush */
+ socklen_t socklen = sizeof(recvaddr);
+ sent = recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT,
+ (struct sockaddr *) &recvaddr, &socklen);
+
+ sent = sendto(sockfd, respacket, sizeof(respacket), 0,
+ (struct sockaddr *) &servaddr, sizeof(servaddr));
+ RUNTIME_CHECK(sent == sizeof(respacket));
+
+ 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 processed. */
+ buf[0] = rbuf[0];
+ buf[1] = rbuf[1];
+ buf[2] |= 0x80;
+
+ 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, we're done. */
+ recvfrom(sockfd, buf, 65536, 0, NULL, NULL);
+ break;
+ }
+
+ /*
+ * We've got additional question (eg. cname chain)
+ * We are bouncing it - setting QR flag and NOERROR
+ * rcode and sending it back.
+ */
+
+ length = recvfrom(listenfd, buf, 65536, 0,
+ (struct sockaddr *) &recvaddr, &socklen);
+ 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);
+ ns_server_flushonshutdown(ns_g_server, false);
+ isc_app_shutdown();
+
+ /*
+ * It's here just for the signature, that's how AFL detects if it's
+ * a 'persistent mode' binary.
+ */
+ __AFL_LOOP(0);
+
+ return (NULL);
+}
+
+static void *
+fuzz_main_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(ns_g_fuzz_named_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 */
+ while (!ns_g_run_done) {
+ usleep(10000);
+ }
+
+ buf = malloc(65539);
+ RUNTIME_CHECK(buf != NULL);
+
+ loop = 100000;
+ while (loop--) {
+ ssize_t length;
+
+ if (ns_g_fuzz_type == ns_fuzz_tcpclient) {
+ /*
+ * To fuzz TCP client we have to put length at
+ * the start of packet.
+ */
+ length = read(0, buf+2, 65535);
+ buf[0] = length >> 8;
+ buf[1] = length & 0xff;
+ length += 2;
+ } else {
+ length = read(0, buf, 65535);
+ }
+ if (length <= 0) {
+ usleep(1000000);
+ continue;
+ }
+ if (ns_g_fuzz_type == ns_fuzz_http) {
+ /*
+ * This guarantees that the request will be processed.
+ */
+ buf[length++]='\r';
+ buf[length++]='\n';
+ buf[length++]='\r';
+ buf[length++]='\n';
+ }
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == ISC_R_SUCCESS);
+
+ ready = false;
+
+ ssize_t sent;
+ int yes = 1;
+ int r;
+ 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));
+ } while (r != 0);
+
+ sent = write(sockfd, buf, length);
+ RUNTIME_CHECK(sent == length);
+ close(sockfd);
+
+ /* unclog */
+ recvfrom(sockfd, buf, 65537, MSG_DONTWAIT, NULL, NULL);
+
+ while (!ready)
+ pthread_cond_wait(&cond, &mutex);
+
+ RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == ISC_R_SUCCESS);
+ }
+
+ free(buf);
+ close(sockfd);
+ ns_server_flushonshutdown(ns_g_server, false);
+ isc_app_shutdown();
+
+ return (NULL);
+}
+
+#endif /* ENABLE_AFL */
+
+void
+named_fuzz_notify(void) {
+#ifdef ENABLE_AFL
+ if (getenv("AFL_CMIN")) {
+ ns_server_flushonshutdown(ns_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 (ns_g_fuzz_type) {
+ case ns_fuzz_client:
+ fn = fuzz_main_client;
+ break;
+
+ case ns_fuzz_http:
+ case ns_fuzz_tcpclient:
+ case ns_fuzz_rndc:
+ fn = fuzz_main_tcp;
+ break;
+ case ns_fuzz_resolver:
+ fn = fuzz_main_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..5bc504e
--- /dev/null
+++ b/bin/named/geoip.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <named/log.h>
+#include <named/geoip.h>
+
+#include <dns/geoip.h>
+
+#ifdef HAVE_GEOIP
+static dns_geoip_databases_t geoip_table = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static void
+init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback,
+ GeoIPOptions method, const char *name)
+{
+ char *info;
+ GeoIP *db;
+
+ REQUIRE(dbp != NULL);
+
+ db = *dbp;
+
+ if (db != NULL) {
+ GeoIP_delete(db);
+ db = *dbp = NULL;
+ }
+
+ if (! GeoIP_db_avail(edition)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "GeoIP %s (type %d) DB not available", name, edition);
+ goto fail;
+ }
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "initializing GeoIP %s (type %d) DB", name, edition);
+
+ db = GeoIP_open_type(edition, method);
+ if (db == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed to initialize GeoIP %s (type %d) DB%s",
+ name, edition, fallback == 0
+ ? "geoip matches using this database will fail" : "");
+ goto fail;
+ }
+
+ info = GeoIP_database_info(db);
+ if (info != NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s", info);
+ free(info);
+ }
+
+ *dbp = db;
+ return;
+ fail:
+ if (fallback != 0)
+ init_geoip_db(dbp, fallback, 0, method, name);
+
+}
+#endif /* HAVE_GEOIP */
+
+void
+ns_geoip_init(void) {
+#ifndef HAVE_GEOIP
+ return;
+#else
+ GeoIP_cleanup();
+ if (ns_g_geoip == NULL)
+ ns_g_geoip = &geoip_table;
+#endif
+}
+
+void
+ns_geoip_load(char *dir) {
+#ifndef HAVE_GEOIP
+
+ UNUSED(dir);
+
+ return;
+#else
+ GeoIPOptions method;
+
+#ifdef _WIN32
+ method = GEOIP_STANDARD;
+#else
+ method = GEOIP_MMAP_CACHE;
+#endif
+
+ ns_geoip_init();
+ if (dir != NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using \"%s\" as GeoIP directory", dir);
+ GeoIP_setup_custom_directory(dir);
+ }
+
+ init_geoip_db(&ns_g_geoip->country_v4, GEOIP_COUNTRY_EDITION, 0,
+ method, "Country (IPv4)");
+#ifdef HAVE_GEOIP_V6
+ init_geoip_db(&ns_g_geoip->country_v6, GEOIP_COUNTRY_EDITION_V6, 0,
+ method, "Country (IPv6)");
+#endif
+
+ init_geoip_db(&ns_g_geoip->city_v4, GEOIP_CITY_EDITION_REV1,
+ GEOIP_CITY_EDITION_REV0, method, "City (IPv4)");
+#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6)
+ init_geoip_db(&ns_g_geoip->city_v6, GEOIP_CITY_EDITION_REV1_V6,
+ GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)");
+#endif
+
+ init_geoip_db(&ns_g_geoip->region, GEOIP_REGION_EDITION_REV1,
+ GEOIP_REGION_EDITION_REV0, method, "Region");
+
+ init_geoip_db(&ns_g_geoip->isp, GEOIP_ISP_EDITION, 0,
+ method, "ISP");
+ init_geoip_db(&ns_g_geoip->org, GEOIP_ORG_EDITION, 0,
+ method, "Org");
+ init_geoip_db(&ns_g_geoip->as, GEOIP_ASNUM_EDITION, 0,
+ method, "AS");
+ init_geoip_db(&ns_g_geoip->domain, GEOIP_DOMAIN_EDITION, 0,
+ method, "Domain");
+ init_geoip_db(&ns_g_geoip->netspeed, GEOIP_NETSPEED_EDITION, 0,
+ method, "NetSpeed");
+#endif /* HAVE_GEOIP */
+}
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..14a637b
--- /dev/null
+++ b/bin/named/include/dlz/dlz_dlopen_driver.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef DLZ_DLOPEN_DRIVER_H
+#define DLZ_DLOPEN_DRIVER_H
+
+isc_result_t
+dlz_dlopen_init(isc_mem_t *mctx);
+
+void
+dlz_dlopen_clear(void);
+#endif
diff --git a/bin/named/include/named/builtin.h b/bin/named/include/named/builtin.h
new file mode 100644
index 0000000..97ffdee
--- /dev/null
+++ b/bin/named/include/named/builtin.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: builtin.h,v 1.6 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_BUILTIN_H
+#define NAMED_BUILTIN_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+
+isc_result_t ns_builtin_init(void);
+
+void ns_builtin_deinit(void);
+
+#endif /* NAMED_BUILTIN_H */
diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h
new file mode 100644
index 0000000..b23a7b1
--- /dev/null
+++ b/bin/named/include/named/client.h
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: client.h,v 1.96 2012/01/31 23:47:31 tbox Exp $ */
+
+#ifndef NAMED_CLIENT_H
+#define NAMED_CLIENT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * This module defines two objects, ns_client_t and ns_clientmgr_t.
+ *
+ * An ns_client_t object handles incoming DNS requests from clients
+ * on a given network interface.
+ *
+ * Each ns_client_t object can handle only one TCP connection or UDP
+ * request at a time. Therefore, several ns_client_t objects are
+ * typically created to serve each network interface, e.g., one
+ * for handling TCP requests and a few (one per CPU) for handling
+ * UDP requests.
+ *
+ * Incoming requests are classified as queries, zone transfer
+ * requests, update requests, notify requests, etc, and handed off
+ * to the appropriate request handler. When the request has been
+ * fully handled (which can be much later), the ns_client_t must be
+ * notified of this by calling one of the following functions
+ * exactly once in the context of its task:
+ * \code
+ * ns_client_send() (sending a non-error response)
+ * ns_client_sendraw() (sending a raw response)
+ * ns_client_error() (sending an error response)
+ * ns_client_next() (sending no response)
+ *\endcode
+ * This will release any resources used by the request and
+ * and allow the ns_client_t to listen for the next request.
+ *
+ * A ns_clientmgr_t manages a number of ns_client_t objects.
+ * New ns_client_t objects are created by calling
+ * ns_clientmgr_createclients(). They are destroyed by
+ * destroying their manager.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/stdtime.h>
+#include <isc/quota.h>
+#include <isc/queue.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/tcpmsg.h>
+#include <dns/types.h>
+
+#include <named/types.h>
+#include <named/query.h>
+
+/***
+ *** Types
+ ***/
+
+/*% nameserver client structure */
+struct ns_client {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ ns_clientmgr_t * manager;
+ int state;
+ int newstate;
+ int naccepts;
+ int nreads;
+ int nsends;
+ int nrecvs;
+ int nupdates;
+ int nctls;
+ int references;
+ bool needshutdown; /*
+ * Used by clienttest to get
+ * the client to go from
+ * inactive to free state
+ * by shutting down the
+ * client's task.
+ */
+ unsigned int attributes;
+ isc_task_t * task;
+ dns_view_t * view;
+ dns_dispatch_t * dispatch;
+ isc_socket_t * udpsocket;
+ isc_socket_t * tcplistener;
+ isc_socket_t * tcpsocket;
+ unsigned char * tcpbuf;
+ dns_tcpmsg_t tcpmsg;
+ bool tcpmsg_valid;
+ isc_timer_t * timer;
+ isc_timer_t * delaytimer;
+ bool timerset;
+ dns_message_t * message;
+ isc_socketevent_t * sendevent;
+ isc_socketevent_t * recvevent;
+ unsigned char * recvbuf;
+ dns_rdataset_t * opt;
+ uint16_t udpsize;
+ uint16_t extflags;
+ int16_t ednsversion; /* -1 noedns */
+ void (*next)(ns_client_t *);
+ void (*shutdown)(void *arg, isc_result_t result);
+ void *shutdown_arg;
+ ns_query_t query;
+ isc_time_t requesttime;
+ isc_stdtime_t now;
+ isc_time_t tnow;
+ dns_name_t signername; /*%< [T]SIG key name */
+ dns_name_t * signer; /*%< NULL if not valid sig */
+ bool mortal; /*%< Die after handling request */
+ bool pipelined; /*%< TCP queries not in sequence */
+ isc_quota_t *tcpquota;
+ isc_quota_t *recursionquota;
+ ns_interface_t *interface;
+
+ isc_sockaddr_t peeraddr;
+ bool peeraddr_valid;
+ isc_netaddr_t destaddr;
+ isc_sockaddr_t destsockaddr;
+
+ isc_netaddr_t ecs_addr; /*%< EDNS client subnet */
+ uint8_t ecs_addrlen;
+ uint8_t ecs_scope;
+
+ struct in6_pktinfo pktinfo;
+ isc_dscp_t dscp;
+ isc_event_t ctlevent;
+#ifdef ALLOW_FILTER_AAAA
+ dns_aaaa_t filter_aaaa;
+#endif
+ /*%
+ * Information about recent FORMERR response(s), for
+ * FORMERR loop avoidance. This is separate for each
+ * client object rather than global only to avoid
+ * the need for locking.
+ */
+ struct {
+ isc_sockaddr_t addr;
+ isc_stdtime_t time;
+ dns_messageid_t id;
+ } formerrcache;
+
+ ISC_LINK(ns_client_t) link;
+ ISC_LINK(ns_client_t) rlink;
+ ISC_QLINK(ns_client_t) ilink;
+ unsigned char cookie[8];
+ uint32_t expire;
+ unsigned char *keytag;
+ uint16_t keytag_len;
+};
+
+typedef ISC_QUEUE(ns_client_t) client_queue_t;
+typedef ISC_LIST(ns_client_t) client_list_t;
+
+#define NS_CLIENT_MAGIC ISC_MAGIC('N','S','C','c')
+#define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC)
+
+#define NS_CLIENTATTR_TCP 0x0001
+#define NS_CLIENTATTR_RA 0x0002 /*%< Client gets recursive service */
+#define NS_CLIENTATTR_PKTINFO 0x0004 /*%< pktinfo is valid */
+#define NS_CLIENTATTR_MULTICAST 0x0008 /*%< recv'd from multicast */
+#define NS_CLIENTATTR_WANTDNSSEC 0x0010 /*%< include dnssec records */
+#define NS_CLIENTATTR_WANTNSID 0x0020 /*%< include nameserver ID */
+#ifdef ALLOW_FILTER_AAAA
+#define NS_CLIENTATTR_FILTER_AAAA 0x0040 /*%< suppress AAAAs */
+#define NS_CLIENTATTR_FILTER_AAAA_RC 0x0080 /*%< recursing for A against AAAA */
+#endif
+#define NS_CLIENTATTR_WANTAD 0x0100 /*%< want AD in response if possible */
+#define NS_CLIENTATTR_WANTCOOKIE 0x0200 /*%< return a COOKIE */
+#define NS_CLIENTATTR_HAVECOOKIE 0x0400 /*%< has a valid COOKIE */
+#define NS_CLIENTATTR_WANTEXPIRE 0x0800 /*%< return seconds to expire */
+#define NS_CLIENTATTR_HAVEEXPIRE 0x1000 /*%< return seconds to expire */
+#define NS_CLIENTATTR_WANTOPT 0x2000 /*%< add opt to reply */
+#define NS_CLIENTATTR_HAVEECS 0x4000 /*%< received an ECS option */
+
+#define NS_CLIENTATTR_NOSETFC 0x8000 /*%< don't set servfail cache */
+
+/*
+ * Flag to use with the SERVFAIL cache to indicate
+ * that a query had the CD bit set.
+ */
+#define NS_FAILCACHE_CD 0x01
+
+
+
+extern unsigned int ns_client_requests;
+
+/***
+ *** Functions
+ ***/
+
+/*%
+ * Note! These ns_client_ routines MUST be called ONLY from the client's
+ * task in order to ensure synchronization.
+ */
+
+void
+ns_client_send(ns_client_t *client);
+/*%
+ * Finish processing the current client request and
+ * send client->message as a response.
+ * \brief
+ * Note! These ns_client_ routines MUST be called ONLY from the client's
+ * task in order to ensure synchronization.
+ */
+
+void
+ns_client_sendraw(ns_client_t *client, dns_message_t *msg);
+/*%
+ * Finish processing the current client request and
+ * send msg as a response using client->message->id for the id.
+ */
+
+void
+ns_client_error(ns_client_t *client, isc_result_t result);
+/*%
+ * Finish processing the current client request and return
+ * an error response to the client. The error response
+ * will have an RCODE determined by 'result'.
+ */
+
+void
+ns_client_next(ns_client_t *client, isc_result_t result);
+/*%
+ * Finish processing the current client request,
+ * return no response to the client.
+ */
+
+bool
+ns_client_shuttingdown(ns_client_t *client);
+/*%
+ * Return true iff the client is currently shutting down.
+ */
+
+void
+ns_client_attach(ns_client_t *source, ns_client_t **target);
+/*%
+ * Attach '*targetp' to 'source'.
+ */
+
+void
+ns_client_detach(ns_client_t **clientp);
+/*%
+ * Detach '*clientp' from its client.
+ */
+
+isc_result_t
+ns_client_replace(ns_client_t *client);
+/*%
+ * Try to replace the current client with a new one, so that the
+ * current one can go off and do some lengthy work without
+ * leaving the dispatch/socket without service.
+ */
+
+void
+ns_client_settimeout(ns_client_t *client, unsigned int seconds);
+/*%
+ * Set a timer in the client to go off in the specified amount of time.
+ */
+
+isc_result_t
+ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, ns_clientmgr_t **managerp);
+/*%
+ * Create a client manager.
+ */
+
+void
+ns_clientmgr_destroy(ns_clientmgr_t **managerp);
+/*%
+ * Destroy a client manager and all ns_client_t objects
+ * managed by it.
+ */
+
+isc_result_t
+ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
+ ns_interface_t *ifp, bool tcp);
+/*%
+ * Create up to 'n' clients listening on interface 'ifp'.
+ * If 'tcp' is true, the clients will listen for TCP connections,
+ * otherwise for UDP requests.
+ */
+
+isc_sockaddr_t *
+ns_client_getsockaddr(ns_client_t *client);
+/*%
+ * Get the socket address of the client whose request is
+ * currently being processed.
+ */
+
+isc_sockaddr_t *
+ns_client_getdestaddr(ns_client_t *client);
+/*%<
+ * Get the destination address (server) for the request that is
+ * currently being processed.
+ */
+
+isc_result_t
+ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
+ dns_acl_t *acl, bool default_allow);
+
+/*%
+ * Convenience function for client request ACL checking.
+ *
+ * Check the current client request against 'acl'. If 'acl'
+ * is NULL, allow the request iff 'default_allow' is true.
+ * If netaddr is NULL, check the ACL against client->peeraddr;
+ * otherwise check it against netaddr.
+ *
+ * Notes:
+ *\li This is appropriate for checking allow-update,
+ * allow-query, allow-transfer, etc. It is not appropriate
+ * for checking the blackhole list because we treat positive
+ * matches as "allow" and negative matches as "deny"; in
+ * the case of the blackhole list this would be backwards.
+ *
+ * Requires:
+ *\li 'client' points to a valid client.
+ *\li 'netaddr' points to a valid address, or is NULL.
+ *\li 'acl' points to a valid ACL, or is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS if the request should be allowed
+ * \li DNS_R_REFUSED if the request should be denied
+ *\li No other return values are possible.
+ */
+
+isc_result_t
+ns_client_checkacl(ns_client_t *client,
+ isc_sockaddr_t *sockaddr,
+ const char *opname, dns_acl_t *acl,
+ bool default_allow,
+ int log_level);
+/*%
+ * Like ns_client_checkaclsilent, except the outcome of the check is
+ * logged at log level 'log_level' if denied, and at debug 3 if approved.
+ * Log messages will refer to the request as an 'opname' request.
+ *
+ * Requires:
+ *\li 'client' points to a valid client.
+ *\li 'sockaddr' points to a valid address, or is NULL.
+ *\li 'acl' points to a valid ACL, or is NULL.
+ *\li 'opname' points to a null-terminated string.
+ */
+
+void
+ns_client_log(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
+
+void
+ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, va_list ap) ISC_FORMAT_PRINTF(5, 0);
+
+void
+ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataclass_t rdclass, char *buf, size_t len);
+
+#define NS_CLIENT_ACLMSGSIZE(x) \
+ (DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + \
+ DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'"))
+
+void
+ns_client_recursing(ns_client_t *client);
+/*%
+ * Add client to end of th recursing list.
+ */
+
+void
+ns_client_killoldestquery(ns_client_t *client);
+/*%
+ * Kill the oldest recursive query (recursing list head).
+ */
+
+void
+ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager);
+/*%
+ * Dump the outstanding recursive queries to 'f'.
+ */
+
+void
+ns_client_qnamereplace(ns_client_t *client, dns_name_t *name);
+/*%
+ * Replace the qname.
+ */
+
+bool
+ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_rdataclass_t rdclass, void *arg);
+/*%
+ * Isself callback.
+ */
+
+isc_result_t
+ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp);
+
+isc_result_t
+ns_client_addopt(ns_client_t *client, dns_message_t *message,
+ dns_rdataset_t **opt);
+
+#endif /* NAMED_CLIENT_H */
diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h
new file mode 100644
index 0000000..965c2b0
--- /dev/null
+++ b/bin/named/include/named/config.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef NAMED_CONFIG_H
+#define NAMED_CONFIG_H 1
+
+/*! \file */
+
+#include <inttypes.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/types.h>
+#include <dns/zone.h>
+
+isc_result_t
+ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf);
+
+isc_result_t
+ns_config_get(cfg_obj_t const * const *maps, const char *name,
+ const cfg_obj_t **obj);
+
+isc_result_t
+ns_checknames_get(const cfg_obj_t **maps, const char *name,
+ const cfg_obj_t **obj);
+
+int
+ns_config_listcount(const cfg_obj_t *list);
+
+isc_result_t
+ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
+ dns_rdataclass_t *classp);
+
+isc_result_t
+ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+ dns_rdatatype_t *typep);
+
+dns_zonetype_t
+ns_config_getzonetype(const cfg_obj_t *zonetypeobj);
+
+isc_result_t
+ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
+ in_port_t defport, isc_mem_t *mctx,
+ isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
+ uint32_t *countp);
+
+void
+ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ isc_dscp_t **dscpsp, uint32_t count);
+
+isc_result_t
+ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
+ isc_mem_t *mctx, dns_ipkeylist_t *ipkl);
+
+isc_result_t
+ns_config_getport(const cfg_obj_t *config, in_port_t *portp);
+
+isc_result_t
+ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
+ uint16_t *digestbits);
+isc_result_t
+ns_config_getkeyalgorithm2(const char *str, dns_name_t **name,
+ unsigned int *typep, uint16_t *digestbits);
+
+isc_result_t
+ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp);
+
+#endif /* NAMED_CONFIG_H */
diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h
new file mode 100644
index 0000000..8705fdd
--- /dev/null
+++ b/bin/named/include/named/control.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: control.h,v 1.38 2012/01/31 23:47:31 tbox Exp $ */
+
+#ifndef NAMED_CONTROL_H
+#define NAMED_CONTROL_H 1
+
+/*! \file
+ * \brief
+ * The name server command channel.
+ */
+
+#include <stdbool.h>
+#include <isccc/types.h>
+
+#include <isccfg/aclconf.h>
+
+#include <named/types.h>
+
+#define NS_CONTROL_PORT 953
+
+#define NS_COMMAND_STOP "stop"
+#define NS_COMMAND_HALT "halt"
+#define NS_COMMAND_RELOAD "reload"
+#define NS_COMMAND_RECONFIG "reconfig"
+#define NS_COMMAND_REFRESH "refresh"
+#define NS_COMMAND_RETRANSFER "retransfer"
+#define NS_COMMAND_DUMPSTATS "stats"
+#define NS_COMMAND_QUERYLOG "querylog"
+#define NS_COMMAND_DUMPDB "dumpdb"
+#define NS_COMMAND_SECROOTS "secroots"
+#define NS_COMMAND_TRACE "trace"
+#define NS_COMMAND_NOTRACE "notrace"
+#define NS_COMMAND_FLUSH "flush"
+#define NS_COMMAND_FLUSHNAME "flushname"
+#define NS_COMMAND_FLUSHTREE "flushtree"
+#define NS_COMMAND_STATUS "status"
+#define NS_COMMAND_TSIGLIST "tsig-list"
+#define NS_COMMAND_TSIGDELETE "tsig-delete"
+#define NS_COMMAND_FREEZE "freeze"
+#define NS_COMMAND_UNFREEZE "unfreeze"
+#define NS_COMMAND_THAW "thaw"
+#define NS_COMMAND_TIMERPOKE "timerpoke"
+#define NS_COMMAND_RECURSING "recursing"
+#define NS_COMMAND_NULL "null"
+#define NS_COMMAND_NOTIFY "notify"
+#define NS_COMMAND_VALIDATION "validation"
+#define NS_COMMAND_SCAN "scan"
+#define NS_COMMAND_SIGN "sign"
+#define NS_COMMAND_LOADKEYS "loadkeys"
+#define NS_COMMAND_ADDZONE "addzone"
+#define NS_COMMAND_MODZONE "modzone"
+#define NS_COMMAND_DELZONE "delzone"
+#define NS_COMMAND_SHOWZONE "showzone"
+#define NS_COMMAND_SYNC "sync"
+#define NS_COMMAND_SIGNING "signing"
+#define NS_COMMAND_ZONESTATUS "zonestatus"
+#define NS_COMMAND_NTA "nta"
+#define NS_COMMAND_TESTGEN "testgen"
+#define NS_COMMAND_MKEYS "managed-keys"
+#define NS_COMMAND_DNSTAPREOPEN "dnstap-reopen"
+#define NS_COMMAND_DNSTAP "dnstap"
+
+isc_result_t
+ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
+/*%<
+ * Create an initial, empty set of command channels for 'server'.
+ */
+
+void
+ns_controls_destroy(ns_controls_t **ctrlsp);
+/*%<
+ * Destroy a set of command channels.
+ *
+ * Requires:
+ * Shutdown of the channels has completed.
+ */
+
+isc_result_t
+ns_controls_configure(ns_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
+ns_controls_shutdown(ns_controls_t *controls);
+/*%<
+ * Initiate shutdown of all the command channels in 'controls'.
+ */
+
+isc_result_t
+ns_control_docommand(isccc_sexpr_t *message, bool readonly,
+ isc_buffer_t **text);
+
+#endif /* NAMED_CONTROL_H */
diff --git a/bin/named/include/named/fuzz.h b/bin/named/include/named/fuzz.h
new file mode 100644
index 0000000..6e5eac5
--- /dev/null
+++ b/bin/named/include/named/fuzz.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_FUZZ_H
+#define NAMED_FUZZ_H
+
+void
+named_fuzz_notify(void);
+
+void
+named_fuzz_setup(void);
+
+typedef enum {
+ ns_fuzz_none,
+ ns_fuzz_client,
+ ns_fuzz_tcpclient,
+ ns_fuzz_resolver,
+ ns_fuzz_http,
+ ns_fuzz_rndc
+} ns_fuzz_t;
+
+#endif /* NAMED_FUZZ_H */
diff --git a/bin/named/include/named/geoip.h b/bin/named/include/named/geoip.h
new file mode 100644
index 0000000..04a5a39
--- /dev/null
+++ b/bin/named/include/named/geoip.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef _GEOIP_H
+#define _GEOIP_H
+
+#ifdef HAVE_GEOIP
+#include <GeoIP.h>
+#include <GeoIPCity.h>
+#endif /* HAVE_GEOIP */
+
+void ns_geoip_init(void);
+void ns_geoip_load(char *dir);
+
+#ifdef HAVE_GEOIP
+extern dns_geoip_databases_t *ns_g_geoip;
+#endif /* HAVE_GEOIP */
+#endif
diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h
new file mode 100644
index 0000000..494e005
--- /dev/null
+++ b/bin/named/include/named/globals.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_GLOBALS_H
+#define NAMED_GLOBALS_H 1
+
+/*! \file */
+
+#include <stdbool.h>
+#include <isc/rwlock.h>
+#include <isc/log.h>
+#include <isc/net.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+
+#include <dns/acl.h>
+#include <dns/zone.h>
+
+#include <dst/dst.h>
+
+#include <named/types.h>
+#include <named/fuzz.h>
+
+#undef EXTERN
+#undef INIT
+#ifdef NS_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else
+#define EXTERN extern
+#define INIT(v)
+#endif
+
+#ifndef NS_RUN_PID_DIR
+#define NS_RUN_PID_DIR 1
+#endif
+
+EXTERN isc_mem_t * ns_g_mctx INIT(NULL);
+EXTERN unsigned int ns_g_cpus INIT(0);
+EXTERN unsigned int ns_g_udpdisp INIT(0);
+EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL);
+EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL);
+EXTERN isc_entropy_t * ns_g_entropy INIT(NULL);
+EXTERN isc_entropy_t * ns_g_fallbackentropy INIT(NULL);
+EXTERN unsigned int ns_g_cpus_detected INIT(1);
+
+#ifdef ENABLE_AFL
+EXTERN bool ns_g_run_done INIT(false);
+#endif
+/*
+ * 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 * ns_g_timermgr INIT(NULL);
+EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL);
+EXTERN cfg_parser_t * ns_g_parser INIT(NULL);
+EXTERN cfg_parser_t * ns_g_addparser INIT(NULL);
+EXTERN const char * ns_g_version INIT(VERSION);
+EXTERN const char * ns_g_product INIT(PRODUCT);
+EXTERN const char * ns_g_description INIT(DESCRIPTION);
+EXTERN const char * ns_g_srcid INIT(SRCID);
+EXTERN const char * ns_g_configargs INIT(CONFIGARGS);
+EXTERN const char * ns_g_builder INIT(BUILDER);
+EXTERN in_port_t ns_g_port INIT(0);
+EXTERN isc_dscp_t ns_g_dscp INIT(-1);
+EXTERN in_port_t lwresd_g_listenport INIT(0);
+
+EXTERN ns_server_t * ns_g_server INIT(NULL);
+
+EXTERN bool ns_g_lwresdonly INIT(false);
+
+/*
+ * Logging.
+ */
+EXTERN isc_log_t * ns_g_lctx INIT(NULL);
+EXTERN isc_logcategory_t * ns_g_categories INIT(NULL);
+EXTERN isc_logmodule_t * ns_g_modules INIT(NULL);
+EXTERN unsigned int ns_g_debuglevel INIT(0);
+
+/*
+ * Current configuration information.
+ */
+EXTERN cfg_obj_t * ns_g_config INIT(NULL);
+EXTERN const cfg_obj_t * ns_g_defaults INIT(NULL);
+EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR
+ "/named.conf");
+EXTERN cfg_obj_t * ns_g_bindkeys INIT(NULL);
+EXTERN const char * ns_g_keyfile INIT(NS_SYSCONFDIR
+ "/rndc.key");
+
+EXTERN dns_tsigkey_t * ns_g_sessionkey INIT(NULL);
+EXTERN dns_name_t ns_g_sessionkeyname;
+
+EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR
+ "/lwresd.conf");
+EXTERN const char * lwresd_g_resolvconffile INIT("/etc"
+ "/resolv.conf");
+EXTERN bool ns_g_conffileset INIT(false);
+EXTERN bool lwresd_g_useresolvconf INIT(false);
+EXTERN uint16_t ns_g_udpsize INIT(4096);
+EXTERN cfg_aclconfctx_t * ns_g_aclconfctx INIT(NULL);
+
+/*
+ * Initial resource limits.
+ */
+EXTERN isc_resourcevalue_t ns_g_initstacksize INIT(0);
+EXTERN isc_resourcevalue_t ns_g_initdatasize INIT(0);
+EXTERN isc_resourcevalue_t ns_g_initcoresize INIT(0);
+EXTERN isc_resourcevalue_t ns_g_initopenfiles INIT(0);
+
+/*
+ * Misc.
+ */
+EXTERN bool ns_g_coreok INIT(true);
+EXTERN const char * ns_g_chrootdir INIT(NULL);
+EXTERN bool ns_g_foreground INIT(false);
+EXTERN bool ns_g_logstderr INIT(false);
+EXTERN bool ns_g_nosyslog INIT(false);
+EXTERN const char * ns_g_logfile INIT(NULL);
+
+EXTERN const char * ns_g_defaultsessionkeyfile
+ INIT(NS_LOCALSTATEDIR "/run/named/"
+ "session.key");
+EXTERN const char * ns_g_defaultlockfile INIT(NS_LOCALSTATEDIR
+ "/run/named/"
+ "named.lock");
+EXTERN bool ns_g_forcelock INIT(false);
+
+#if NS_RUN_PID_DIR
+EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/named/"
+ "named.pid");
+EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/lwresd/"
+ "lwresd.pid");
+#else
+EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/named.pid");
+EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/lwresd.pid");
+#endif
+
+#ifdef HAVE_DNSTAP
+EXTERN const char * ns_g_defaultdnstap
+ INIT(NS_LOCALSTATEDIR "/run/named/"
+ "dnstap.sock");
+#else
+EXTERN const char * ns_g_defaultdnstap INIT(NULL);
+#endif /* HAVE_DNSTAP */
+
+EXTERN const char * ns_g_username INIT(NULL);
+
+#if defined(USE_PKCS11)
+EXTERN const char * ns_g_engine INIT(PKCS11_ENGINE);
+#else
+EXTERN const char * ns_g_engine INIT(NULL);
+#endif
+
+EXTERN int ns_g_listen INIT(3);
+EXTERN isc_time_t ns_g_boottime;
+EXTERN isc_time_t ns_g_configtime;
+EXTERN bool ns_g_memstatistics INIT(false);
+EXTERN bool ns_g_clienttest INIT(false);
+EXTERN bool ns_g_dropedns INIT(false);
+EXTERN bool ns_g_noedns INIT(false);
+EXTERN bool ns_g_nosoa INIT(false);
+EXTERN bool ns_g_noaa INIT(false);
+EXTERN bool ns_g_keepstderr INIT(false);
+EXTERN unsigned int ns_g_delay INIT(0);
+EXTERN bool ns_g_nonearest INIT(false);
+EXTERN bool ns_g_notcp INIT(false);
+EXTERN bool ns_g_disable6 INIT(false);
+EXTERN bool ns_g_disable4 INIT(false);
+EXTERN unsigned int ns_g_tat_interval INIT(24*3600);
+EXTERN bool ns_g_fixedlocal INIT(false);
+EXTERN bool ns_g_sigvalinsecs INIT(false);
+
+#ifdef HAVE_GEOIP
+EXTERN dns_geoip_databases_t *ns_g_geoip INIT(NULL);
+#endif
+
+EXTERN const char * ns_g_fuzz_named_addr INIT(NULL);
+EXTERN ns_fuzz_t ns_g_fuzz_type INIT(ns_fuzz_none);
+
+EXTERN dns_acl_t * ns_g_mapped INIT(NULL);
+
+#undef EXTERN
+#undef INIT
+
+#endif /* NAMED_GLOBALS_H */
diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h
new file mode 100644
index 0000000..7d1883e
--- /dev/null
+++ b/bin/named/include/named/interfacemgr.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */
+
+#ifndef NAMED_INTERFACEMGR_H
+#define NAMED_INTERFACEMGR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * The interface manager monitors the operating system's list
+ * of network interfaces, creating and destroying listeners
+ * as needed.
+ *
+ * Reliability:
+ *\li No impact expected.
+ *
+ * Resources:
+ *
+ * Security:
+ * \li The server will only be able to bind to the DNS port on
+ * newly discovered interfaces if it is running as root.
+ *
+ * Standards:
+ *\li The API for scanning varies greatly among operating systems.
+ * This module attempts to hide the differences.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdbool.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+
+#include <dns/result.h>
+
+#include <named/listenlist.h>
+#include <named/types.h>
+
+/***
+ *** Types
+ ***/
+
+#define IFACE_MAGIC ISC_MAGIC('I',':','-',')')
+#define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC)
+
+#define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */
+#define MAX_UDP_DISPATCH 128 /*%< Maximum number of UDP dispatchers
+ to start per interface */
+/*% The nameserver interface structure */
+struct ns_interface {
+ unsigned int magic; /*%< Magic number. */
+ ns_interfacemgr_t * mgr; /*%< Interface manager. */
+ isc_mutex_t lock;
+ int references; /*%< Locked */
+ unsigned int generation; /*%< Generation number. */
+ isc_sockaddr_t addr; /*%< Address and port. */
+ unsigned int flags; /*%< Interface characteristics */
+ char name[32]; /*%< Null terminated. */
+ dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH];
+ /*%< UDP dispatchers. */
+ isc_socket_t * tcpsocket; /*%< TCP socket. */
+ isc_dscp_t dscp; /*%< "listen-on" DSCP value */
+ int ntcptarget; /*%< Desired number of concurrent
+ TCP accepts */
+ int ntcpcurrent; /*%< Current ditto, locked */
+ int nudpdispatch; /*%< Number of UDP dispatches */
+ ns_clientmgr_t * clientmgr; /*%< Client manager. */
+ ISC_LINK(ns_interface_t) link;
+};
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr,
+ dns_dispatchmgr_t *dispatchmgr,
+ isc_task_t *task, ns_interfacemgr_t **mgrp);
+/*%
+ * Create a new interface manager.
+ *
+ * Initially, the new manager will not listen on any interfaces.
+ * Call ns_interfacemgr_setlistenon() and/or ns_interfacemgr_setlistenon6()
+ * to set nonempty listen-on lists.
+ */
+
+void
+ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target);
+
+void
+ns_interfacemgr_detach(ns_interfacemgr_t **targetp);
+
+void
+ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr);
+
+bool
+ns_interfacemgr_islistening(ns_interfacemgr_t *mgr);
+/*%
+ * Return if the manager is listening on any interface. It can be called
+ * after a scan or adjust.
+ */
+
+isc_result_t
+ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose);
+/*%
+ * Scan the operatings system's list of network interfaces
+ * and create listeners when new interfaces are discovered.
+ * Shut down the sockets for interfaces that go away.
+ *
+ * This should be called once on server startup and then
+ * periodically according to the 'interface-interval' option
+ * in named.conf.
+ */
+
+isc_result_t
+ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
+ bool verbose);
+/*%
+ * Similar to ns_interfacemgr_scan(), but this function also tries to see the
+ * need for an explicit listen-on when a list element in 'list' is going to
+ * override an already-listening a wildcard interface.
+ *
+ * This function does not update localhost and localnets ACLs.
+ *
+ * This should be called once on server startup, after configuring views and
+ * zones.
+ */
+
+void
+ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value);
+/*%
+ * Set the IPv4 "listen-on" list of 'mgr' to 'value'.
+ * The previous IPv4 listen-on list is freed.
+ */
+
+void
+ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value);
+/*%
+ * Set the IPv6 "listen-on" list of 'mgr' to 'value'.
+ * The previous IPv6 listen-on list is freed.
+ */
+
+dns_aclenv_t *
+ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr);
+
+void
+ns_interface_attach(ns_interface_t *source, ns_interface_t **target);
+
+void
+ns_interface_detach(ns_interface_t **targetp);
+
+void
+ns_interface_shutdown(ns_interface_t *ifp);
+/*%
+ * Stop listening for queries on interface 'ifp'.
+ * May safely be called multiple times.
+ */
+
+void
+ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr);
+
+bool
+ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr);
+
+#endif /* NAMED_INTERFACEMGR_H */
diff --git a/bin/named/include/named/listenlist.h b/bin/named/include/named/listenlist.h
new file mode 100644
index 0000000..d44594c
--- /dev/null
+++ b/bin/named/include/named/listenlist.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: listenlist.h,v 1.15 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LISTENLIST_H
+#define NAMED_LISTENLIST_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * "Listen lists", as in the "listen-on" configuration statement.
+ */
+
+/***
+ *** Imports
+ ***/
+
+
+#include <stdbool.h>
+#include <isc/net.h>
+
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+typedef struct ns_listenelt ns_listenelt_t;
+typedef struct ns_listenlist ns_listenlist_t;
+
+struct ns_listenelt {
+ isc_mem_t * mctx;
+ in_port_t port;
+ isc_dscp_t dscp; /* -1 = not set, 0..63 */
+ dns_acl_t * acl;
+ ISC_LINK(ns_listenelt_t) link;
+};
+
+struct ns_listenlist {
+ isc_mem_t * mctx;
+ int refcount;
+ ISC_LIST(ns_listenelt_t) elts;
+};
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
+ dns_acl_t *acl, ns_listenelt_t **target);
+/*%
+ * Create a listen-on list element.
+ */
+
+void
+ns_listenelt_destroy(ns_listenelt_t *elt);
+/*%
+ * Destroy a listen-on list element.
+ */
+
+isc_result_t
+ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target);
+/*%
+ * Create a new, empty listen-on list.
+ */
+
+void
+ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target);
+/*%
+ * Attach '*target' to '*source'.
+ */
+
+void
+ns_listenlist_detach(ns_listenlist_t **listp);
+/*%
+ * Detach 'listp'.
+ */
+
+isc_result_t
+ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
+ bool enabled, ns_listenlist_t **target);
+/*%
+ * Create a listen-on list with default contents, matching
+ * all addresses with port 'port' (if 'enabled' is true),
+ * or no addresses (if 'enabled' is false).
+ */
+
+#endif /* NAMED_LISTENLIST_H */
diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h
new file mode 100644
index 0000000..56bfcd4
--- /dev/null
+++ b/bin/named/include/named/log.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: log.h,v 1.27 2009/01/07 23:47:46 tbox Exp $ */
+
+#ifndef NAMED_LOG_H
+#define NAMED_LOG_H 1
+
+/*! \file */
+
+#include <isc/log.h>
+#include <isc/types.h>
+
+#include <dns/log.h>
+
+#include <named/globals.h> /* Required for ns_g_(categories|modules). */
+
+/* Unused slot 0. */
+#define NS_LOGCATEGORY_CLIENT (&ns_g_categories[1])
+#define NS_LOGCATEGORY_NETWORK (&ns_g_categories[2])
+#define NS_LOGCATEGORY_UPDATE (&ns_g_categories[3])
+#define NS_LOGCATEGORY_QUERIES (&ns_g_categories[4])
+#define NS_LOGCATEGORY_UNMATCHED (&ns_g_categories[5])
+#define NS_LOGCATEGORY_UPDATE_SECURITY (&ns_g_categories[6])
+#define NS_LOGCATEGORY_QUERY_ERRORS (&ns_g_categories[7])
+#define NS_LOGCATEGORY_TAT (&ns_g_categories[8])
+
+/*
+ * Backwards compatibility.
+ */
+#define NS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL
+
+#define NS_LOGMODULE_MAIN (&ns_g_modules[0])
+#define NS_LOGMODULE_CLIENT (&ns_g_modules[1])
+#define NS_LOGMODULE_SERVER (&ns_g_modules[2])
+#define NS_LOGMODULE_QUERY (&ns_g_modules[3])
+#define NS_LOGMODULE_INTERFACEMGR (&ns_g_modules[4])
+#define NS_LOGMODULE_UPDATE (&ns_g_modules[5])
+#define NS_LOGMODULE_XFER_IN (&ns_g_modules[6])
+#define NS_LOGMODULE_XFER_OUT (&ns_g_modules[7])
+#define NS_LOGMODULE_NOTIFY (&ns_g_modules[8])
+#define NS_LOGMODULE_CONTROL (&ns_g_modules[9])
+#define NS_LOGMODULE_LWRESD (&ns_g_modules[10])
+
+isc_result_t
+ns_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.
+ */
+
+isc_result_t
+ns_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.
+ */
+
+isc_result_t
+ns_log_setsafechannels(isc_logconfig_t *lcfg);
+/*%
+ * Like ns_log_setdefaultchannels(), but omits any logging to files.
+ */
+
+isc_result_t
+ns_log_setdefaultcategory(isc_logconfig_t *lcfg);
+/*%
+ * Set up "category default" to go to the right places.
+ */
+
+isc_result_t
+ns_log_setunmatchedcategory(isc_logconfig_t *lcfg);
+/*%
+ * Set up "category unmatched" to go to the right places.
+ */
+
+void
+ns_log_shutdown(void);
+
+#endif /* NAMED_LOG_H */
diff --git a/bin/named/include/named/logconf.h b/bin/named/include/named/logconf.h
new file mode 100644
index 0000000..90dc9c4
--- /dev/null
+++ b/bin/named/include/named/logconf.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef NAMED_LOGCONF_H
+#define NAMED_LOGCONF_H 1
+
+/*! \file */
+
+#include <isc/log.h>
+
+isc_result_t
+ns_log_configure(isc_logconfig_t *logconf, const cfg_obj_t *logstmt);
+/*%<
+ * Set up the logging configuration in '*logconf' according to
+ * the named.conf data in 'logstmt'.
+ */
+
+#endif /* NAMED_LOGCONF_H */
diff --git a/bin/named/include/named/lwaddr.h b/bin/named/include/named/lwaddr.h
new file mode 100644
index 0000000..a48d756
--- /dev/null
+++ b/bin/named/include/named/lwaddr.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwaddr.h,v 1.8 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+isc_result_t
+lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la);
+
+isc_result_t
+lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la,
+ in_port_t port);
+
+isc_result_t
+lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na);
+
+isc_result_t
+lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa);
diff --git a/bin/named/include/named/lwdclient.h b/bin/named/include/named/lwdclient.h
new file mode 100644
index 0000000..65e630d
--- /dev/null
+++ b/bin/named/include/named/lwdclient.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwdclient.h,v 1.20 2009/01/17 23:47:42 tbox Exp $ */
+
+#ifndef NAMED_LWDCLIENT_H
+#define NAMED_LWDCLIENT_H 1
+
+/*! \file */
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/types.h>
+
+#include <dns/fixedname.h>
+#include <dns/types.h>
+
+#include <lwres/lwres.h>
+
+#include <named/lwsearch.h>
+
+#define LWRD_EVENTCLASS ISC_EVENTCLASS(4242)
+
+#define LWRD_SHUTDOWN (LWRD_EVENTCLASS + 0x0001)
+
+/*% Lightweight Resolver Daemon Client */
+struct ns_lwdclient {
+ isc_sockaddr_t address; /*%< where to reply */
+ struct in6_pktinfo pktinfo;
+ bool pktinfo_valid;
+ ns_lwdclientmgr_t *clientmgr; /*%< our parent */
+ ISC_LINK(ns_lwdclient_t) link;
+ unsigned int state;
+ void *arg; /*%< packet processing state */
+
+ /*
+ * Received data info.
+ */
+ unsigned char buffer[LWRES_RECVLENGTH]; /*%< receive buffer */
+ uint32_t recvlength; /*%< length recv'd */
+ lwres_lwpacket_t pkt;
+
+ /*%
+ * Send data state. If sendbuf != buffer (that is, the send buffer
+ * isn't our receive buffer) it will be freed to the lwres_context_t.
+ */
+ unsigned char *sendbuf;
+ uint32_t sendlength;
+ isc_buffer_t recv_buffer;
+
+ /*%
+ * gabn (get address by name) state info.
+ */
+ dns_adbfind_t *find;
+ dns_adbfind_t *v4find;
+ dns_adbfind_t *v6find;
+ unsigned int find_wanted; /*%< Addresses we want */
+ dns_fixedname_t query_name;
+ dns_fixedname_t target_name;
+ ns_lwsearchctx_t searchctx;
+ lwres_gabnresponse_t gabn;
+
+ /*%
+ * gnba (get name by address) state info.
+ */
+ lwres_gnbaresponse_t gnba;
+ dns_byaddr_t *byaddr;
+ unsigned int options;
+ isc_netaddr_t na;
+
+ /*%
+ * grbn (get rrset by name) state info.
+ *
+ * Note: this also uses target_name and searchctx.
+ */
+ lwres_grbnresponse_t grbn;
+ dns_lookup_t *lookup;
+ dns_rdatatype_t rdtype;
+
+ /*%
+ * Alias and address info. This is copied up to the gabn/gnba
+ * structures eventually.
+ *
+ * XXXMLG We can keep all of this in a client since we only service
+ * three packet types right now. If we started handling more,
+ * we'd need to use "arg" above and allocate/destroy things.
+ */
+ char *aliases[LWRES_MAX_ALIASES];
+ uint16_t aliaslen[LWRES_MAX_ALIASES];
+ lwres_addr_t addrs[LWRES_MAX_ADDRS];
+};
+
+/*%
+ * Client states.
+ *
+ * _IDLE The client is not doing anything at all.
+ *
+ * _RECV The client is waiting for data after issuing a socket recv().
+ *
+ * _RECVDONE Data has been received, and is being processed.
+ *
+ * _FINDWAIT An adb (or other) request was made that cannot be satisfied
+ * immediately. An event will wake the client up.
+ *
+ * _SEND All data for a response has completed, and a reply was
+ * sent via a socket send() call.
+ *
+ * Badly formatted state table:
+ *
+ * IDLE -> RECV when client has a recv() queued.
+ *
+ * RECV -> RECVDONE when recvdone event received.
+ *
+ * RECVDONE -> SEND if the data for a reply is at hand.
+ * RECVDONE -> FINDWAIT if more searching is needed, and events will
+ * eventually wake us up again.
+ *
+ * FINDWAIT -> SEND when enough data was received to reply.
+ *
+ * SEND -> IDLE when a senddone event was received.
+ *
+ * At any time -> IDLE on error. Sometimes this will be -> SEND
+ * instead, if enough data is on hand to reply with a meaningful
+ * error.
+ *
+ * Packets which are badly formatted may or may not get error returns.
+ */
+#define NS_LWDCLIENT_STATEIDLE 1
+#define NS_LWDCLIENT_STATERECV 2
+#define NS_LWDCLIENT_STATERECVDONE 3
+#define NS_LWDCLIENT_STATEFINDWAIT 4
+#define NS_LWDCLIENT_STATESEND 5
+#define NS_LWDCLIENT_STATESENDDONE 6
+
+#define NS_LWDCLIENT_ISIDLE(c) \
+ ((c)->state == NS_LWDCLIENT_STATEIDLE)
+#define NS_LWDCLIENT_ISRECV(c) \
+ ((c)->state == NS_LWDCLIENT_STATERECV)
+#define NS_LWDCLIENT_ISRECVDONE(c) \
+ ((c)->state == NS_LWDCLIENT_STATERECVDONE)
+#define NS_LWDCLIENT_ISFINDWAIT(c) \
+ ((c)->state == NS_LWDCLIENT_STATEFINDWAIT)
+#define NS_LWDCLIENT_ISSEND(c) \
+ ((c)->state == NS_LWDCLIENT_STATESEND)
+
+/*%
+ * Overall magic test that means we're not idle.
+ */
+#define NS_LWDCLIENT_ISRUNNING(c) (!NS_LWDCLIENT_ISIDLE(c))
+
+#define NS_LWDCLIENT_SETIDLE(c) \
+ ((c)->state = NS_LWDCLIENT_STATEIDLE)
+#define NS_LWDCLIENT_SETRECV(c) \
+ ((c)->state = NS_LWDCLIENT_STATERECV)
+#define NS_LWDCLIENT_SETRECVDONE(c) \
+ ((c)->state = NS_LWDCLIENT_STATERECVDONE)
+#define NS_LWDCLIENT_SETFINDWAIT(c) \
+ ((c)->state = NS_LWDCLIENT_STATEFINDWAIT)
+#define NS_LWDCLIENT_SETSEND(c) \
+ ((c)->state = NS_LWDCLIENT_STATESEND)
+#define NS_LWDCLIENT_SETSENDDONE(c) \
+ ((c)->state = NS_LWDCLIENT_STATESENDDONE)
+
+/*% lightweight daemon client manager */
+struct ns_lwdclientmgr {
+ ns_lwreslistener_t *listener;
+ isc_mem_t *mctx;
+ isc_socket_t *sock; /*%< socket to use */
+ dns_view_t *view;
+ lwres_context_t *lwctx; /*%< lightweight proto context */
+ isc_task_t *task; /*%< owning task */
+ unsigned int flags;
+ isc_mutex_t lock;
+ ISC_LINK(ns_lwdclientmgr_t) link;
+ ISC_LIST(ns_lwdclient_t) idle; /*%< idle client slots */
+ ISC_LIST(ns_lwdclient_t) running; /*%< running clients */
+};
+
+#define NS_LWDCLIENTMGR_FLAGRECVPENDING 0x00000001
+#define NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN 0x00000002
+
+isc_result_t
+ns_lwdclientmgr_create(ns_lwreslistener_t *, unsigned int, isc_taskmgr_t *);
+
+void
+ns_lwdclient_initialize(ns_lwdclient_t *, ns_lwdclientmgr_t *);
+
+isc_result_t
+ns_lwdclient_startrecv(ns_lwdclientmgr_t *);
+
+void
+ns_lwdclient_stateidle(ns_lwdclient_t *);
+
+void
+ns_lwdclient_recv(isc_task_t *, isc_event_t *);
+
+void
+ns_lwdclient_shutdown(isc_task_t *, isc_event_t *);
+
+void
+ns_lwdclient_send(isc_task_t *, isc_event_t *);
+
+isc_result_t
+ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r);
+
+/*
+ * Processing functions of various types.
+ */
+void ns_lwdclient_processgabn(ns_lwdclient_t *, lwres_buffer_t *);
+void ns_lwdclient_processgnba(ns_lwdclient_t *, lwres_buffer_t *);
+void ns_lwdclient_processgrbn(ns_lwdclient_t *, lwres_buffer_t *);
+void ns_lwdclient_processnoop(ns_lwdclient_t *, lwres_buffer_t *);
+
+void ns_lwdclient_errorpktsend(ns_lwdclient_t *, uint32_t);
+
+void ns_lwdclient_log(int level, const char *format, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+#endif /* NAMED_LWDCLIENT_H */
diff --git a/bin/named/include/named/lwresd.h b/bin/named/include/named/lwresd.h
new file mode 100644
index 0000000..90e5113
--- /dev/null
+++ b/bin/named/include/named/lwresd.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwresd.h,v 1.19 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LWRESD_H
+#define NAMED_LWRESD_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/sockaddr.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/types.h>
+
+struct ns_lwresd {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ dns_view_t *view;
+ ns_lwsearchlist_t *search;
+ unsigned int ndots;
+ unsigned int ntasks;
+ unsigned int nclients;
+ isc_mem_t *mctx;
+ bool shutting_down;
+ unsigned int refs;
+};
+
+struct ns_lwreslistener {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+ isc_sockaddr_t address;
+ ns_lwresd_t *manager;
+ isc_socket_t *sock;
+ unsigned int refs;
+ ISC_LIST(ns_lwdclientmgr_t) cmgrs;
+ ISC_LINK(ns_lwreslistener_t) link;
+};
+
+/*%
+ * Configure lwresd.
+ */
+isc_result_t
+ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config);
+
+isc_result_t
+ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
+ cfg_obj_t **configp);
+
+/*%
+ * Trigger shutdown.
+ */
+void
+ns_lwresd_shutdown(void);
+
+/*
+ * Manager functions
+ */
+/*% create manager */
+isc_result_t
+ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
+ ns_lwresd_t **lwresdp);
+
+/*% attach to manager */
+void
+ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp);
+
+/*% detach from manager */
+void
+ns_lwdmanager_detach(ns_lwresd_t **lwresdp);
+
+/*
+ * Listener functions
+ */
+/*% attach to listener */
+void
+ns_lwreslistener_attach(ns_lwreslistener_t *source,
+ ns_lwreslistener_t **targetp);
+
+/*% detach from lister */
+void
+ns_lwreslistener_detach(ns_lwreslistener_t **listenerp);
+
+/*% link client manager */
+void
+ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm);
+
+/*% unlink client manager */
+void
+ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm);
+
+
+
+
+/*
+ * INTERNAL FUNCTIONS.
+ */
+void *
+ns__lwresd_memalloc(void *arg, size_t size);
+
+void
+ns__lwresd_memfree(void *arg, void *mem, size_t size);
+
+#endif /* NAMED_LWRESD_H */
diff --git a/bin/named/include/named/lwsearch.h b/bin/named/include/named/lwsearch.h
new file mode 100644
index 0000000..cf3bc6a
--- /dev/null
+++ b/bin/named/include/named/lwsearch.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwsearch.h,v 1.9 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LWSEARCH_H
+#define NAMED_LWSEARCH_H 1
+
+#include <isc/mutex.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+#include <named/types.h>
+
+/*! \file
+ * \brief
+ * Lightweight resolver search list types and routines.
+ *
+ * An ns_lwsearchlist_t holds a list of search path elements.
+ *
+ * An ns_lwsearchctx stores the state of search list during a lookup
+ * operation.
+ */
+
+/*% An ns_lwsearchlist_t holds a list of search path elements. */
+struct ns_lwsearchlist {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+ unsigned int refs;
+ dns_namelist_t names;
+};
+/*% An ns_lwsearchctx stores the state of search list during a lookup operation. */
+struct ns_lwsearchctx {
+ dns_name_t *relname;
+ dns_name_t *searchname;
+ unsigned int ndots;
+ ns_lwsearchlist_t *list;
+ bool doneexact;
+ bool exactfirst;
+};
+
+isc_result_t
+ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp);
+/*%<
+ * Create an empty search list object.
+ */
+
+void
+ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target);
+/*%<
+ * Attach to a search list object.
+ */
+
+void
+ns_lwsearchlist_detach(ns_lwsearchlist_t **listp);
+/*%<
+ * Detach from a search list object.
+ */
+
+isc_result_t
+ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name);
+/*%<
+ * Append an element to a search list. This creates a copy of the name.
+ */
+
+void
+ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list,
+ dns_name_t *name, unsigned int ndots);
+/*%<
+ * Creates a search list context structure.
+ */
+
+void
+ns_lwsearchctx_first(ns_lwsearchctx_t *sctx);
+/*%<
+ * Moves the search list context iterator to the first element, which
+ * is usually the exact name.
+ */
+
+isc_result_t
+ns_lwsearchctx_next(ns_lwsearchctx_t *sctx);
+/*%<
+ * Moves the search list context iterator to the next element.
+ */
+
+isc_result_t
+ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname);
+/*%<
+ * Obtains the current name to be looked up. This involves either
+ * concatenating the name with a search path element, making an
+ * exact name absolute, or doing nothing.
+ */
+
+#endif /* NAMED_LWSEARCH_H */
diff --git a/bin/named/include/named/main.h b/bin/named/include/named/main.h
new file mode 100644
index 0000000..2860bc2
--- /dev/null
+++ b/bin/named/include/named/main.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_MAIN_H
+#define NAMED_MAIN_H 1
+
+/*! \file */
+
+#ifdef ISC_MAIN_HOOK
+#define main(argc, argv) bindmain(argc, argv)
+#endif
+
+/*
+ * Commandline arguments for named; also referenced in win32/ntservice.c
+ */
+#define NS_MAIN_ARGS "46A:c:C:d:D:E:fFgi:lL:M:m:n:N:p:P:sS:t:T:U:u:vVx:X:"
+
+ISC_PLATFORM_NORETURN_PRE void
+ns_main_earlyfatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+void
+ns_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+ns_main_setmemstats(const char *);
+
+#endif /* NAMED_MAIN_H */
diff --git a/bin/named/include/named/notify.h b/bin/named/include/named/notify.h
new file mode 100644
index 0000000..293a6a8
--- /dev/null
+++ b/bin/named/include/named/notify.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: notify.h,v 1.16 2009/01/17 23:47:42 tbox Exp $ */
+
+#ifndef NAMED_NOTIFY_H
+#define NAMED_NOTIFY_H 1
+
+#include <named/types.h>
+#include <named/client.h>
+
+/***
+ *** Module Info
+ ***/
+
+/*! \file
+ * \brief
+ * RFC1996
+ * A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)
+ */
+
+/***
+ *** Functions.
+ ***/
+
+void
+ns_notify_start(ns_client_t *client);
+
+/*%<
+ * Examines the incoming message to determine appropriate zone.
+ * Returns FORMERR if there is not exactly one question.
+ * Returns REFUSED if we do not serve the listed zone.
+ * Pass the message to the zone module for processing
+ * and returns the return status.
+ *
+ * Requires
+ *\li client to be valid.
+ */
+
+#endif /* NAMED_NOTIFY_H */
+
diff --git a/bin/named/include/named/ns_smf_globals.h b/bin/named/include/named/ns_smf_globals.h
new file mode 100644
index 0000000..9fc49e6
--- /dev/null
+++ b/bin/named/include/named/ns_smf_globals.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: ns_smf_globals.h,v 1.7 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NS_SMF_GLOBALS_H
+#define NS_SMF_GLOBALS_H 1
+
+#include <libscf.h>
+
+#undef EXTERN
+#undef INIT
+#ifdef NS_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else
+#define EXTERN extern
+#define INIT(v)
+#endif
+
+EXTERN unsigned int ns_smf_got_instance INIT(0);
+EXTERN unsigned int ns_smf_chroot INIT(0);
+EXTERN unsigned int ns_smf_want_disable INIT(0);
+
+isc_result_t ns_smf_add_message(isc_buffer_t **text);
+isc_result_t ns_smf_get_instance(char **name, int debug, isc_mem_t *mctx);
+
+#undef EXTERN
+#undef INIT
+
+#endif /* NS_SMF_GLOBALS_H */
diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h
new file mode 100644
index 0000000..9661f56
--- /dev/null
+++ b/bin/named/include/named/query.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_QUERY_H
+#define NAMED_QUERY_H 1
+
+/*! \file */
+
+#include <stdbool.h>
+
+#include <isc/types.h>
+#include <isc/buffer.h>
+#include <isc/netaddr.h>
+
+#include <dns/rdataset.h>
+#include <dns/rpz.h>
+#include <dns/types.h>
+
+#include <named/types.h>
+
+/*% nameserver database version structure */
+typedef struct ns_dbversion {
+ dns_db_t *db;
+ dns_dbversion_t *version;
+ bool acl_checked;
+ bool queryok;
+ ISC_LINK(struct ns_dbversion) link;
+} ns_dbversion_t;
+
+/*% nameserver query structure */
+struct ns_query {
+ unsigned int attributes;
+ unsigned int restarts;
+ bool timerset;
+ dns_name_t * qname;
+ dns_name_t * origqname;
+ dns_rdatatype_t qtype;
+ unsigned int dboptions;
+ unsigned int fetchoptions;
+ dns_db_t * gluedb;
+ dns_db_t * authdb;
+ dns_zone_t * authzone;
+ bool authdbset;
+ bool isreferral;
+ isc_mutex_t fetchlock;
+ dns_fetch_t * fetch;
+ dns_fetch_t * prefetch;
+ dns_rpz_st_t * rpz_st;
+ isc_bufferlist_t namebufs;
+ ISC_LIST(ns_dbversion_t) activeversions;
+ ISC_LIST(ns_dbversion_t) freeversions;
+ dns_rdataset_t * dns64_aaaa;
+ dns_rdataset_t * dns64_sigaaaa;
+ bool * dns64_aaaaok;
+ unsigned int dns64_aaaaoklen;
+ unsigned int dns64_options;
+ unsigned int dns64_ttl;
+ struct {
+ dns_db_t * db;
+ dns_zone_t * zone;
+ dns_dbnode_t * node;
+ dns_rdatatype_t qtype;
+ dns_name_t * fname;
+ dns_fixedname_t fixed;
+ isc_result_t result;
+ dns_rdataset_t * rdataset;
+ dns_rdataset_t * sigrdataset;
+ bool authoritative;
+ bool is_zone;
+ } redirect;
+ dns_keytag_t root_key_sentinel_keyid;
+ bool root_key_sentinel_is_ta;
+ bool root_key_sentinel_not_ta;
+};
+
+#define NS_QUERYATTR_RECURSIONOK 0x0001
+#define NS_QUERYATTR_CACHEOK 0x0002
+#define NS_QUERYATTR_PARTIALANSWER 0x0004
+#define NS_QUERYATTR_NAMEBUFUSED 0x0008
+#define NS_QUERYATTR_RECURSING 0x0010
+#define NS_QUERYATTR_CACHEGLUEOK 0x0020
+#define NS_QUERYATTR_QUERYOKVALID 0x0040
+#define NS_QUERYATTR_QUERYOK 0x0080
+#define NS_QUERYATTR_WANTRECURSION 0x0100
+#define NS_QUERYATTR_SECURE 0x0200
+#define NS_QUERYATTR_NOAUTHORITY 0x0400
+#define NS_QUERYATTR_NOADDITIONAL 0x0800
+#define NS_QUERYATTR_CACHEACLOKVALID 0x1000
+#define NS_QUERYATTR_CACHEACLOK 0x2000
+#define NS_QUERYATTR_DNS64 0x4000
+#define NS_QUERYATTR_DNS64EXCLUDE 0x8000
+#define NS_QUERYATTR_RRL_CHECKED 0x10000
+#define NS_QUERYATTR_REDIRECT 0x20000
+
+isc_result_t
+ns_query_init(ns_client_t *client);
+
+void
+ns_query_free(ns_client_t *client);
+
+void
+ns_query_start(ns_client_t *client);
+
+void
+ns_query_cancel(ns_client_t *client);
+
+#endif /* NAMED_QUERY_H */
diff --git a/bin/named/include/named/seccomp.h b/bin/named/include/named/seccomp.h
new file mode 100644
index 0000000..4e2c2d9
--- /dev/null
+++ b/bin/named/include/named/seccomp.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_SECCOMP_H
+#define NAMED_SECCOMP_H 1
+
+/*! \file */
+
+#ifdef HAVE_LIBSECCOMP
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <seccomp.h>
+#include <isc/platform.h>
+
+/*%
+ * For each architecture, the scmp_syscalls and
+ * scmp_syscall_names arrays MUST be kept in sync.
+ */
+#ifdef __x86_64__
+int scmp_syscalls[] = {
+ SCMP_SYS(access),
+ SCMP_SYS(open),
+ SCMP_SYS(openat),
+ SCMP_SYS(lseek),
+ SCMP_SYS(clock_gettime),
+ SCMP_SYS(time),
+ SCMP_SYS(read),
+ SCMP_SYS(write),
+ SCMP_SYS(close),
+ SCMP_SYS(brk),
+ SCMP_SYS(poll),
+ SCMP_SYS(select),
+ SCMP_SYS(madvise),
+ SCMP_SYS(mmap),
+ SCMP_SYS(munmap),
+ SCMP_SYS(exit_group),
+ SCMP_SYS(rt_sigprocmask),
+ SCMP_SYS(rt_sigaction),
+ SCMP_SYS(fsync),
+ SCMP_SYS(rt_sigreturn),
+ SCMP_SYS(setsid),
+ SCMP_SYS(chdir),
+ SCMP_SYS(futex),
+ SCMP_SYS(stat),
+ SCMP_SYS(rt_sigsuspend),
+ SCMP_SYS(fstat),
+ SCMP_SYS(epoll_ctl),
+ SCMP_SYS(gettimeofday),
+ SCMP_SYS(getpid),
+#ifdef HAVE_GETRANDOM
+ SCMP_SYS(getrandom),
+#endif
+ SCMP_SYS(rename),
+ SCMP_SYS(unlink),
+ SCMP_SYS(socket),
+ SCMP_SYS(sendto),
+#ifndef ISC_PLATFORM_USETHREADS
+ SCMP_SYS(bind),
+ SCMP_SYS(accept),
+ SCMP_SYS(connect),
+ SCMP_SYS(listen),
+ SCMP_SYS(fcntl),
+ SCMP_SYS(sendmsg),
+ SCMP_SYS(recvmsg),
+ SCMP_SYS(uname),
+ SCMP_SYS(setrlimit),
+ SCMP_SYS(getrlimit),
+ SCMP_SYS(setsockopt),
+ SCMP_SYS(getsockopt),
+ SCMP_SYS(getsockname),
+ SCMP_SYS(lstat),
+ SCMP_SYS(getgid),
+ SCMP_SYS(getegid),
+ SCMP_SYS(getuid),
+ SCMP_SYS(geteuid),
+ SCMP_SYS(setresgid),
+ SCMP_SYS(setresuid),
+ SCMP_SYS(setgid),
+ SCMP_SYS(setuid),
+ SCMP_SYS(prctl),
+ SCMP_SYS(epoll_wait),
+ SCMP_SYS(getdents),
+ SCMP_SYS(utimes),
+ SCMP_SYS(dup),
+#endif
+};
+const char *scmp_syscall_names[] = {
+ "access",
+ "open",
+ "openat",
+ "lseek",
+ "clock_gettime",
+ "time",
+ "read",
+ "write",
+ "close",
+ "brk",
+ "poll",
+ "select",
+ "madvise",
+ "mmap",
+ "munmap",
+ "exit_group",
+ "rt_sigprocmask",
+ "rt_sigaction",
+ "fsync",
+ "rt_sigreturn",
+ "setsid",
+ "chdir",
+ "futex",
+ "stat",
+ "rt_sigsuspend",
+ "fstat",
+ "epoll_ctl",
+ "gettimeofday",
+ "getpid",
+#ifdef HAVE_GETRANDOM
+ "getrandom",
+#endif
+ "rename",
+ "unlink",
+ "socket",
+ "sendto",
+#ifndef ISC_PLATFORM_USETHREADS
+ "bind",
+ "accept",
+ "connect",
+ "listen",
+ "fcntl",
+ "sendmsg",
+ "recvmsg",
+ "uname",
+ "setrlimit",
+ "getrlimit",
+ "setsockopt",
+ "getsockopt",
+ "getsockname",
+ "lstat",
+ "getgid",
+ "getegid",
+ "getuid",
+ "geteuid",
+ "setresgid",
+ "setresuid",
+ "setgid",
+ "setuid",
+ "prctl",
+ "epoll_wait",
+ "getdents",
+ "utimes",
+ "dup",
+#endif
+};
+#endif /* __x86_64__ */
+#ifdef __i386__
+int scmp_syscalls[] = {
+ SCMP_SYS(access),
+ SCMP_SYS(open),
+ SCMP_SYS(clock_gettime),
+ SCMP_SYS(time),
+ SCMP_SYS(read),
+ SCMP_SYS(write),
+ SCMP_SYS(close),
+ SCMP_SYS(brk),
+ SCMP_SYS(poll),
+ SCMP_SYS(_newselect),
+ SCMP_SYS(select),
+ SCMP_SYS(madvise),
+ SCMP_SYS(mmap2),
+ SCMP_SYS(mmap),
+ SCMP_SYS(munmap),
+ SCMP_SYS(exit_group),
+ SCMP_SYS(rt_sigprocmask),
+ SCMP_SYS(sigprocmask),
+ SCMP_SYS(rt_sigaction),
+ SCMP_SYS(socketcall),
+ SCMP_SYS(fsync),
+ SCMP_SYS(sigreturn),
+ SCMP_SYS(setsid),
+ SCMP_SYS(chdir),
+ SCMP_SYS(futex),
+ SCMP_SYS(stat64),
+ SCMP_SYS(rt_sigsuspend),
+ SCMP_SYS(fstat64),
+ SCMP_SYS(epoll_ctl),
+ SCMP_SYS(gettimeofday),
+ SCMP_SYS(getpid),
+#ifdef HAVE_GETRANDOM
+ SCMP_SYS(getrandom),
+#endif
+ SCMP_SYS(unlink),
+#ifndef ISC_PLATFORM_USETHREADS
+ SCMP_SYS(fcntl64),
+#endif
+};
+const char *scmp_syscall_names[] = {
+ "access",
+ "open",
+ "clock_gettime",
+ "time",
+ "read",
+ "write",
+ "close",
+ "brk",
+ "poll",
+ "_newselect",
+ "select",
+ "madvise",
+ "mmap2",
+ "mmap",
+ "munmap",
+ "exit_group",
+ "rt_sigprocmask",
+ "sigprocmask",
+ "rt_sigaction",
+ "socketcall",
+ "fsync",
+ "sigreturn",
+ "setsid",
+ "chdir",
+ "futex",
+ "stat64",
+ "rt_sigsuspend",
+ "fstat64",
+ "epoll_ctl",
+ "gettimeofday",
+ "getpid",
+#ifdef HAVE_GETRANDOM
+ "getrandom",
+#endif
+ "unlink",
+#ifndef ISC_PLATFORM_USETHREADS
+ "fcntl64",
+#endif
+};
+#endif /* __i386__ */
+#endif /* HAVE_LIBSECCOMP */
+
+#endif /* NAMED_SECCOMP_H */
diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h
new file mode 100644
index 0000000..f5ed2b7
--- /dev/null
+++ b/bin/named/include/named/server.h
@@ -0,0 +1,762 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_SERVER_H
+#define NAMED_SERVER_H 1
+
+/*! \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/types.h>
+#include <isc/xml.h>
+
+#include <dns/acl.h>
+#include <dns/dnstap.h>
+#include <dns/types.h>
+
+#include <named/types.h>
+
+#define NS_EVENTCLASS ISC_EVENTCLASS(0x4E43)
+#define NS_EVENT_RELOAD (NS_EVENTCLASS + 0)
+#define NS_EVENT_CLIENTCONTROL (NS_EVENTCLASS + 1)
+#define NS_EVENT_DELZONE (NS_EVENTCLASS + 2)
+
+/*%
+ * Name server state. Better here than in lots of separate global variables.
+ */
+struct ns_server {
+ unsigned int magic;
+ isc_mem_t * mctx;
+
+ isc_task_t * task;
+
+ /* Configurable data. */
+ isc_quota_t xfroutquota;
+ isc_quota_t tcpquota;
+ isc_quota_t recursionquota;
+
+ dns_acl_t *blackholeacl;
+ dns_acl_t *keepresporder;
+ 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 */
+ /*% Use hostname for server id */
+ bool server_usehostname;
+ char * server_id; /*%< User-specified server id */
+
+ /*%
+ * Current ACL environment. This defines the
+ * current values of the localhost and localnets
+ * ACLs.
+ */
+ dns_aclenv_t aclenv;
+
+ /* Server data structures. */
+ dns_loadmgr_t * loadmgr;
+ dns_zonemgr_t * zonemgr;
+ dns_viewlist_t viewlist;
+ ns_interfacemgr_t * interfacemgr;
+ dns_db_t * in_roothints;
+ dns_tkeyctx_t * tkeyctx;
+
+ 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;
+
+ isc_mutex_t reload_event_lock;
+ isc_event_t * reload_event;
+
+ bool flushonshutdown;
+ bool log_queries; /*%< For BIND 8 compatibility */
+
+ ns_cachelist_t cachelist; /*%< Possibly shared caches */
+ isc_stats_t * nsstats; /*%< Server stats */
+ dns_stats_t * rcvquerystats; /*% Incoming query stats */
+ dns_stats_t * opcodestats; /*%< Incoming message stats */
+ isc_stats_t * zonestats; /*% Zone management stats */
+ isc_stats_t * resolverstats; /*% Resolver stats */
+ isc_stats_t * sockstats; /*%< Socket stats */
+ isc_stats_t * udpinstats4; /*%< Traffic size: UDPv4 in */
+ isc_stats_t * udpoutstats4; /*%< Traffic size: UDPv4 out */
+ isc_stats_t * udpinstats6; /*%< Traffic size: UDPv6 in */
+ isc_stats_t * udpoutstats6; /*%< Traffic size: UDPv6 out */
+ isc_stats_t * tcpinstats4; /*%< Traffic size: TCPv4 in */
+ isc_stats_t * tcpoutstats4; /*%< Traffic size: TCPv4 out */
+ isc_stats_t * tcpinstats6; /*%< Traffic size: TCPv6 in */
+ isc_stats_t * tcpoutstats6; /*%< Traffic size: TCPv6 out */
+ dns_stats_t * rcodestats; /*%< Sent Response code stats */
+
+ ns_controls_t * controls; /*%< Control channels */
+ unsigned int dispatchgen;
+ ns_dispatchlist_t dispatches;
+
+ dns_acache_t *acache;
+
+ ns_statschannellist_t statschannels;
+
+ dns_tsigkey_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_altsecretlist_t altsecrets;
+ ns_cookiealg_t cookiealg;
+ bool answercookie;
+
+ dns_dtenv_t *dtenv; /*%< Dnstap environment */
+
+ char * lockfile;
+
+ uint16_t transfer_tcp_message_size;
+};
+
+struct ns_altsecret {
+ ISC_LINK(ns_altsecret_t) link;
+ unsigned char secret[32];
+};
+
+#define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
+#define NS_SERVER_VALID(s) ISC_MAGIC_VALID(s, NS_SERVER_MAGIC)
+
+/*%
+ * Server statistics counters. Used as isc_statscounter_t values.
+ */
+enum {
+ dns_nsstatscounter_requestv4 = 0,
+ dns_nsstatscounter_requestv6 = 1,
+ dns_nsstatscounter_edns0in = 2,
+ dns_nsstatscounter_badednsver = 3,
+ dns_nsstatscounter_tsigin = 4,
+ dns_nsstatscounter_sig0in = 5,
+ dns_nsstatscounter_invalidsig = 6,
+ dns_nsstatscounter_requesttcp = 7,
+
+ dns_nsstatscounter_authrej = 8,
+ dns_nsstatscounter_recurserej = 9,
+ dns_nsstatscounter_xfrrej = 10,
+ dns_nsstatscounter_updaterej = 11,
+
+ dns_nsstatscounter_response = 12,
+ dns_nsstatscounter_truncatedresp = 13,
+ dns_nsstatscounter_edns0out = 14,
+ dns_nsstatscounter_tsigout = 15,
+ dns_nsstatscounter_sig0out = 16,
+
+ dns_nsstatscounter_success = 17,
+ dns_nsstatscounter_authans = 18,
+ dns_nsstatscounter_nonauthans = 19,
+ dns_nsstatscounter_referral = 20,
+ dns_nsstatscounter_nxrrset = 21,
+ dns_nsstatscounter_servfail = 22,
+ dns_nsstatscounter_formerr = 23,
+ dns_nsstatscounter_nxdomain = 24,
+ dns_nsstatscounter_recursion = 25,
+ dns_nsstatscounter_duplicate = 26,
+ dns_nsstatscounter_dropped = 27,
+ dns_nsstatscounter_failure = 28,
+
+ dns_nsstatscounter_xfrdone = 29,
+
+ dns_nsstatscounter_updatereqfwd = 30,
+ dns_nsstatscounter_updaterespfwd = 31,
+ dns_nsstatscounter_updatefwdfail = 32,
+ dns_nsstatscounter_updatedone = 33,
+ dns_nsstatscounter_updatefail = 34,
+ dns_nsstatscounter_updatebadprereq = 35,
+
+ dns_nsstatscounter_recursclients = 36,
+
+ dns_nsstatscounter_dns64 = 37,
+
+ dns_nsstatscounter_ratedropped = 38,
+ dns_nsstatscounter_rateslipped = 39,
+
+ dns_nsstatscounter_rpz_rewrites = 40,
+
+ dns_nsstatscounter_udp = 41,
+ dns_nsstatscounter_tcp = 42,
+
+ dns_nsstatscounter_nsidopt = 43,
+ dns_nsstatscounter_expireopt = 44,
+ dns_nsstatscounter_otheropt = 45,
+ dns_nsstatscounter_ecsopt = 46,
+
+ dns_nsstatscounter_nxdomainredirect = 47,
+ dns_nsstatscounter_nxdomainredirect_rlookup = 48,
+
+ dns_nsstatscounter_cookiein = 49,
+ dns_nsstatscounter_cookiebadsize = 50,
+ dns_nsstatscounter_cookiebadtime = 51,
+ dns_nsstatscounter_cookienomatch = 52,
+ dns_nsstatscounter_cookiematch = 53,
+ dns_nsstatscounter_cookienew = 54,
+ dns_nsstatscounter_badcookie = 55,
+
+ dns_nsstatscounter_keytagopt = 56,
+
+ dns_nsstatscounter_max = 57
+};
+
+/*%
+ * Traffic size statistics counters. Used as isc_statscounter_t values.
+ */
+enum {
+ dns_sizecounter_in_0 = 0,
+ dns_sizecounter_in_16 = 1,
+ dns_sizecounter_in_32 = 2,
+ dns_sizecounter_in_48 = 3,
+ dns_sizecounter_in_64 = 4,
+ dns_sizecounter_in_80 = 5,
+ dns_sizecounter_in_96 = 6,
+ dns_sizecounter_in_112 = 7,
+ dns_sizecounter_in_128 = 8,
+ dns_sizecounter_in_144 = 9,
+ dns_sizecounter_in_160 = 10,
+ dns_sizecounter_in_176 = 11,
+ dns_sizecounter_in_192 = 12,
+ dns_sizecounter_in_208 = 13,
+ dns_sizecounter_in_224 = 14,
+ dns_sizecounter_in_240 = 15,
+ dns_sizecounter_in_256 = 16,
+ dns_sizecounter_in_272 = 17,
+ dns_sizecounter_in_288 = 18,
+
+ dns_sizecounter_in_max = 19,
+};
+
+enum {
+ dns_sizecounter_out_0 = 0,
+ dns_sizecounter_out_16 = 1,
+ dns_sizecounter_out_32 = 2,
+ dns_sizecounter_out_48 = 3,
+ dns_sizecounter_out_64 = 4,
+ dns_sizecounter_out_80 = 5,
+ dns_sizecounter_out_96 = 6,
+ dns_sizecounter_out_112 = 7,
+ dns_sizecounter_out_128 = 8,
+ dns_sizecounter_out_144 = 9,
+ dns_sizecounter_out_160 = 10,
+ dns_sizecounter_out_176 = 11,
+ dns_sizecounter_out_192 = 12,
+ dns_sizecounter_out_208 = 13,
+ dns_sizecounter_out_224 = 14,
+ dns_sizecounter_out_240 = 15,
+ dns_sizecounter_out_256 = 16,
+ dns_sizecounter_out_272 = 17,
+ dns_sizecounter_out_288 = 18,
+ dns_sizecounter_out_304 = 19,
+ dns_sizecounter_out_320 = 20,
+ dns_sizecounter_out_336 = 21,
+ dns_sizecounter_out_352 = 22,
+ dns_sizecounter_out_368 = 23,
+ dns_sizecounter_out_384 = 24,
+ dns_sizecounter_out_400 = 25,
+ dns_sizecounter_out_416 = 26,
+ dns_sizecounter_out_432 = 27,
+ dns_sizecounter_out_448 = 28,
+ dns_sizecounter_out_464 = 29,
+ dns_sizecounter_out_480 = 30,
+ dns_sizecounter_out_496 = 31,
+ dns_sizecounter_out_512 = 32,
+ dns_sizecounter_out_528 = 33,
+ dns_sizecounter_out_544 = 34,
+ dns_sizecounter_out_560 = 35,
+ dns_sizecounter_out_576 = 36,
+ dns_sizecounter_out_592 = 37,
+ dns_sizecounter_out_608 = 38,
+ dns_sizecounter_out_624 = 39,
+ dns_sizecounter_out_640 = 40,
+ dns_sizecounter_out_656 = 41,
+ dns_sizecounter_out_672 = 42,
+ dns_sizecounter_out_688 = 43,
+ dns_sizecounter_out_704 = 44,
+ dns_sizecounter_out_720 = 45,
+ dns_sizecounter_out_736 = 46,
+ dns_sizecounter_out_752 = 47,
+ dns_sizecounter_out_768 = 48,
+ dns_sizecounter_out_784 = 49,
+ dns_sizecounter_out_800 = 50,
+ dns_sizecounter_out_816 = 51,
+ dns_sizecounter_out_832 = 52,
+ dns_sizecounter_out_848 = 53,
+ dns_sizecounter_out_864 = 54,
+ dns_sizecounter_out_880 = 55,
+ dns_sizecounter_out_896 = 56,
+ dns_sizecounter_out_912 = 57,
+ dns_sizecounter_out_928 = 58,
+ dns_sizecounter_out_944 = 59,
+ dns_sizecounter_out_960 = 60,
+ dns_sizecounter_out_976 = 61,
+ dns_sizecounter_out_992 = 62,
+ dns_sizecounter_out_1008 = 63,
+ dns_sizecounter_out_1024 = 64,
+ dns_sizecounter_out_1040 = 65,
+ dns_sizecounter_out_1056 = 66,
+ dns_sizecounter_out_1072 = 67,
+ dns_sizecounter_out_1088 = 68,
+ dns_sizecounter_out_1104 = 69,
+ dns_sizecounter_out_1120 = 70,
+ dns_sizecounter_out_1136 = 71,
+ dns_sizecounter_out_1152 = 72,
+ dns_sizecounter_out_1168 = 73,
+ dns_sizecounter_out_1184 = 74,
+ dns_sizecounter_out_1200 = 75,
+ dns_sizecounter_out_1216 = 76,
+ dns_sizecounter_out_1232 = 77,
+ dns_sizecounter_out_1248 = 78,
+ dns_sizecounter_out_1264 = 79,
+ dns_sizecounter_out_1280 = 80,
+ dns_sizecounter_out_1296 = 81,
+ dns_sizecounter_out_1312 = 82,
+ dns_sizecounter_out_1328 = 83,
+ dns_sizecounter_out_1344 = 84,
+ dns_sizecounter_out_1360 = 85,
+ dns_sizecounter_out_1376 = 86,
+ dns_sizecounter_out_1392 = 87,
+ dns_sizecounter_out_1408 = 88,
+ dns_sizecounter_out_1424 = 89,
+ dns_sizecounter_out_1440 = 90,
+ dns_sizecounter_out_1456 = 91,
+ dns_sizecounter_out_1472 = 92,
+ dns_sizecounter_out_1488 = 93,
+ dns_sizecounter_out_1504 = 94,
+ dns_sizecounter_out_1520 = 95,
+ dns_sizecounter_out_1536 = 96,
+ dns_sizecounter_out_1552 = 97,
+ dns_sizecounter_out_1568 = 98,
+ dns_sizecounter_out_1584 = 99,
+ dns_sizecounter_out_1600 = 100,
+ dns_sizecounter_out_1616 = 101,
+ dns_sizecounter_out_1632 = 102,
+ dns_sizecounter_out_1648 = 103,
+ dns_sizecounter_out_1664 = 104,
+ dns_sizecounter_out_1680 = 105,
+ dns_sizecounter_out_1696 = 106,
+ dns_sizecounter_out_1712 = 107,
+ dns_sizecounter_out_1728 = 108,
+ dns_sizecounter_out_1744 = 109,
+ dns_sizecounter_out_1760 = 110,
+ dns_sizecounter_out_1776 = 111,
+ dns_sizecounter_out_1792 = 112,
+ dns_sizecounter_out_1808 = 113,
+ dns_sizecounter_out_1824 = 114,
+ dns_sizecounter_out_1840 = 115,
+ dns_sizecounter_out_1856 = 116,
+ dns_sizecounter_out_1872 = 117,
+ dns_sizecounter_out_1888 = 118,
+ dns_sizecounter_out_1904 = 119,
+ dns_sizecounter_out_1920 = 120,
+ dns_sizecounter_out_1936 = 121,
+ dns_sizecounter_out_1952 = 122,
+ dns_sizecounter_out_1968 = 123,
+ dns_sizecounter_out_1984 = 124,
+ dns_sizecounter_out_2000 = 125,
+ dns_sizecounter_out_2016 = 126,
+ dns_sizecounter_out_2032 = 127,
+ dns_sizecounter_out_2048 = 128,
+ dns_sizecounter_out_2064 = 129,
+ dns_sizecounter_out_2080 = 130,
+ dns_sizecounter_out_2096 = 131,
+ dns_sizecounter_out_2112 = 132,
+ dns_sizecounter_out_2128 = 133,
+ dns_sizecounter_out_2144 = 134,
+ dns_sizecounter_out_2160 = 135,
+ dns_sizecounter_out_2176 = 136,
+ dns_sizecounter_out_2192 = 137,
+ dns_sizecounter_out_2208 = 138,
+ dns_sizecounter_out_2224 = 139,
+ dns_sizecounter_out_2240 = 140,
+ dns_sizecounter_out_2256 = 141,
+ dns_sizecounter_out_2272 = 142,
+ dns_sizecounter_out_2288 = 143,
+ dns_sizecounter_out_2304 = 144,
+ dns_sizecounter_out_2320 = 145,
+ dns_sizecounter_out_2336 = 146,
+ dns_sizecounter_out_2352 = 147,
+ dns_sizecounter_out_2368 = 148,
+ dns_sizecounter_out_2384 = 149,
+ dns_sizecounter_out_2400 = 150,
+ dns_sizecounter_out_2416 = 151,
+ dns_sizecounter_out_2432 = 152,
+ dns_sizecounter_out_2448 = 153,
+ dns_sizecounter_out_2464 = 154,
+ dns_sizecounter_out_2480 = 155,
+ dns_sizecounter_out_2496 = 156,
+ dns_sizecounter_out_2512 = 157,
+ dns_sizecounter_out_2528 = 158,
+ dns_sizecounter_out_2544 = 159,
+ dns_sizecounter_out_2560 = 160,
+ dns_sizecounter_out_2576 = 161,
+ dns_sizecounter_out_2592 = 162,
+ dns_sizecounter_out_2608 = 163,
+ dns_sizecounter_out_2624 = 164,
+ dns_sizecounter_out_2640 = 165,
+ dns_sizecounter_out_2656 = 166,
+ dns_sizecounter_out_2672 = 167,
+ dns_sizecounter_out_2688 = 168,
+ dns_sizecounter_out_2704 = 169,
+ dns_sizecounter_out_2720 = 170,
+ dns_sizecounter_out_2736 = 171,
+ dns_sizecounter_out_2752 = 172,
+ dns_sizecounter_out_2768 = 173,
+ dns_sizecounter_out_2784 = 174,
+ dns_sizecounter_out_2800 = 175,
+ dns_sizecounter_out_2816 = 176,
+ dns_sizecounter_out_2832 = 177,
+ dns_sizecounter_out_2848 = 178,
+ dns_sizecounter_out_2864 = 179,
+ dns_sizecounter_out_2880 = 180,
+ dns_sizecounter_out_2896 = 181,
+ dns_sizecounter_out_2912 = 182,
+ dns_sizecounter_out_2928 = 183,
+ dns_sizecounter_out_2944 = 184,
+ dns_sizecounter_out_2960 = 185,
+ dns_sizecounter_out_2976 = 186,
+ dns_sizecounter_out_2992 = 187,
+ dns_sizecounter_out_3008 = 188,
+ dns_sizecounter_out_3024 = 189,
+ dns_sizecounter_out_3040 = 190,
+ dns_sizecounter_out_3056 = 191,
+ dns_sizecounter_out_3072 = 192,
+ dns_sizecounter_out_3088 = 193,
+ dns_sizecounter_out_3104 = 194,
+ dns_sizecounter_out_3120 = 195,
+ dns_sizecounter_out_3136 = 196,
+ dns_sizecounter_out_3152 = 197,
+ dns_sizecounter_out_3168 = 198,
+ dns_sizecounter_out_3184 = 199,
+ dns_sizecounter_out_3200 = 200,
+ dns_sizecounter_out_3216 = 201,
+ dns_sizecounter_out_3232 = 202,
+ dns_sizecounter_out_3248 = 203,
+ dns_sizecounter_out_3264 = 204,
+ dns_sizecounter_out_3280 = 205,
+ dns_sizecounter_out_3296 = 206,
+ dns_sizecounter_out_3312 = 207,
+ dns_sizecounter_out_3328 = 208,
+ dns_sizecounter_out_3344 = 209,
+ dns_sizecounter_out_3360 = 210,
+ dns_sizecounter_out_3376 = 211,
+ dns_sizecounter_out_3392 = 212,
+ dns_sizecounter_out_3408 = 213,
+ dns_sizecounter_out_3424 = 214,
+ dns_sizecounter_out_3440 = 215,
+ dns_sizecounter_out_3456 = 216,
+ dns_sizecounter_out_3472 = 217,
+ dns_sizecounter_out_3488 = 218,
+ dns_sizecounter_out_3504 = 219,
+ dns_sizecounter_out_3520 = 220,
+ dns_sizecounter_out_3536 = 221,
+ dns_sizecounter_out_3552 = 222,
+ dns_sizecounter_out_3568 = 223,
+ dns_sizecounter_out_3584 = 224,
+ dns_sizecounter_out_3600 = 225,
+ dns_sizecounter_out_3616 = 226,
+ dns_sizecounter_out_3632 = 227,
+ dns_sizecounter_out_3648 = 228,
+ dns_sizecounter_out_3664 = 229,
+ dns_sizecounter_out_3680 = 230,
+ dns_sizecounter_out_3696 = 231,
+ dns_sizecounter_out_3712 = 232,
+ dns_sizecounter_out_3728 = 233,
+ dns_sizecounter_out_3744 = 234,
+ dns_sizecounter_out_3760 = 235,
+ dns_sizecounter_out_3776 = 236,
+ dns_sizecounter_out_3792 = 237,
+ dns_sizecounter_out_3808 = 238,
+ dns_sizecounter_out_3824 = 239,
+ dns_sizecounter_out_3840 = 240,
+ dns_sizecounter_out_3856 = 241,
+ dns_sizecounter_out_3872 = 242,
+ dns_sizecounter_out_3888 = 243,
+ dns_sizecounter_out_3904 = 244,
+ dns_sizecounter_out_3920 = 245,
+ dns_sizecounter_out_3936 = 246,
+ dns_sizecounter_out_3952 = 247,
+ dns_sizecounter_out_3968 = 248,
+ dns_sizecounter_out_3984 = 249,
+ dns_sizecounter_out_4000 = 250,
+ dns_sizecounter_out_4016 = 251,
+ dns_sizecounter_out_4032 = 252,
+ dns_sizecounter_out_4048 = 253,
+ dns_sizecounter_out_4064 = 254,
+ dns_sizecounter_out_4080 = 255,
+ dns_sizecounter_out_4096 = 256,
+
+ dns_sizecounter_out_max = 257
+};
+
+void
+ns_server_create(isc_mem_t *mctx, ns_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
+ns_server_destroy(ns_server_t **serverp);
+/*%<
+ * Destroy a server object, freeing its memory.
+ */
+
+void
+ns_server_reloadwanted(ns_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
+ns_server_scan_interfaces(ns_server_t *server);
+/*%<
+ * Trigger a interface scan.
+ * Must only be called when running under server->task.
+ */
+
+void
+ns_server_flushonshutdown(ns_server_t *server, bool flush);
+/*%<
+ * Inform the server that the zones should be flushed to disk on shutdown.
+ */
+
+isc_result_t
+ns_server_reloadcommand(ns_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "reload" command from the command channel.
+ */
+
+isc_result_t
+ns_server_reconfigcommand(ns_server_t *server);
+/*%<
+ * Act on a "reconfig" command from the command channel.
+ */
+
+isc_result_t
+ns_server_notifycommand(ns_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "notify" command from the command channel.
+ */
+
+isc_result_t
+ns_server_refreshcommand(ns_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "refresh" command from the command channel.
+ */
+
+isc_result_t
+ns_server_retransfercommand(ns_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "retransfer" command from the command channel.
+ */
+
+isc_result_t
+ns_server_togglequerylog(ns_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
+ns_server_saventa(ns_server_t *server);
+
+/*%
+ * Load NTAs for all views from files.
+ */
+isc_result_t
+ns_server_loadnta(ns_server_t *server);
+
+/*%
+ * Dump the current statistics to the statistics file.
+ */
+isc_result_t
+ns_server_dumpstats(ns_server_t *server);
+
+/*%
+ * Dump the current cache to the dump file.
+ */
+isc_result_t
+ns_server_dumpdb(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Dump the current security roots to the secroots file.
+ */
+isc_result_t
+ns_server_dumpsecroots(ns_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Change or increment the server debug level.
+ */
+isc_result_t
+ns_server_setdebuglevel(ns_server_t *server, isc_lex_t *lex);
+
+/*%
+ * Flush the server's cache(s)
+ */
+isc_result_t
+ns_server_flushcache(ns_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
+ns_server_flushnode(ns_server_t *server, isc_lex_t *lex,
+ bool tree);
+
+/*%
+ * Report the server's status.
+ */
+isc_result_t
+ns_server_status(ns_server_t *server, isc_buffer_t **text);
+
+/*%
+ * Report a list of dynamic and static tsig keys, per view.
+ */
+isc_result_t
+ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text);
+
+/*%
+ * Delete a specific key (with optional view).
+ */
+isc_result_t
+ns_server_tsigdelete(ns_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Enable or disable updates for a zone.
+ */
+isc_result_t
+ns_server_freeze(ns_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
+ns_server_sync(ns_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
+ns_server_rekey(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Dump the current recursive queries.
+ */
+isc_result_t
+ns_server_dumprecursing(ns_server_t *server);
+
+/*%
+ * Maintain a list of dispatches that require reserved ports.
+ */
+void
+ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr);
+
+/*%
+ * Enable or disable dnssec validation.
+ */
+isc_result_t
+ns_server_validation(ns_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
+ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text);
+
+/*%
+ * Deletes a zone from a running process
+ */
+isc_result_t
+ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Show current configuration for a given zone
+ */
+isc_result_t
+ns_server_showzone(ns_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
+ns_server_signing(ns_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
+ns_server_zonestatus(ns_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
+ns_server_nta(ns_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
+ns_server_testgen(isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Force fefresh or print status for managed keys zones.
+ */
+isc_result_t
+ns_server_mkeys(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Close and reopen DNSTAP output file.
+ */
+isc_result_t
+ns_server_dnstap(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+#endif /* NAMED_SERVER_H */
diff --git a/bin/named/include/named/sortlist.h b/bin/named/include/named/sortlist.h
new file mode 100644
index 0000000..15bf2a6
--- /dev/null
+++ b/bin/named/include/named/sortlist.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: sortlist.h,v 1.11 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_SORTLIST_H
+#define NAMED_SORTLIST_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+/*%
+ * Type for callback functions that rank addresses.
+ */
+typedef int
+(*dns_addressorderfunc_t)(const isc_netaddr_t *address, const void *arg);
+
+/*%
+ * Return value type for setup_sortlist.
+ */
+typedef enum {
+ NS_SORTLISTTYPE_NONE,
+ NS_SORTLISTTYPE_1ELEMENT,
+ NS_SORTLISTTYPE_2ELEMENT
+} ns_sortlisttype_t;
+
+ns_sortlisttype_t
+ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
+ const void **argp);
+/*%<
+ * Find the sortlist statement in 'acl' that applies to 'clientaddr', if any.
+ *
+ * If a 1-element sortlist item applies, return NS_SORTLISTTYPE_1ELEMENT and
+ * make '*argp' point to the matching subelement.
+ *
+ * If a 2-element sortlist item applies, return NS_SORTLISTTYPE_2ELEMENT and
+ * make '*argp' point to ACL that forms the second element.
+ *
+ * If no sortlist item applies, return NS_SORTLISTTYPE_NONE and set '*argp'
+ * to NULL.
+ */
+
+int
+ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg);
+/*%<
+ * Find the sort order of 'addr' in 'arg', the matching element
+ * of a 1-element top-level sortlist statement.
+ */
+
+int
+ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg);
+/*%<
+ * Find the sort order of 'addr' in 'arg', a topology-like
+ * ACL forming the second element in a 2-element top-level
+ * sortlist statement.
+ */
+
+void
+ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr,
+ dns_addressorderfunc_t *orderp,
+ const void **argp);
+/*%<
+ * Find the sortlist statement in 'acl' that applies to 'clientaddr', if any.
+ * If a sortlist statement applies, return in '*orderp' a pointer to a function
+ * for ranking network addresses based on that sortlist statement, and in
+ * '*argp' an argument to pass to said function. If no sortlist statement
+ * applies, set '*orderp' and '*argp' to NULL.
+ */
+
+#endif /* NAMED_SORTLIST_H */
diff --git a/bin/named/include/named/statschannel.h b/bin/named/include/named/statschannel.h
new file mode 100644
index 0000000..95f71b3
--- /dev/null
+++ b/bin/named/include/named/statschannel.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: statschannel.h,v 1.3 2008/04/03 05:55:51 marka Exp $ */
+
+#ifndef NAMED_STATSCHANNEL_H
+#define NAMED_STATSCHANNEL_H 1
+
+/*! \file
+ * \brief
+ * The statistics channels built-in the name server.
+ */
+
+#include <isccc/types.h>
+
+#include <isccfg/aclconf.h>
+
+#include <named/types.h>
+
+#define NS_STATSCHANNEL_HTTPPORT 80
+
+isc_result_t
+ns_statschannels_configure(ns_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
+ns_statschannels_shutdown(ns_server_t *server);
+/*%<
+ * Initiate shutdown of all the statistics channel listeners.
+ */
+
+isc_result_t
+ns_stats_dump(ns_server_t *server, FILE *fp);
+/*%<
+ * Dump statistics counters managed by the server to the file fp.
+ */
+
+#endif /* NAMED_STATSCHANNEL_H */
diff --git a/bin/named/include/named/tkeyconf.h b/bin/named/include/named/tkeyconf.h
new file mode 100644
index 0000000..5370913
--- /dev/null
+++ b/bin/named/include/named/tkeyconf.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: tkeyconf.h,v 1.16 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NS_TKEYCONF_H
+#define NS_TKEYCONF_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
+ isc_entropy_t *ectx, 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 'ectx' is not NULL
+ *\li 'tctx' is not NULL
+ *\li '*tctx' is NULL
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* NS_TKEYCONF_H */
diff --git a/bin/named/include/named/tsigconf.h b/bin/named/include/named/tsigconf.h
new file mode 100644
index 0000000..0bdd02b
--- /dev/null
+++ b/bin/named/include/named/tsigconf.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: tsigconf.h,v 1.18 2009/06/11 23:47:55 tbox Exp $ */
+
+#ifndef NS_TSIGCONF_H
+#define NS_TSIGCONF_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+ns_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
+
+#endif /* NS_TSIGCONF_H */
diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h
new file mode 100644
index 0000000..486ec31
--- /dev/null
+++ b/bin/named/include/named/types.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NAMED_TYPES_H
+#define NAMED_TYPES_H 1
+
+/*! \file */
+
+#include <dns/types.h>
+
+typedef struct ns_cache ns_cache_t;
+typedef ISC_LIST(ns_cache_t) ns_cachelist_t;
+typedef struct ns_client ns_client_t;
+typedef struct ns_clientmgr ns_clientmgr_t;
+typedef struct ns_query ns_query_t;
+typedef struct ns_server ns_server_t;
+typedef struct ns_xmld ns_xmld_t;
+typedef struct ns_xmldmgr ns_xmldmgr_t;
+typedef struct ns_interface ns_interface_t;
+typedef struct ns_interfacemgr ns_interfacemgr_t;
+typedef struct ns_lwresd ns_lwresd_t;
+typedef struct ns_lwreslistener ns_lwreslistener_t;
+typedef struct ns_lwdclient ns_lwdclient_t;
+typedef struct ns_lwdclientmgr ns_lwdclientmgr_t;
+typedef struct ns_lwsearchlist ns_lwsearchlist_t;
+typedef struct ns_lwsearchctx ns_lwsearchctx_t;
+typedef struct ns_controls ns_controls_t;
+typedef struct ns_dispatch ns_dispatch_t;
+typedef ISC_LIST(ns_dispatch_t) ns_dispatchlist_t;
+typedef struct ns_statschannel ns_statschannel_t;
+typedef ISC_LIST(ns_statschannel_t) ns_statschannellist_t;
+typedef struct ns_altsecret ns_altsecret_t;
+typedef ISC_LIST(ns_altsecret_t) ns_altsecretlist_t;
+
+typedef enum {
+ ns_cookiealg_aes,
+ ns_cookiealg_sha1,
+ ns_cookiealg_sha256
+} ns_cookiealg_t;
+
+#endif /* NAMED_TYPES_H */
diff --git a/bin/named/include/named/update.h b/bin/named/include/named/update.h
new file mode 100644
index 0000000..3ee6623
--- /dev/null
+++ b/bin/named/include/named/update.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: update.h,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_UPDATE_H
+#define NAMED_UPDATE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * RFC2136 Dynamic Update
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <dns/types.h>
+#include <dns/result.h>
+
+/***
+ *** Types.
+ ***/
+
+/***
+ *** Functions
+ ***/
+
+void
+ns_update_start(ns_client_t *client, isc_result_t sigresult);
+
+#endif /* NAMED_UPDATE_H */
diff --git a/bin/named/include/named/xfrout.h b/bin/named/include/named/xfrout.h
new file mode 100644
index 0000000..41c7f27
--- /dev/null
+++ b/bin/named/include/named/xfrout.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: xfrout.h,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_XFROUT_H
+#define NAMED_XFROUT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * Outgoing zone transfers (AXFR + IXFR).
+ */
+
+/***
+ *** Functions
+ ***/
+
+void
+ns_xfr_start(ns_client_t *client, dns_rdatatype_t xfrtype);
+
+#endif /* NAMED_XFROUT_H */
diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h
new file mode 100644
index 0000000..5e016f7
--- /dev/null
+++ b/bin/named/include/named/zoneconf.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: zoneconf.h,v 1.30 2011/08/30 23:46:51 tbox Exp $ */
+
+#ifndef NS_ZONECONF_H
+#define NS_ZONECONF_H 1
+
+/*! \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
+ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
+ dns_zone_t *zone, dns_zone_t *raw);
+/*%<
+ * Configure or reconfigure a zone according to the named.conf
+ * data in 'cctx' and 'czone'.
+ *
+ * The zone origin is not configured, it is assumed to have been set
+ * at zone creation time.
+ *
+ * Require:
+ * \li 'lctx' to be initialized or NULL.
+ * \li 'cctx' to be initialized or NULL.
+ * \li 'ac' to point to an initialized ns_aclconfctx_t.
+ * \li 'czone' to be initialized.
+ * \li 'zone' to be initialized.
+ */
+
+bool
+ns_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.
+ */
+
+isc_result_t
+ns_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
+
+#endif /* NS_ZONECONF_H */
diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c
new file mode 100644
index 0000000..419927b
--- /dev/null
+++ b/bin/named/interfacemgr.c
@@ -0,0 +1,1246 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/os.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/dispatch.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/interfacemgr.h>
+#include <named/server.h>
+
+#ifdef HAVE_NET_ROUTE_H
+#include <net/route.h>
+#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
+#define USE_ROUTE_SOCKET 1
+#define ROUTE_SOCKET_PROTOCOL PF_ROUTE
+#define MSGHDR rt_msghdr
+#define MSGTYPE rtm_type
+#endif
+#endif
+
+#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
+#define USE_ROUTE_SOCKET 1
+#define ROUTE_SOCKET_PROTOCOL PF_NETLINK
+#define MSGHDR nlmsghdr
+#define MSGTYPE nlmsg_type
+#endif
+#endif
+
+#ifdef TUNE_LARGE
+#define UDPBUFFERS 32768
+#else
+#define UDPBUFFERS 1000
+#endif /* TUNE_LARGE */
+
+#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
+#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
+
+#define IFMGR_COMMON_LOGARGS \
+ ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
+
+/*% nameserver interface manager structure */
+struct ns_interfacemgr {
+ unsigned int magic; /*%< Magic number. */
+ int references;
+ isc_mutex_t lock;
+ isc_mem_t * mctx; /*%< Memory context. */
+ isc_taskmgr_t * taskmgr; /*%< Task manager. */
+ isc_socketmgr_t * socketmgr; /*%< Socket manager. */
+ dns_dispatchmgr_t * dispatchmgr;
+ unsigned int generation; /*%< Current generation no. */
+ ns_listenlist_t * listenon4;
+ ns_listenlist_t * listenon6;
+ dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
+ ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
+ ISC_LIST(isc_sockaddr_t) listenon;
+#ifdef USE_ROUTE_SOCKET
+ isc_task_t * task;
+ isc_socket_t * route;
+ unsigned char buf[2048];
+#endif
+};
+
+static void
+purge_old_interfaces(ns_interfacemgr_t *mgr);
+
+static void
+clearlistenon(ns_interfacemgr_t *mgr);
+
+#ifdef USE_ROUTE_SOCKET
+static void
+route_event(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = NULL;
+ ns_interfacemgr_t *mgr = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ struct MSGHDR *rtm;
+ bool done = true;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ mgr = event->ev_arg;
+ sevent = (isc_socketevent_t *)event;
+
+ if (sevent->result != ISC_R_SUCCESS) {
+ if (sevent->result != ISC_R_CANCELED)
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "automatic interface scanning "
+ "terminated: %s",
+ isc_result_totext(sevent->result));
+ ns_interfacemgr_detach(&mgr);
+ isc_event_free(&event);
+ return;
+ }
+
+ rtm = (struct MSGHDR *)mgr->buf;
+#ifdef RTM_VERSION
+ if (rtm->rtm_version != RTM_VERSION) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "automatic interface rescanning disabled: "
+ "rtm->rtm_version mismatch (%u != %u) "
+ "recompile required", rtm->rtm_version,
+ RTM_VERSION);
+ ns_interfacemgr_detach(&mgr);
+ isc_event_free(&event);
+ return;
+ }
+#endif
+
+ switch (rtm->MSGTYPE) {
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ if (mgr->route != NULL && ns_g_server->interface_auto)
+ ns_server_scan_interfaces(ns_g_server);
+ break;
+ default:
+ break;
+ }
+
+ LOCK(&mgr->lock);
+ if (mgr->route != NULL) {
+ /*
+ * Look for next route event.
+ */
+ r.base = mgr->buf;
+ r.length = sizeof(mgr->buf);
+ result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
+ route_event, mgr);
+ if (result == ISC_R_SUCCESS)
+ done = false;
+ }
+ UNLOCK(&mgr->lock);
+
+ if (done)
+ ns_interfacemgr_detach(&mgr);
+ isc_event_free(&event);
+ return;
+}
+#endif
+
+isc_result_t
+ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr,
+ dns_dispatchmgr_t *dispatchmgr,
+ isc_task_t *task, ns_interfacemgr_t **mgrp)
+{
+ isc_result_t result;
+ ns_interfacemgr_t *mgr;
+
+#ifndef USE_ROUTE_SOCKET
+ UNUSED(task);
+#endif
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(mgrp != NULL);
+ REQUIRE(*mgrp == NULL);
+
+ mgr = isc_mem_get(mctx, sizeof(*mgr));
+ if (mgr == NULL)
+ return (ISC_R_NOMEMORY);
+
+ mgr->mctx = NULL;
+ isc_mem_attach(mctx, &mgr->mctx);
+
+ result = isc_mutex_init(&mgr->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mem;
+
+ mgr->taskmgr = taskmgr;
+ mgr->socketmgr = socketmgr;
+ mgr->dispatchmgr = dispatchmgr;
+ mgr->generation = 1;
+ mgr->listenon4 = NULL;
+ mgr->listenon6 = NULL;
+
+ ISC_LIST_INIT(mgr->interfaces);
+ ISC_LIST_INIT(mgr->listenon);
+
+ /*
+ * The listen-on lists are initially empty.
+ */
+ result = ns_listenlist_create(mctx, &mgr->listenon4);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mem;
+ ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
+
+ result = dns_aclenv_init(mctx, &mgr->aclenv);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_listenon;
+#ifdef HAVE_GEOIP
+ mgr->aclenv.geoip = ns_g_geoip;
+#endif
+
+#ifdef USE_ROUTE_SOCKET
+ mgr->route = NULL;
+ result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
+ isc_sockettype_raw, &mgr->route);
+ switch (result) {
+ case ISC_R_NOPERM:
+ case ISC_R_SUCCESS:
+ case ISC_R_NOTIMPLEMENTED:
+ case ISC_R_FAMILYNOSUPPORT:
+ break;
+ default:
+ goto cleanup_aclenv;
+ }
+
+ mgr->task = NULL;
+ if (mgr->route != NULL)
+ isc_task_attach(task, &mgr->task);
+ mgr->references = (mgr->route != NULL) ? 2 : 1;
+#else
+ mgr->references = 1;
+#endif
+ mgr->magic = IFMGR_MAGIC;
+ *mgrp = mgr;
+
+#ifdef USE_ROUTE_SOCKET
+ if (mgr->route != NULL) {
+ isc_region_t r = { mgr->buf, sizeof(mgr->buf) };
+
+ result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
+ route_event, mgr);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_detach(&mgr->task);
+ isc_socket_detach(&mgr->route);
+ ns_interfacemgr_detach(&mgr);
+ }
+ }
+#endif
+ return (ISC_R_SUCCESS);
+
+#ifdef USE_ROUTE_SOCKET
+ cleanup_aclenv:
+ dns_aclenv_destroy(&mgr->aclenv);
+#endif
+ cleanup_listenon:
+ ns_listenlist_detach(&mgr->listenon4);
+ ns_listenlist_detach(&mgr->listenon6);
+ cleanup_mem:
+ isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
+ return (result);
+}
+
+static void
+ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+#ifdef USE_ROUTE_SOCKET
+ if (mgr->route != NULL)
+ isc_socket_detach(&mgr->route);
+ if (mgr->task != NULL)
+ isc_task_detach(&mgr->task);
+#endif
+ dns_aclenv_destroy(&mgr->aclenv);
+ ns_listenlist_detach(&mgr->listenon4);
+ ns_listenlist_detach(&mgr->listenon6);
+ clearlistenon(mgr);
+ DESTROYLOCK(&mgr->lock);
+ mgr->magic = 0;
+ isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
+}
+
+dns_aclenv_t *
+ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
+ return (&mgr->aclenv);
+}
+
+void
+ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
+ REQUIRE(NS_INTERFACEMGR_VALID(source));
+ LOCK(&source->lock);
+ INSIST(source->references > 0);
+ source->references++;
+ UNLOCK(&source->lock);
+ *target = source;
+}
+
+void
+ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
+ isc_result_t need_destroy = false;
+ ns_interfacemgr_t *target = *targetp;
+ REQUIRE(target != NULL);
+ REQUIRE(NS_INTERFACEMGR_VALID(target));
+ LOCK(&target->lock);
+ REQUIRE(target->references > 0);
+ target->references--;
+ if (target->references == 0)
+ need_destroy = true;
+ UNLOCK(&target->lock);
+ if (need_destroy)
+ ns_interfacemgr_destroy(target);
+ *targetp = NULL;
+}
+
+void
+ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+ /*%
+ * Shut down and detach all interfaces.
+ * By incrementing the generation count, we make purge_old_interfaces()
+ * consider all interfaces "old".
+ */
+ mgr->generation++;
+#ifdef USE_ROUTE_SOCKET
+ LOCK(&mgr->lock);
+ if (mgr->route != NULL) {
+ isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
+ isc_socket_detach(&mgr->route);
+ isc_task_detach(&mgr->task);
+ }
+ UNLOCK(&mgr->lock);
+#endif
+ purge_old_interfaces(mgr);
+}
+
+
+static isc_result_t
+ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
+ const char *name, ns_interface_t **ifpret)
+{
+ ns_interface_t *ifp;
+ isc_result_t result;
+ int disp;
+
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+ ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
+ if (ifp == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ifp->mgr = NULL;
+ ifp->generation = mgr->generation;
+ ifp->addr = *addr;
+ ifp->flags = 0;
+ strlcpy(ifp->name, name, sizeof(ifp->name));
+ ifp->clientmgr = NULL;
+
+ result = isc_mutex_init(&ifp->lock);
+ if (result != ISC_R_SUCCESS)
+ goto lock_create_failure;
+
+ result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
+ ns_g_timermgr,
+ &ifp->clientmgr);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "ns_clientmgr_create() failed: %s",
+ isc_result_totext(result));
+ goto clientmgr_create_failure;
+ }
+
+ for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
+ ifp->udpdispatch[disp] = NULL;
+
+ ifp->tcpsocket = NULL;
+
+ /*
+ * Create a single TCP client object. It will replace itself
+ * with a new one as soon as it gets a connection, so the actual
+ * connections will be handled in parallel even though there is
+ * only one client initially.
+ */
+ ifp->ntcptarget = 1;
+ ifp->ntcpcurrent = 0;
+ ifp->nudpdispatch = 0;
+
+ ifp->dscp = -1;
+
+ ISC_LINK_INIT(ifp, link);
+
+ ns_interfacemgr_attach(mgr, &ifp->mgr);
+ ISC_LIST_APPEND(mgr->interfaces, ifp, link);
+
+ ifp->references = 1;
+ ifp->magic = IFACE_MAGIC;
+ *ifpret = ifp;
+
+ return (ISC_R_SUCCESS);
+
+ clientmgr_create_failure:
+ DESTROYLOCK(&ifp->lock);
+
+ lock_create_failure:
+ ifp->magic = 0;
+ isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
+
+ return (ISC_R_UNEXPECTED);
+}
+
+static isc_result_t
+ns_interface_listenudp(ns_interface_t *ifp) {
+ isc_result_t result;
+ unsigned int attrs;
+ unsigned int attrmask;
+ int disp, i;
+
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ else
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ attrs |= DNS_DISPATCHATTR_NOLISTEN;
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
+
+ ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
+ for (disp = 0; disp < ifp->nudpdispatch; disp++) {
+ result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
+ ns_g_socketmgr,
+ ns_g_taskmgr, &ifp->addr,
+ 4096, UDPBUFFERS,
+ 32768, 8219, 8237,
+ attrs, attrmask,
+ &ifp->udpdispatch[disp],
+ disp == 0
+ ? NULL
+ : ifp->udpdispatch[0]);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "could not listen on UDP socket: %s",
+ isc_result_totext(result));
+ goto udp_dispatch_failure;
+ }
+
+ }
+
+ result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch,
+ ifp, false);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "UDP ns_clientmgr_createclients(): %s",
+ isc_result_totext(result));
+ goto addtodispatch_failure;
+ }
+
+ return (ISC_R_SUCCESS);
+
+ addtodispatch_failure:
+ for (i = disp - 1; i >= 0; i--) {
+ dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
+ DNS_DISPATCHATTR_NOLISTEN);
+ dns_dispatch_detach(&(ifp->udpdispatch[i]));
+ }
+ ifp->nudpdispatch = 0;
+
+ udp_dispatch_failure:
+ return (result);
+}
+
+static isc_result_t
+ns_interface_accepttcp(ns_interface_t *ifp) {
+ isc_result_t result;
+
+ /*
+ * Open a TCP socket.
+ */
+ result = isc_socket_create(ifp->mgr->socketmgr,
+ isc_sockaddr_pf(&ifp->addr),
+ isc_sockettype_tcp,
+ &ifp->tcpsocket);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "creating TCP socket: %s",
+ isc_result_totext(result));
+ goto tcp_socket_failure;
+ }
+ isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
+#ifndef ISC_ALLOW_MAPPED
+ isc_socket_ipv6only(ifp->tcpsocket, true);
+#endif
+ result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
+ ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "binding TCP socket: %s",
+ isc_result_totext(result));
+ goto tcp_bind_failure;
+ }
+
+ if (ifp->dscp != -1)
+ isc_socket_dscp(ifp->tcpsocket, ifp->dscp);
+
+ result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "listening on TCP socket: %s",
+ isc_result_totext(result));
+ goto tcp_listen_failure;
+ }
+
+ /*
+ * If/when there a multiple filters listen to the
+ * result.
+ */
+ (void)isc_socket_filter(ifp->tcpsocket, "dataready");
+
+ result = ns_clientmgr_createclients(ifp->clientmgr,
+ ifp->ntcptarget, ifp,
+ true);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "TCP ns_clientmgr_createclients(): %s",
+ isc_result_totext(result));
+ goto accepttcp_failure;
+ }
+ return (ISC_R_SUCCESS);
+
+ accepttcp_failure:
+ tcp_listen_failure:
+ tcp_bind_failure:
+ isc_socket_detach(&ifp->tcpsocket);
+ tcp_socket_failure:
+ return (result);
+}
+
+static isc_result_t
+ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
+ const char *name, ns_interface_t **ifpret,
+ bool accept_tcp, isc_dscp_t dscp,
+ bool *addr_in_use)
+{
+ isc_result_t result;
+ ns_interface_t *ifp = NULL;
+ REQUIRE(ifpret != NULL && *ifpret == NULL);
+ REQUIRE(addr_in_use == NULL || *addr_in_use == false);
+
+ result = ns_interface_create(mgr, addr, name, &ifp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ ifp->dscp = dscp;
+
+ result = ns_interface_listenudp(ifp);
+ if (result != ISC_R_SUCCESS) {
+ if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL))
+ *addr_in_use = true;
+ goto cleanup_interface;
+ }
+
+ if (!ns_g_notcp && accept_tcp == true) {
+ result = ns_interface_accepttcp(ifp);
+ if (result != ISC_R_SUCCESS) {
+ if ((result == ISC_R_ADDRINUSE) &&
+ (addr_in_use != NULL))
+ *addr_in_use = true;
+
+ /*
+ * XXXRTH We don't currently have a way to easily stop
+ * dispatch service, so we currently return
+ * ISC_R_SUCCESS (the UDP stuff will work even if TCP
+ * creation failed). This will be fixed later.
+ */
+ result = ISC_R_SUCCESS;
+ }
+ }
+ *ifpret = ifp;
+ return (result);
+
+ cleanup_interface:
+ ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
+ ns_interface_detach(&ifp);
+ return (result);
+}
+
+void
+ns_interface_shutdown(ns_interface_t *ifp) {
+ if (ifp->clientmgr != NULL)
+ ns_clientmgr_destroy(&ifp->clientmgr);
+}
+
+static void
+ns_interface_destroy(ns_interface_t *ifp) {
+ isc_mem_t *mctx = ifp->mgr->mctx;
+ int disp;
+
+ REQUIRE(NS_INTERFACE_VALID(ifp));
+
+ ns_interface_shutdown(ifp);
+
+ for (disp = 0; disp < ifp->nudpdispatch; disp++)
+ if (ifp->udpdispatch[disp] != NULL) {
+ dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0,
+ DNS_DISPATCHATTR_NOLISTEN);
+ dns_dispatch_detach(&(ifp->udpdispatch[disp]));
+ }
+
+ if (ifp->tcpsocket != NULL)
+ isc_socket_detach(&ifp->tcpsocket);
+
+ DESTROYLOCK(&ifp->lock);
+
+ ns_interfacemgr_detach(&ifp->mgr);
+
+ ifp->magic = 0;
+ isc_mem_put(mctx, ifp, sizeof(*ifp));
+}
+
+void
+ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
+ REQUIRE(NS_INTERFACE_VALID(source));
+ LOCK(&source->lock);
+ INSIST(source->references > 0);
+ source->references++;
+ UNLOCK(&source->lock);
+ *target = source;
+}
+
+void
+ns_interface_detach(ns_interface_t **targetp) {
+ isc_result_t need_destroy = false;
+ ns_interface_t *target = *targetp;
+ REQUIRE(target != NULL);
+ REQUIRE(NS_INTERFACE_VALID(target));
+ LOCK(&target->lock);
+ REQUIRE(target->references > 0);
+ target->references--;
+ if (target->references == 0)
+ need_destroy = true;
+ UNLOCK(&target->lock);
+ if (need_destroy)
+ ns_interface_destroy(target);
+ *targetp = NULL;
+}
+
+/*%
+ * Search the interface list for an interface whose address and port
+ * both match those of 'addr'. Return a pointer to it, or NULL if not found.
+ */
+static ns_interface_t *
+find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
+ ns_interface_t *ifp;
+ for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
+ ifp = ISC_LIST_NEXT(ifp, link)) {
+ if (isc_sockaddr_equal(&ifp->addr, addr))
+ break;
+ }
+ return (ifp);
+}
+
+/*%
+ * Remove any interfaces whose generation number is not the current one.
+ */
+static void
+purge_old_interfaces(ns_interfacemgr_t *mgr) {
+ ns_interface_t *ifp, *next;
+ for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
+ INSIST(NS_INTERFACE_VALID(ifp));
+ next = ISC_LIST_NEXT(ifp, link);
+ if (ifp->generation != mgr->generation) {
+ char sabuf[256];
+ ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
+ isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "no longer listening on %s", sabuf);
+ ns_interface_shutdown(ifp);
+ ns_interface_detach(&ifp);
+ }
+ }
+}
+
+static isc_result_t
+clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
+ dns_acl_t *newacl = NULL;
+ isc_result_t result;
+ result = dns_acl_create(mctx, 0, &newacl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_acl_detach(aclp);
+ dns_acl_attach(newacl, aclp);
+ dns_acl_detach(&newacl);
+ return (ISC_R_SUCCESS);
+}
+
+static bool
+listenon_is_ip6_any(ns_listenelt_t *elt) {
+ REQUIRE(elt && elt->acl);
+ return dns_acl_isany(elt->acl);
+}
+
+static isc_result_t
+setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
+ isc_result_t result;
+ unsigned int prefixlen;
+ isc_netaddr_t *netaddr;
+
+ netaddr = &interface->address;
+
+ /* First add localhost address */
+ prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
+ result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
+ netaddr, prefixlen, true);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Then add localnets prefix */
+ result = isc_netaddr_masktoprefixlen(&interface->netmask,
+ &prefixlen);
+
+ /* Non contiguous netmasks not allowed by IPv6 arch. */
+ if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
+ return (result);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
+ "omitting IPv4 interface %s from "
+ "localnets ACL: %s", interface->name,
+ isc_result_totext(result));
+ return (ISC_R_SUCCESS);
+ }
+
+ if (prefixlen == 0U) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
+ "omitting %s interface %s from localnets ACL: "
+ "zero prefix length detected",
+ (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
+ interface->name);
+ return (ISC_R_SUCCESS);
+ }
+
+ result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
+ netaddr, prefixlen, true);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
+ in_port_t port)
+{
+ isc_sockaddr_t *addr;
+ isc_sockaddr_t *old;
+
+ addr = isc_mem_get(mgr->mctx, sizeof(*addr));
+ if (addr == NULL)
+ return;
+
+ isc_sockaddr_fromnetaddr(addr, &interface->address, port);
+
+ for (old = ISC_LIST_HEAD(mgr->listenon);
+ old != NULL;
+ old = ISC_LIST_NEXT(old, link))
+ if (isc_sockaddr_equal(addr, old))
+ break;
+
+ if (old != NULL)
+ isc_mem_put(mgr->mctx, addr, sizeof(*addr));
+ else
+ ISC_LIST_APPEND(mgr->listenon, addr, link);
+}
+
+static void
+clearlistenon(ns_interfacemgr_t *mgr) {
+ isc_sockaddr_t *old;
+
+ old = ISC_LIST_HEAD(mgr->listenon);
+ while (old != NULL) {
+ ISC_LIST_UNLINK(mgr->listenon, old, link);
+ isc_mem_put(mgr->mctx, old, sizeof(*old));
+ old = ISC_LIST_HEAD(mgr->listenon);
+ }
+}
+
+static isc_result_t
+do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
+ bool verbose)
+{
+ isc_interfaceiter_t *iter = NULL;
+ bool scan_ipv4 = false;
+ bool scan_ipv6 = false;
+ bool adjusting = false;
+ bool ipv6only = true;
+ bool ipv6pktinfo = true;
+ isc_result_t result;
+ isc_netaddr_t zero_address, zero_address6;
+ ns_listenelt_t *le;
+ isc_sockaddr_t listen_addr;
+ ns_interface_t *ifp;
+ bool log_explicit = false;
+ bool dolistenon;
+ char sabuf[ISC_SOCKADDR_FORMATSIZE];
+ bool tried_listening;
+ bool all_addresses_in_use;
+
+ if (ext_listen != NULL)
+ adjusting = true;
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ scan_ipv6 = true;
+#ifdef WANT_IPV6
+ else if (!ns_g_disable6)
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
+ "no IPv6 interfaces found");
+#endif
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS)
+ scan_ipv4 = true;
+ else if (!ns_g_disable4)
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
+ "no IPv4 interfaces found");
+
+ /*
+ * A special, but typical case; listen-on-v6 { any; }.
+ * When we can make the socket IPv6-only, open a single wildcard
+ * socket for IPv6 communication. Otherwise, make separate socket
+ * for each IPv6 address in order to avoid accepting IPv4 packets
+ * as the form of mapped addresses unintentionally unless explicitly
+ * allowed.
+ */
+#ifndef ISC_ALLOW_MAPPED
+ if (scan_ipv6 == true &&
+ isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
+ ipv6only = false;
+ log_explicit = true;
+ }
+#endif
+ if (scan_ipv6 == true &&
+ isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
+ ipv6pktinfo = false;
+ log_explicit = true;
+ }
+ if (scan_ipv6 == true && ipv6only && ipv6pktinfo) {
+ for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
+ le != NULL;
+ le = ISC_LIST_NEXT(le, link)) {
+ struct in6_addr in6a;
+
+ if (!listenon_is_ip6_any(le))
+ continue;
+
+ in6a = in6addr_any;
+ isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
+
+ ifp = find_matching_interface(mgr, &listen_addr);
+ if (ifp != NULL) {
+ ifp->generation = mgr->generation;
+ if (le->dscp != -1 && ifp->dscp == -1)
+ ifp->dscp = le->dscp;
+ else if (le->dscp != ifp->dscp) {
+ isc_sockaddr_format(&listen_addr,
+ sabuf,
+ sizeof(sabuf));
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_WARNING,
+ "%s: conflicting DSCP "
+ "values, using %d",
+ sabuf, ifp->dscp);
+ }
+ } else {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "listening on IPv6 "
+ "interfaces, port %u",
+ le->port);
+ result = ns_interface_setup(mgr, &listen_addr,
+ "<any>", &ifp,
+ true,
+ le->dscp,
+ NULL);
+ if (result == ISC_R_SUCCESS)
+ ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
+ else
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_ERROR,
+ "listening on all IPv6 "
+ "interfaces failed");
+ /* Continue. */
+ }
+ }
+ }
+
+ isc_netaddr_any(&zero_address);
+ isc_netaddr_any6(&zero_address6);
+
+ result = isc_interfaceiter_create(mgr->mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (adjusting == false) {
+ result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iter;
+ result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iter;
+ clearlistenon(mgr);
+ }
+
+ tried_listening = false;
+ all_addresses_in_use = true;
+ for (result = isc_interfaceiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = isc_interfaceiter_next(iter))
+ {
+ isc_interface_t interface;
+ ns_listenlist_t *ll;
+ unsigned int family;
+
+ result = isc_interfaceiter_current(iter, &interface);
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ family = interface.address.family;
+ if (family != AF_INET && family != AF_INET6)
+ continue;
+ if (scan_ipv4 == false && family == AF_INET)
+ continue;
+ if (scan_ipv6 == false && family == AF_INET6)
+ continue;
+
+ /*
+ * Test for the address being nonzero rather than testing
+ * INTERFACE_F_UP, because on some systems the latter
+ * follows the media state and we could end up ignoring
+ * the interface for an entire rescan interval due to
+ * a temporary media glitch at rescan time.
+ */
+ if (family == AF_INET &&
+ isc_netaddr_equal(&interface.address, &zero_address)) {
+ continue;
+ }
+ if (family == AF_INET6 &&
+ isc_netaddr_equal(&interface.address, &zero_address6)) {
+ continue;
+ }
+
+ if (adjusting == false) {
+ /*
+ * If running with -T fixedlocal, then we only
+ * want 127.0.0.1 and ::1 in the localhost ACL.
+ */
+ if (ns_g_fixedlocal &&
+ !isc_netaddr_isloopback(&interface.address))
+ {
+ goto listenon;
+ }
+
+ result = setup_locals(mgr, &interface);
+ if (result != ISC_R_SUCCESS)
+ goto ignore_interface;
+ }
+
+ listenon:
+ ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
+ dolistenon = true;
+ for (le = ISC_LIST_HEAD(ll->elts);
+ le != NULL;
+ le = ISC_LIST_NEXT(le, link))
+ {
+ int match;
+ bool ipv6_wildcard = false;
+ isc_netaddr_t listen_netaddr;
+ isc_sockaddr_t listen_sockaddr;
+
+ /*
+ * Construct a socket address for this IP/port
+ * combination.
+ */
+ if (family == AF_INET) {
+ isc_netaddr_fromin(&listen_netaddr,
+ &interface.address.type.in);
+ } else {
+ isc_netaddr_fromin6(&listen_netaddr,
+ &interface.address.type.in6);
+ isc_netaddr_setzone(&listen_netaddr,
+ interface.address.zone);
+ }
+ isc_sockaddr_fromnetaddr(&listen_sockaddr,
+ &listen_netaddr,
+ le->port);
+
+ /*
+ * See if the address matches the listen-on statement;
+ * if not, ignore the interface.
+ */
+ (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
+ &mgr->aclenv, &match, NULL);
+ if (match <= 0)
+ continue;
+
+ if (adjusting == false && dolistenon == true) {
+ setup_listenon(mgr, &interface, le->port);
+ dolistenon = false;
+ }
+
+ /*
+ * The case of "any" IPv6 address will require
+ * special considerations later, so remember it.
+ */
+ if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
+ listenon_is_ip6_any(le))
+ ipv6_wildcard = true;
+
+ /*
+ * When adjusting interfaces with extra a listening
+ * list, see if the address matches the extra list.
+ * If it does, and is also covered by a wildcard
+ * interface, we need to listen on the address
+ * explicitly.
+ */
+ if (adjusting == true) {
+ ns_listenelt_t *ele;
+
+ match = 0;
+ for (ele = ISC_LIST_HEAD(ext_listen->elts);
+ ele != NULL;
+ ele = ISC_LIST_NEXT(ele, link)) {
+ (void)dns_acl_match(&listen_netaddr,
+ NULL, ele->acl,
+ NULL, &match, NULL);
+ if (match > 0 &&
+ (ele->port == le->port ||
+ ele->port == 0))
+ break;
+ else
+ match = 0;
+ }
+ if (ipv6_wildcard == true && match == 0)
+ continue;
+ }
+
+ ifp = find_matching_interface(mgr, &listen_sockaddr);
+ if (ifp != NULL) {
+ ifp->generation = mgr->generation;
+ if (le->dscp != -1 && ifp->dscp == -1)
+ ifp->dscp = le->dscp;
+ else if (le->dscp != ifp->dscp) {
+ isc_sockaddr_format(&listen_sockaddr,
+ sabuf,
+ sizeof(sabuf));
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_WARNING,
+ "%s: conflicting DSCP "
+ "values, using %d",
+ sabuf, ifp->dscp);
+ }
+ } else {
+ bool addr_in_use = false;
+
+ if (adjusting == false &&
+ ipv6_wildcard == true)
+ continue;
+
+ if (log_explicit && family == AF_INET6 &&
+ !adjusting && listenon_is_ip6_any(le)) {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO :
+ ISC_LOG_DEBUG(1),
+ "IPv6 socket API is "
+ "incomplete; explicitly "
+ "binding to each IPv6 "
+ "address separately");
+ log_explicit = false;
+ }
+ isc_sockaddr_format(&listen_sockaddr,
+ sabuf, sizeof(sabuf));
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "%s"
+ "listening on %s interface "
+ "%s, %s",
+ (adjusting == true) ?
+ "additionally " : "",
+ (family == AF_INET) ?
+ "IPv4" : "IPv6",
+ interface.name, sabuf);
+
+ result = ns_interface_setup(mgr,
+ &listen_sockaddr,
+ interface.name,
+ &ifp,
+ (adjusting == true) ?
+ false : true,
+ le->dscp,
+ &addr_in_use);
+
+ tried_listening = true;
+ if (!addr_in_use)
+ all_addresses_in_use = false;
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_ERROR,
+ "creating %s interface "
+ "%s failed; interface "
+ "ignored",
+ (family == AF_INET) ?
+ "IPv4" : "IPv6",
+ interface.name);
+ }
+ /* Continue. */
+ }
+
+ }
+ continue;
+
+ ignore_interface:
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_ERROR,
+ "ignoring %s interface %s: %s",
+ (family == AF_INET) ? "IPv4" : "IPv6",
+ interface.name, isc_result_totext(result));
+ continue;
+ }
+ if (result != ISC_R_NOMORE)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "interface iteration failed: %s",
+ isc_result_totext(result));
+ else
+ result = ((tried_listening && all_addresses_in_use) ?
+ ISC_R_ADDRINUSE : ISC_R_SUCCESS);
+ cleanup_iter:
+ isc_interfaceiter_destroy(&iter);
+ return (result);
+}
+
+static isc_result_t
+ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
+ bool verbose)
+{
+ isc_result_t result;
+ bool purge = true;
+
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+ mgr->generation++; /* Increment the generation count. */
+
+ result = do_scan(mgr, ext_listen, verbose);
+ if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE))
+ purge = false;
+
+ /*
+ * Now go through the interface list and delete anything that
+ * does not have the current generation number. This is
+ * how we catch interfaces that go away or change their
+ * addresses.
+ */
+ if (purge)
+ purge_old_interfaces(mgr);
+
+ /*
+ * Warn if we are not listening on any interface, unless
+ * we're in lwresd-only mode, in which case that is to
+ * be expected.
+ */
+ if (ext_listen == NULL &&
+ ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
+ "not listening on any interfaces");
+ }
+
+ return (result);
+}
+
+bool
+ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) {
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+ return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true);
+}
+
+isc_result_t
+ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) {
+ return (ns_interfacemgr_scan0(mgr, NULL, verbose));
+}
+
+isc_result_t
+ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
+ bool verbose)
+{
+ return (ns_interfacemgr_scan0(mgr, list, verbose));
+}
+
+void
+ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
+ LOCK(&mgr->lock);
+ ns_listenlist_detach(&mgr->listenon4);
+ ns_listenlist_attach(value, &mgr->listenon4);
+ UNLOCK(&mgr->lock);
+}
+
+void
+ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
+ LOCK(&mgr->lock);
+ ns_listenlist_detach(&mgr->listenon6);
+ ns_listenlist_attach(value, &mgr->listenon6);
+ UNLOCK(&mgr->lock);
+}
+
+void
+ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
+ ns_interface_t *interface;
+
+ LOCK(&mgr->lock);
+ interface = ISC_LIST_HEAD(mgr->interfaces);
+ while (interface != NULL) {
+ if (interface->clientmgr != NULL)
+ ns_client_dumprecursing(f, interface->clientmgr);
+ interface = ISC_LIST_NEXT(interface, link);
+ }
+ UNLOCK(&mgr->lock);
+}
+
+bool
+ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
+ isc_sockaddr_t *old;
+
+ for (old = ISC_LIST_HEAD(mgr->listenon);
+ old != NULL;
+ old = ISC_LIST_NEXT(old, link))
+ if (isc_sockaddr_equal(old, addr))
+ return (true);
+ return (false);
+}
diff --git a/bin/named/listenlist.c b/bin/named/listenlist.c
new file mode 100644
index 0000000..234ea75
--- /dev/null
+++ b/bin/named/listenlist.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: listenlist.c,v 1.14 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+
+#include <named/listenlist.h>
+
+static void
+destroy(ns_listenlist_t *list);
+
+isc_result_t
+ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
+ dns_acl_t *acl, ns_listenelt_t **target)
+{
+ ns_listenelt_t *elt = NULL;
+ REQUIRE(target != NULL && *target == NULL);
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ return (ISC_R_NOMEMORY);
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ elt->port = port;
+ elt->dscp = dscp;
+ elt->acl = acl;
+ *target = elt;
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_listenelt_destroy(ns_listenelt_t *elt) {
+ if (elt->acl != NULL)
+ dns_acl_detach(&elt->acl);
+ isc_mem_put(elt->mctx, elt, sizeof(*elt));
+}
+
+isc_result_t
+ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target) {
+ ns_listenlist_t *list = NULL;
+ REQUIRE(target != NULL && *target == NULL);
+ list = isc_mem_get(mctx, sizeof(*list));
+ if (list == NULL)
+ return (ISC_R_NOMEMORY);
+ list->mctx = mctx;
+ list->refcount = 1;
+ ISC_LIST_INIT(list->elts);
+ *target = list;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroy(ns_listenlist_t *list) {
+ ns_listenelt_t *elt, *next;
+ for (elt = ISC_LIST_HEAD(list->elts);
+ elt != NULL;
+ elt = next)
+ {
+ next = ISC_LIST_NEXT(elt, link);
+ ns_listenelt_destroy(elt);
+ }
+ isc_mem_put(list->mctx, list, sizeof(*list));
+}
+
+void
+ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target) {
+ INSIST(source->refcount > 0);
+ source->refcount++;
+ *target = source;
+}
+
+void
+ns_listenlist_detach(ns_listenlist_t **listp) {
+ ns_listenlist_t *list = *listp;
+ INSIST(list->refcount > 0);
+ list->refcount--;
+ if (list->refcount == 0)
+ destroy(list);
+ *listp = NULL;
+}
+
+isc_result_t
+ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
+ bool enabled, ns_listenlist_t **target)
+{
+ isc_result_t result;
+ dns_acl_t *acl = NULL;
+ ns_listenelt_t *elt = NULL;
+ ns_listenlist_t *list = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+ if (enabled)
+ result = dns_acl_any(mctx, &acl);
+ else
+ result = dns_acl_none(mctx, &acl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = ns_listenelt_create(mctx, port, dscp, acl, &elt);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_acl;
+
+ result = ns_listenlist_create(mctx, &list);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_listenelt;
+
+ ISC_LIST_APPEND(list->elts, elt, link);
+
+ *target = list;
+ return (ISC_R_SUCCESS);
+
+ cleanup_listenelt:
+ ns_listenelt_destroy(elt);
+ cleanup_acl:
+ dns_acl_detach(&acl);
+ cleanup:
+ return (result);
+}
diff --git a/bin/named/log.c b/bin/named/log.c
new file mode 100644
index 0000000..3aa25e9
--- /dev/null
+++ b/bin/named/log.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+
+#include <isccfg/log.h>
+
+#include <named/log.h>
+
+#ifndef ISC_FACILITY
+#define ISC_FACILITY LOG_DAEMON
+#endif
+
+/*%
+ * 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 },
+ { "client", 0 },
+ { "network", 0 },
+ { "update", 0 },
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
+ { "query-errors", 0 },
+ { "trust-anchor-telemetry", 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 },
+ { "client", 0 },
+ { "server", 0 },
+ { "query", 0 },
+ { "interfacemgr", 0 },
+ { "update", 0 },
+ { "xfer-in", 0 },
+ { "xfer-out", 0 },
+ { "notify", 0 },
+ { "control", 0 },
+ { "lwresd", 0 },
+ { NULL, 0 }
+};
+
+isc_result_t
+ns_log_init(bool safe) {
+ isc_result_t result;
+ isc_logconfig_t *lcfg = NULL;
+
+ ns_g_categories = categories;
+ ns_g_modules = modules;
+
+ /*
+ * Setup a logging context.
+ */
+ result = isc_log_create(ns_g_mctx, &ns_g_lctx, &lcfg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * named-checktool.c:setup_logging() needs to be kept in sync.
+ */
+ isc_log_registercategories(ns_g_lctx, ns_g_categories);
+ isc_log_registermodules(ns_g_lctx, ns_g_modules);
+ isc_log_setcontext(ns_g_lctx);
+ dns_log_init(ns_g_lctx);
+ dns_log_setcontext(ns_g_lctx);
+ cfg_log_init(ns_g_lctx);
+
+ if (safe)
+ result = ns_log_setsafechannels(lcfg);
+ else
+ result = ns_log_setdefaultchannels(lcfg);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = ns_log_setdefaultcategory(lcfg);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_log_destroy(&ns_g_lctx);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+
+ return (result);
+}
+
+isc_result_t
+ns_log_setdefaultchannels(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+ 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 (! ns_g_logstderr) {
+ destination.file.stream = NULL;
+ destination.file.name = "named.run";
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "default_debug",
+ ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC,
+ &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_DEBUGONLY);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ if (ns_g_logfile != NULL) {
+ destination.file.stream = NULL;
+ destination.file.name = ns_g_logfile;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "default_logfile",
+ ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC,
+ &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_PRINTCATEGORY|
+ ISC_LOG_PRINTLEVEL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+#if ISC_FACILITY != LOG_DAEMON
+ destination.facility = ISC_FACILITY;
+ result = isc_log_createchannel(lcfg, "default_syslog",
+ ISC_LOG_TOSYSLOG, ISC_LOG_INFO,
+ &destination, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+#endif
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+ns_log_setsafechannels(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+ isc_logdestination_t destination;
+
+ if (! ns_g_logstderr) {
+ result = isc_log_createchannel(lcfg, "default_debug",
+ ISC_LOG_TONULL,
+ ISC_LOG_DYNAMIC,
+ NULL, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Setting the debug level to zero should get the output
+ * discarded a bit faster.
+ */
+ isc_log_setdebuglevel(ns_g_lctx, 0);
+ } else {
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ }
+
+ if (ns_g_logfile != NULL) {
+ destination.file.stream = NULL;
+ destination.file.name = ns_g_logfile;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "default_logfile",
+ ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC,
+ &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_PRINTCATEGORY|
+ ISC_LOG_PRINTLEVEL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+#if ISC_FACILITY != LOG_DAEMON
+ destination.facility = ISC_FACILITY;
+ result = isc_log_createchannel(lcfg, "default_syslog",
+ ISC_LOG_TOSYSLOG, ISC_LOG_INFO,
+ &destination, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+#endif
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+ns_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 (! ns_g_logstderr) {
+ if (ns_g_logfile != NULL)
+ result = isc_log_usechannel(lcfg, "default_logfile",
+ ISC_LOGCATEGORY_DEFAULT,
+ NULL);
+ else if (! ns_g_nosyslog)
+ result = isc_log_usechannel(lcfg, "default_syslog",
+ ISC_LOGCATEGORY_DEFAULT,
+ NULL);
+ }
+
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+ns_log_setunmatchedcategory(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+
+ result = isc_log_usechannel(lcfg, "null",
+ NS_LOGCATEGORY_UNMATCHED, NULL);
+ return (result);
+}
+
+void
+ns_log_shutdown(void) {
+ isc_log_destroy(&ns_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..e1cd762
--- /dev/null
+++ b/bin/named/logconf.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: logconf.c,v 1.45 2011/03/05 23:52:29 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#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(ns_g_lctx, catname);
+ if (category == NULL) {
+ cfg_obj_log(ccat, ns_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(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
+ NS_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_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, ns_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");
+ int32_t versions = ISC_LOG_ROLLNEVER;
+ 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:
+ INSIST(0);
+ }
+
+ type = ISC_LOG_TOFILE;
+
+ if (versionsobj != NULL && cfg_obj_isuint32(versionsobj))
+ versions = cfg_obj_asuint32(versionsobj);
+ 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);
+ dest.file.stream = NULL;
+ dest.file.name = cfg_obj_asstring(pathobj);
+ dest.file.versions = versions;
+ 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.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 (printtime != NULL && cfg_obj_asboolean(printtime))
+ flags |= ISC_LOG_PRINTTIME;
+ if (printsev != NULL && cfg_obj_asboolean(printsev))
+ flags |= ISC_LOG_PRINTLEVEL;
+ if (buffered != NULL && cfg_obj_asboolean(buffered))
+ flags |= ISC_LOG_BUFFERED;
+ }
+
+ 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)
+ result = ISC_R_SUCCESS;
+ else
+ result = isc_log_createchannel(logconfig, channelname,
+ type, level, &dest, flags);
+
+ if (result == ISC_R_SUCCESS && 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 && !ns_g_nosyslog)
+ syslog(LOG_ERR,
+ "isc_stdio_open '%s' failed: "
+ "%s", dest.file.name,
+ isc_result_totext(result));
+ fprintf(stderr,
+ "isc_stdio_open '%s' failed: %s\n",
+ dest.file.name,
+ isc_result_totext(result));
+ } else
+ (void)isc_stdio_close(fp);
+ goto done;
+ }
+ if (logconfig != NULL && !ns_g_nosyslog)
+ syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s",
+ dest.file.name, isc_result_totext(result));
+ fprintf(stderr, "isc_file_isplainfile '%s' failed: %s\n",
+ dest.file.name, isc_result_totext(result));
+ }
+
+ done:
+ return (result);
+}
+
+isc_result_t
+ns_log_configure(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)
+ CHECK(ns_log_setdefaultchannels(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(ns_log_setdefaultcategory(logconfig));
+
+ if (logconfig != NULL && !unmatched_set)
+ CHECK(ns_log_setunmatchedcategory(logconfig));
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ return (result);
+}
diff --git a/bin/named/lwaddr.c b/bin/named/lwaddr.c
new file mode 100644
index 0000000..9a58ee4
--- /dev/null
+++ b/bin/named/lwaddr.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwaddr.c,v 1.10 2008/01/11 23:46:56 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/result.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+
+#include <lwres/lwres.h>
+
+#include <named/lwaddr.h>
+
+/*%
+ * Convert addresses from lwres to isc format.
+ */
+isc_result_t
+lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la) {
+ if (la->family != LWRES_ADDRTYPE_V4 && la->family != LWRES_ADDRTYPE_V6)
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ if (la->family == LWRES_ADDRTYPE_V4) {
+ struct in_addr ina;
+ memmove(&ina.s_addr, la->address, 4);
+ isc_netaddr_fromin(na, &ina);
+ } else {
+ struct in6_addr ina6;
+ memmove(&ina6.s6_addr, la->address, 16);
+ isc_netaddr_fromin6(na, &ina6);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la,
+ in_port_t port)
+{
+ isc_netaddr_t na;
+ isc_result_t result;
+
+ result = lwaddr_netaddr_fromlwresaddr(&na, la);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_sockaddr_fromnetaddr(sa, &na, port);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Convert addresses from isc to lwres format.
+ */
+
+isc_result_t
+lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na) {
+ if (na->family != AF_INET && na->family != AF_INET6)
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ if (na->family == AF_INET) {
+ la->family = LWRES_ADDRTYPE_V4;
+ la->length = 4;
+ memmove(la->address, &na->type.in, 4);
+ } else {
+ la->family = LWRES_ADDRTYPE_V6;
+ la->length = 16;
+ memmove(la->address, &na->type.in6, 16);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa) {
+ isc_netaddr_t na;
+ isc_netaddr_fromsockaddr(&na, sa);
+ return (lwaddr_lwresaddr_fromnetaddr(la, &na));
+}
diff --git a/bin/named/lwdclient.c b/bin/named/lwdclient.c
new file mode 100644
index 0000000..d34f831
--- /dev/null
+++ b/bin/named/lwdclient.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwdclient.c,v 1.22 2007/06/18 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/view.h>
+#include <dns/log.h>
+
+#include <named/types.h>
+#include <named/log.h>
+#include <named/lwresd.h>
+#include <named/lwdclient.h>
+
+#define SHUTTINGDOWN(cm) ((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) != 0)
+
+static void
+lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev);
+
+void
+ns_lwdclient_log(int level, const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ isc_log_vwrite(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
+ ISC_LOG_DEBUG(level), format, args);
+ va_end(args);
+}
+
+isc_result_t
+ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
+ isc_taskmgr_t *taskmgr)
+{
+ ns_lwresd_t *lwresd = listener->manager;
+ ns_lwdclientmgr_t *cm;
+ ns_lwdclient_t *client;
+ unsigned int i;
+ isc_result_t result;
+
+ cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t));
+ if (cm == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&cm->lock);
+ if (result != ISC_R_SUCCESS)
+ goto freecm;
+
+ cm->listener = NULL;
+ ns_lwreslistener_attach(listener, &cm->listener);
+ cm->mctx = lwresd->mctx;
+ cm->sock = NULL;
+ isc_socket_attach(listener->sock, &cm->sock);
+ cm->view = lwresd->view;
+ cm->lwctx = NULL;
+ cm->task = NULL;
+ cm->flags = 0;
+ ISC_LINK_INIT(cm, link);
+ ISC_LIST_INIT(cm->idle);
+ ISC_LIST_INIT(cm->running);
+
+ result = lwres_context_create(&cm->lwctx, cm->mctx,
+ ns__lwresd_memalloc, ns__lwresd_memfree,
+ LWRES_CONTEXT_SERVERMODE);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ for (i = 0; i < nclients; i++) {
+ client = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclient_t));
+ if (client != NULL) {
+ ns_lwdclient_log(50, "created client %p, manager %p",
+ client, cm);
+ ns_lwdclient_initialize(client, cm);
+ }
+ }
+
+ /*
+ * If we could create no clients, clean up and return.
+ */
+ if (ISC_LIST_EMPTY(cm->idle)) {
+ result = ISC_R_NOMEMORY;
+ goto errout;
+ }
+
+ result = isc_task_create(taskmgr, 0, &cm->task);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+ isc_task_setname(cm->task, "lwdclient", NULL);
+
+ /*
+ * This MUST be last, since there is no way to cancel an onshutdown...
+ */
+ result = isc_task_onshutdown(cm->task, lwdclientmgr_shutdown_callback,
+ cm);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ ns_lwreslistener_linkcm(listener, cm);
+
+ return (ISC_R_SUCCESS);
+
+ errout:
+ client = ISC_LIST_HEAD(cm->idle);
+ while (client != NULL) {
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ isc_mem_put(lwresd->mctx, client, sizeof(*client));
+ client = ISC_LIST_HEAD(cm->idle);
+ }
+
+ if (cm->task != NULL)
+ isc_task_detach(&cm->task);
+
+ if (cm->lwctx != NULL)
+ lwres_context_destroy(&cm->lwctx);
+
+ DESTROYLOCK(&cm->lock);
+
+ freecm:
+ isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
+ return (result);
+}
+
+static void
+lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) {
+ ns_lwdclient_t *client;
+ ns_lwreslistener_t *listener;
+
+ LOCK(&cm->lock);
+ if (!SHUTTINGDOWN(cm)) {
+ UNLOCK(&cm->lock);
+ return;
+ }
+
+ /*
+ * Run through the idle list and free the clients there. Idle
+ * clients do not have a recv running nor do they have any finds
+ * or similar running.
+ */
+ client = ISC_LIST_HEAD(cm->idle);
+ while (client != NULL) {
+ ns_lwdclient_log(50, "destroying client %p, manager %p",
+ client, cm);
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ isc_mem_put(cm->mctx, client, sizeof(*client));
+ client = ISC_LIST_HEAD(cm->idle);
+ }
+
+ if (!ISC_LIST_EMPTY(cm->running)) {
+ UNLOCK(&cm->lock);
+ return;
+ }
+
+ UNLOCK(&cm->lock);
+
+ lwres_context_destroy(&cm->lwctx);
+ cm->view = NULL;
+ isc_socket_detach(&cm->sock);
+ isc_task_detach(&cm->task);
+
+ DESTROYLOCK(&cm->lock);
+
+ listener = cm->listener;
+ ns_lwreslistener_unlinkcm(listener, cm);
+ ns_lwdclient_log(50, "destroying manager %p", cm);
+ isc_mem_put(cm->mctx, cm, sizeof(*cm));
+ ns_lwreslistener_detach(&listener);
+}
+
+static void
+process_request(ns_lwdclient_t *client) {
+ lwres_buffer_t b;
+ isc_result_t result;
+
+ lwres_buffer_init(&b, client->buffer, client->recvlength);
+ lwres_buffer_add(&b, client->recvlength);
+
+ result = lwres_lwpacket_parseheader(&b, &client->pkt);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_log(50, "invalid packet header received");
+ goto restart;
+ }
+
+ ns_lwdclient_log(50, "opcode %08x", client->pkt.opcode);
+
+ switch (client->pkt.opcode) {
+ case LWRES_OPCODE_GETADDRSBYNAME:
+ ns_lwdclient_processgabn(client, &b);
+ return;
+ case LWRES_OPCODE_GETNAMEBYADDR:
+ ns_lwdclient_processgnba(client, &b);
+ return;
+ case LWRES_OPCODE_GETRDATABYNAME:
+ ns_lwdclient_processgrbn(client, &b);
+ return;
+ case LWRES_OPCODE_NOOP:
+ ns_lwdclient_processnoop(client, &b);
+ return;
+ default:
+ ns_lwdclient_log(50, "unknown opcode %08x", client->pkt.opcode);
+ goto restart;
+ }
+
+ /*
+ * Drop the packet.
+ */
+ restart:
+ ns_lwdclient_log(50, "restarting client %p...", client);
+ ns_lwdclient_stateidle(client);
+}
+
+void
+ns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) {
+ isc_result_t result;
+ ns_lwdclient_t *client = ev->ev_arg;
+ ns_lwdclientmgr_t *cm = client->clientmgr;
+ isc_socketevent_t *dev = (isc_socketevent_t *)ev;
+
+ INSIST(dev->region.base == client->buffer);
+ INSIST(NS_LWDCLIENT_ISRECV(client));
+
+ NS_LWDCLIENT_SETRECVDONE(client);
+
+ LOCK(&cm->lock);
+ INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0);
+ cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
+ UNLOCK(&cm->lock);
+
+ ns_lwdclient_log(50,
+ "event received: task %p, length %u, result %u (%s)",
+ task, dev->n, dev->result,
+ isc_result_totext(dev->result));
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_event_free(&ev);
+ dev = NULL;
+
+ /*
+ * Go idle.
+ */
+ ns_lwdclient_stateidle(client);
+
+ return;
+ }
+
+ client->recvlength = dev->n;
+ client->address = dev->address;
+ if ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
+ client->pktinfo = dev->pktinfo;
+ client->pktinfo_valid = true;
+ } else
+ client->pktinfo_valid = false;
+ isc_event_free(&ev);
+ dev = NULL;
+
+ result = ns_lwdclient_startrecv(cm);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
+ "could not start lwres "
+ "client handler: %s",
+ isc_result_totext(result));
+
+ process_request(client);
+}
+
+/*
+ * This function will start a new recv() on a socket for this client manager.
+ */
+isc_result_t
+ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
+ ns_lwdclient_t *client;
+ isc_result_t result;
+ isc_region_t r;
+ bool destroy = false;
+
+
+ LOCK(&cm->lock);
+ if (SHUTTINGDOWN(cm)) {
+ destroy = true;
+ result = ISC_R_SUCCESS;
+ goto unlock;
+ }
+
+ /*
+ * If a recv is already running, don't bother.
+ */
+ if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) {
+ result = ISC_R_SUCCESS;
+ goto unlock;
+ }
+
+ /*
+ * If we have no idle slots, just return success.
+ */
+ client = ISC_LIST_HEAD(cm->idle);
+ if (client == NULL) {
+ result = ISC_R_SUCCESS;
+ goto unlock;
+ }
+
+ INSIST(NS_LWDCLIENT_ISIDLE(client));
+
+ /*
+ * Set the flag to say there is a recv pending. If isc_socket_recv
+ * fails we will clear the flag otherwise it will be cleared by
+ * ns_lwdclient_recv.
+ */
+ cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;
+
+ /*
+ * Issue the recv. If it fails, return that it did.
+ */
+ r.base = client->buffer;
+ r.length = LWRES_RECVLENGTH;
+ result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
+ client);
+ if (result != ISC_R_SUCCESS) {
+ cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
+ goto unlock;
+ }
+
+ /*
+ * Remove the client from the idle list, and put it on the running
+ * list.
+ */
+ NS_LWDCLIENT_SETRECV(client);
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ ISC_LIST_APPEND(cm->running, client, link);
+
+ unlock:
+ UNLOCK(&cm->lock);
+
+ if (destroy)
+ lwdclientmgr_destroy(cm);
+
+ return (result);
+}
+
+static void
+lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
+ ns_lwdclientmgr_t *cm = ev->ev_arg;
+ ns_lwdclient_t *client;
+
+ REQUIRE(!SHUTTINGDOWN(cm));
+
+ ns_lwdclient_log(50, "got shutdown event, task %p, lwdclientmgr %p",
+ task, cm);
+
+ /*
+ * run through the idle list and free the clients there. Idle
+ * clients do not have a recv running nor do they have any finds
+ * or similar running.
+ */
+ LOCK(&cm->lock);
+ client = ISC_LIST_HEAD(cm->idle);
+ while (client != NULL) {
+ ns_lwdclient_log(50, "destroying client %p, manager %p",
+ client, cm);
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ isc_mem_put(cm->mctx, client, sizeof(*client));
+ client = ISC_LIST_HEAD(cm->idle);
+ }
+ UNLOCK(&cm->lock);
+
+ /*
+ * Cancel any pending I/O.
+ */
+ isc_socket_cancel(cm->sock, task, ISC_SOCKCANCEL_ALL);
+
+ /*
+ * Run through the running client list and kill off any finds
+ * in progress.
+ */
+ LOCK(&cm->lock);
+ client = ISC_LIST_HEAD(cm->running);
+ while (client != NULL) {
+ if (client->find != client->v4find
+ && client->find != client->v6find)
+ dns_adb_cancelfind(client->find);
+ if (client->v4find != NULL)
+ dns_adb_cancelfind(client->v4find);
+ if (client->v6find != NULL)
+ dns_adb_cancelfind(client->v6find);
+ client = ISC_LIST_NEXT(client, link);
+ }
+
+ cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN;
+
+ UNLOCK(&cm->lock);
+
+ isc_event_free(&ev);
+}
+
+/*
+ * Do all the crap needed to move a client from the run queue to the idle
+ * queue.
+ */
+void
+ns_lwdclient_stateidle(ns_lwdclient_t *client) {
+ ns_lwdclientmgr_t *cm;
+ isc_result_t result;
+
+ cm = client->clientmgr;
+
+ INSIST(client->sendbuf == NULL);
+ INSIST(client->sendlength == 0);
+ INSIST(client->arg == NULL);
+ INSIST(client->v4find == NULL);
+ INSIST(client->v6find == NULL);
+
+ LOCK(&cm->lock);
+ ISC_LIST_UNLINK(cm->running, client, link);
+ ISC_LIST_PREPEND(cm->idle, client, link);
+ UNLOCK(&cm->lock);
+
+ NS_LWDCLIENT_SETIDLE(client);
+
+ result = ns_lwdclient_startrecv(cm);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
+ "could not start lwres "
+ "client handler: %s",
+ isc_result_totext(result));
+}
+
+void
+ns_lwdclient_send(isc_task_t *task, isc_event_t *ev) {
+ ns_lwdclient_t *client = ev->ev_arg;
+ ns_lwdclientmgr_t *cm = client->clientmgr;
+ isc_socketevent_t *dev = (isc_socketevent_t *)ev;
+
+ UNUSED(task);
+ UNUSED(dev);
+
+ INSIST(NS_LWDCLIENT_ISSEND(client));
+ INSIST(client->sendbuf == dev->region.base);
+
+ ns_lwdclient_log(50, "task %p for client %p got send-done event",
+ task, client);
+
+ if (client->sendbuf != client->buffer)
+ lwres_context_freemem(cm->lwctx, client->sendbuf,
+ client->sendlength);
+ client->sendbuf = NULL;
+ client->sendlength = 0;
+
+ ns_lwdclient_stateidle(client);
+
+ isc_event_free(&ev);
+}
+
+isc_result_t
+ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r) {
+ struct in6_pktinfo *pktinfo;
+ ns_lwdclientmgr_t *cm = client->clientmgr;
+
+ if (client->pktinfo_valid)
+ pktinfo = &client->pktinfo;
+ else
+ pktinfo = NULL;
+ return (isc_socket_sendto(cm->sock, r, cm->task, ns_lwdclient_send,
+ client, &client->address, pktinfo));
+}
+
+void
+ns_lwdclient_initialize(ns_lwdclient_t *client, ns_lwdclientmgr_t *cmgr) {
+ client->clientmgr = cmgr;
+ ISC_LINK_INIT(client, link);
+ NS_LWDCLIENT_SETIDLE(client);
+ client->arg = NULL;
+
+ client->recvlength = 0;
+
+ client->sendbuf = NULL;
+ client->sendlength = 0;
+
+ client->find = NULL;
+ client->v4find = NULL;
+ client->v6find = NULL;
+ client->find_wanted = 0;
+
+ client->options = 0;
+ client->byaddr = NULL;
+
+ client->lookup = NULL;
+
+ client->pktinfo_valid = false;
+
+ LOCK(&cmgr->lock);
+ ISC_LIST_APPEND(cmgr->idle, client, link);
+ UNLOCK(&cmgr->lock);
+}
diff --git a/bin/named/lwderror.c b/bin/named/lwderror.c
new file mode 100644
index 0000000..32ed2d8
--- /dev/null
+++ b/bin/named/lwderror.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwderror.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/util.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+
+/*%
+ * Generate an error packet for the client, schedule a send, and put us in
+ * the SEND state.
+ *
+ * The client->pkt structure will be modified to form an error return.
+ * The receiver needs to verify that it is in fact an error, and do the
+ * right thing with it. The opcode will be unchanged. The result needs
+ * to be set before calling this function.
+ *
+ * The only change this code makes is to set the receive buffer size to the
+ * size we use, set the reply bit, and recompute any security information.
+ */
+void
+ns_lwdclient_errorpktsend(ns_lwdclient_t *client, uint32_t _result) {
+ isc_result_t result;
+ int lwres;
+ isc_region_t r;
+ lwres_buffer_t b;
+
+ REQUIRE(NS_LWDCLIENT_ISRUNNING(client));
+
+ /*
+ * Since we are only sending the packet header, we can safely toss
+ * the receive buffer. This means we won't need to allocate space
+ * for sending an error reply. This is a Good Thing.
+ */
+ client->pkt.length = LWRES_LWPACKET_LENGTH;
+ client->pkt.pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = _result;
+
+ lwres_buffer_init(&b, client->buffer, LWRES_RECVLENGTH);
+ lwres = lwres_lwpacket_renderheader(&b, &client->pkt);
+ if (lwres != LWRES_R_SUCCESS) {
+ ns_lwdclient_stateidle(client);
+ return;
+ }
+
+ r.base = client->buffer;
+ r.length = b.used;
+ client->sendbuf = client->buffer;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_stateidle(client);
+ return;
+ }
+
+ NS_LWDCLIENT_SETSEND(client);
+}
diff --git a/bin/named/lwdgabn.c b/bin/named/lwdgabn.c
new file mode 100644
index 0000000..01faa26
--- /dev/null
+++ b/bin/named/lwdgabn.c
@@ -0,0 +1,651 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwdgabn.c,v 1.24 2009/09/02 23:48:01 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/events.h>
+#include <dns/result.h>
+
+#include <named/types.h>
+#include <named/lwaddr.h>
+#include <named/lwdclient.h>
+#include <named/lwresd.h>
+#include <named/lwsearch.h>
+#include <named/sortlist.h>
+
+#define NEED_V4(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \
+ && ((c)->v4find == NULL))
+#define NEED_V6(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V6) != 0) \
+ && ((c)->v6find == NULL))
+
+static isc_result_t start_find(ns_lwdclient_t *);
+static void restart_find(ns_lwdclient_t *);
+static void init_gabn(ns_lwdclient_t *);
+
+/*%
+ * Destroy any finds. This can be used to "start over from scratch" and
+ * should only be called when events are _not_ being generated by the finds.
+ */
+static void
+cleanup_gabn(ns_lwdclient_t *client) {
+ ns_lwdclient_log(50, "cleaning up client %p", client);
+
+ if (client->v6find != NULL) {
+ if (client->v6find == client->v4find)
+ client->v6find = NULL;
+ else
+ dns_adb_destroyfind(&client->v6find);
+ }
+ if (client->v4find != NULL)
+ dns_adb_destroyfind(&client->v4find);
+}
+
+static void
+setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
+ dns_adbaddrinfo_t *ai;
+ lwres_addr_t *addr;
+ int af;
+ const struct sockaddr *sa;
+ isc_result_t result;
+
+ if (at == DNS_ADBFIND_INET)
+ af = AF_INET;
+ else
+ af = AF_INET6;
+
+ ai = ISC_LIST_HEAD(find->list);
+ while (ai != NULL && client->gabn.naddrs < LWRES_MAX_ADDRS) {
+ sa = &ai->sockaddr.type.sa;
+ if (sa->sa_family != af)
+ goto next;
+
+ addr = &client->addrs[client->gabn.naddrs];
+
+ result = lwaddr_lwresaddr_fromsockaddr(addr, &ai->sockaddr);
+ if (result != ISC_R_SUCCESS)
+ goto next;
+
+ ns_lwdclient_log(50, "adding address %p, family %d, length %d",
+ addr->address, addr->family, addr->length);
+
+ client->gabn.naddrs++;
+ REQUIRE(!LWRES_LINK_LINKED(addr, link));
+ LWRES_LIST_APPEND(client->gabn.addrs, addr, link);
+
+ next:
+ ai = ISC_LIST_NEXT(ai, publink);
+ }
+}
+
+typedef struct {
+ isc_netaddr_t address;
+ int rank;
+} rankedaddress;
+
+static int
+addr_compare(const void *av, const void *bv) {
+ const rankedaddress *a = (const rankedaddress *) av;
+ const rankedaddress *b = (const rankedaddress *) bv;
+ return (a->rank - b->rank);
+}
+
+static void
+sort_addresses(ns_lwdclient_t *client) {
+ unsigned int naddrs;
+ rankedaddress *addrs;
+ isc_netaddr_t remote;
+ dns_addressorderfunc_t order;
+ const void *arg;
+ ns_lwresd_t *lwresd = client->clientmgr->listener->manager;
+ unsigned int i;
+ isc_result_t result;
+
+ naddrs = client->gabn.naddrs;
+
+ if (naddrs <= 1 || lwresd->view->sortlist == NULL)
+ return;
+
+ addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs);
+ if (addrs == NULL)
+ return;
+
+ isc_netaddr_fromsockaddr(&remote, &client->address);
+ ns_sortlist_byaddrsetup(lwresd->view->sortlist,
+ &remote, &order, &arg);
+ if (order == NULL) {
+ isc_mem_put(lwresd->mctx, addrs,
+ sizeof(rankedaddress) * naddrs);
+ return;
+ }
+ for (i = 0; i < naddrs; i++) {
+ result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address,
+ &client->addrs[i]);
+ INSIST(result == ISC_R_SUCCESS);
+ addrs[i].rank = (*order)(&addrs[i].address, arg);
+ }
+ qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare);
+ for (i = 0; i < naddrs; i++) {
+ result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i],
+ &addrs[i].address);
+ INSIST(result == ISC_R_SUCCESS);
+ }
+
+ isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs);
+}
+
+static void
+generate_reply(ns_lwdclient_t *client) {
+ isc_result_t result;
+ int lwres;
+ isc_region_t r;
+ lwres_buffer_t lwb;
+ ns_lwdclientmgr_t *cm;
+
+ cm = client->clientmgr;
+ lwb.base = NULL;
+
+ ns_lwdclient_log(50, "generating gabn reply for client %p", client);
+
+ /*
+ * We must make certain the client->find is not still active.
+ * If it is either the v4 or v6 answer, just set it to NULL and
+ * let the cleanup code destroy it. Otherwise, destroy it now.
+ */
+ if (client->find == client->v4find || client->find == client->v6find)
+ client->find = NULL;
+ else
+ if (client->find != NULL)
+ dns_adb_destroyfind(&client->find);
+
+ /*
+ * perhaps there are some here?
+ */
+ if (NEED_V6(client) && client->v4find != NULL)
+ client->v6find = client->v4find;
+
+ /*
+ * Run through the finds we have and wire them up to the gabn
+ * structure.
+ */
+ LWRES_LIST_INIT(client->gabn.addrs);
+ if (client->v4find != NULL)
+ setup_addresses(client, client->v4find, DNS_ADBFIND_INET);
+ if (client->v6find != NULL)
+ setup_addresses(client, client->v6find, DNS_ADBFIND_INET6);
+
+ /*
+ * If there are no addresses, try the next element in the search
+ * path, if there are any more. Otherwise, fall through into
+ * the error handling code below.
+ */
+ if (client->gabn.naddrs == 0) {
+ do {
+ result = ns_lwsearchctx_next(&client->searchctx);
+ if (result == ISC_R_SUCCESS) {
+ cleanup_gabn(client);
+ result = start_find(client);
+ if (result == ISC_R_SUCCESS)
+ return;
+ }
+ } while (result == ISC_R_SUCCESS);
+ }
+
+ /*
+ * Render the packet.
+ */
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+
+ /*
+ * If there are no addresses, return failure.
+ */
+ if (client->gabn.naddrs != 0)
+ client->pkt.result = LWRES_R_SUCCESS;
+ else
+ client->pkt.result = LWRES_R_NOTFOUND;
+
+ sort_addresses(client);
+
+ lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn,
+ &client->pkt, &lwb);
+ if (lwres != LWRES_R_SUCCESS)
+ goto out;
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ /*
+ * All done!
+ */
+ cleanup_gabn(client);
+
+ return;
+
+ out:
+ cleanup_gabn(client);
+
+ if (lwb.base != NULL)
+ lwres_context_freemem(client->clientmgr->lwctx,
+ lwb.base, lwb.length);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
+
+/*
+ * Take the current real name, move it to an alias slot (if any are
+ * open) then put this new name in as the real name for the target.
+ *
+ * Return success if it can be rendered, otherwise failure. Note that
+ * not having enough alias slots open is NOT a failure.
+ */
+static isc_result_t
+add_alias(ns_lwdclient_t *client) {
+ isc_buffer_t b;
+ isc_result_t result;
+ uint16_t naliases;
+
+ b = client->recv_buffer;
+
+ /*
+ * Render the new name to the buffer.
+ */
+ result = dns_name_totext(dns_fixedname_name(&client->target_name),
+ true, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Are there any open slots?
+ */
+ naliases = client->gabn.naliases;
+ if (naliases < LWRES_MAX_ALIASES) {
+ client->gabn.aliases[naliases] = client->gabn.realname;
+ client->gabn.aliaslen[naliases] = client->gabn.realnamelen;
+ client->gabn.naliases++;
+ }
+
+ /*
+ * Save this name away as the current real name.
+ */
+ client->gabn.realname = (char *)(b.base) + b.used;
+ client->gabn.realnamelen = client->recv_buffer.used - b.used;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+store_realname(ns_lwdclient_t *client) {
+ isc_buffer_t b;
+ isc_result_t result;
+ dns_name_t *tname;
+
+ b = client->recv_buffer;
+
+ tname = dns_fixedname_name(&client->target_name);
+ result = ns_lwsearchctx_current(&client->searchctx, tname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Render the new name to the buffer.
+ */
+ result = dns_name_totext(tname, true, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Save this name away as the current real name.
+ */
+ client->gabn.realname = (char *) b.base + b.used;
+ client->gabn.realnamelen = client->recv_buffer.used - b.used;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+process_gabn_finddone(isc_task_t *task, isc_event_t *ev) {
+ ns_lwdclient_t *client = ev->ev_arg;
+ isc_eventtype_t evtype;
+ bool claimed;
+
+ ns_lwdclient_log(50, "find done for task %p, client %p", task, client);
+
+ evtype = ev->ev_type;
+ isc_event_free(&ev);
+
+ /*
+ * No more info to be had? If so, we have all the good stuff
+ * right now, so we can render things.
+ */
+ claimed = false;
+ if (evtype == DNS_EVENT_ADBNOMOREADDRESSES) {
+ if (NEED_V4(client)) {
+ client->v4find = client->find;
+ claimed = true;
+ }
+ if (NEED_V6(client)) {
+ client->v6find = client->find;
+ claimed = true;
+ }
+ if (client->find != NULL) {
+ if (claimed)
+ client->find = NULL;
+ else
+ dns_adb_destroyfind(&client->find);
+
+ }
+ generate_reply(client);
+ return;
+ }
+
+ /*
+ * We probably don't need this find anymore. We're either going to
+ * reissue it, or an error occurred. Either way, we're done with
+ * it.
+ */
+ if ((client->find != client->v4find)
+ && (client->find != client->v6find)) {
+ dns_adb_destroyfind(&client->find);
+ } else {
+ client->find = NULL;
+ }
+
+ /*
+ * We have some new information we can gather. Run off and fetch
+ * it.
+ */
+ if (evtype == DNS_EVENT_ADBMOREADDRESSES) {
+ restart_find(client);
+ return;
+ }
+
+ /*
+ * An error or other strangeness happened. Drop this query.
+ */
+ cleanup_gabn(client);
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
+
+static void
+restart_find(ns_lwdclient_t *client) {
+ unsigned int options;
+ isc_result_t result;
+ bool claimed;
+
+ ns_lwdclient_log(50, "starting find for client %p", client);
+
+ /*
+ * Issue a find for the name contained in the request. We won't
+ * set the bit that says "anything is good enough" -- we want it
+ * all.
+ */
+ options = 0;
+ options |= DNS_ADBFIND_WANTEVENT;
+ options |= DNS_ADBFIND_RETURNLAME;
+
+ /*
+ * Set the bits up here to mark that we want this address family
+ * and that we do not currently have a find pending. We will
+ * set that bit again below if it turns out we will get an event.
+ */
+ if (NEED_V4(client))
+ options |= DNS_ADBFIND_INET;
+ if (NEED_V6(client))
+ options |= DNS_ADBFIND_INET6;
+
+ find_again:
+ INSIST(client->find == NULL);
+ result = dns_adb_createfind(client->clientmgr->view->adb,
+ client->clientmgr->task,
+ process_gabn_finddone, client,
+ dns_fixedname_name(&client->target_name),
+ dns_rootname, 0, options, 0,
+ dns_fixedname_name(&client->target_name),
+ client->clientmgr->view->dstport,
+ &client->find);
+
+ /*
+ * Did we get an alias? If so, save it and re-issue the query.
+ */
+ if (result == DNS_R_ALIAS) {
+ ns_lwdclient_log(50, "found alias, restarting query");
+ dns_adb_destroyfind(&client->find);
+ cleanup_gabn(client);
+ result = add_alias(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_log(50,
+ "out of buffer space adding alias");
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+ goto find_again;
+ }
+
+ ns_lwdclient_log(50, "find returned %d (%s)", result,
+ isc_result_totext(result));
+
+ /*
+ * Did we get an error?
+ */
+ if (result != ISC_R_SUCCESS) {
+ if (client->find != NULL)
+ dns_adb_destroyfind(&client->find);
+ cleanup_gabn(client);
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+
+ claimed = false;
+
+ /*
+ * Did we get our answer to V4 addresses?
+ */
+ if (NEED_V4(client)
+ && ((client->find->query_pending & DNS_ADBFIND_INET) == 0)) {
+ ns_lwdclient_log(50, "client %p ipv4 satisfied by find %p",
+ client, client->find);
+ claimed = true;
+ client->v4find = client->find;
+ }
+
+ /*
+ * Did we get our answer to V6 addresses?
+ */
+ if (NEED_V6(client)
+ && ((client->find->query_pending & DNS_ADBFIND_INET6) == 0)) {
+ ns_lwdclient_log(50, "client %p ipv6 satisfied by find %p",
+ client, client->find);
+ claimed = true;
+ client->v6find = client->find;
+ }
+
+ /*
+ * If we're going to get an event, set our internal pending flag
+ * and return. When we get an event back we'll do the right
+ * thing, basically by calling this function again, perhaps with a
+ * new target name.
+ *
+ * If we have both v4 and v6, and we are still getting an event,
+ * we have a programming error, so die hard.
+ */
+ if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
+ ns_lwdclient_log(50, "event will be sent");
+ INSIST(client->v4find == NULL || client->v6find == NULL);
+ return;
+ }
+ ns_lwdclient_log(50, "no event will be sent");
+ if (claimed)
+ client->find = NULL;
+ else
+ dns_adb_destroyfind(&client->find);
+
+ /*
+ * We seem to have everything we asked for, or at least we are
+ * able to respond with things we've learned.
+ */
+
+ generate_reply(client);
+}
+
+static isc_result_t
+start_find(ns_lwdclient_t *client) {
+ isc_result_t result;
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ init_gabn(client);
+
+ result = store_realname(client);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ restart_find(client);
+ return (ISC_R_SUCCESS);
+
+}
+
+static void
+init_gabn(ns_lwdclient_t *client) {
+ int i;
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ for (i = 0; i < LWRES_MAX_ALIASES; i++) {
+ client->aliases[i] = NULL;
+ client->aliaslen[i] = 0;
+ }
+ for (i = 0; i < LWRES_MAX_ADDRS; i++) {
+ client->addrs[i].family = 0;
+ client->addrs[i].length = 0;
+ memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
+ LWRES_LINK_INIT(&client->addrs[i], link);
+ }
+
+ client->gabn.naliases = 0;
+ client->gabn.naddrs = 0;
+ client->gabn.realname = NULL;
+ client->gabn.aliases = client->aliases;
+ client->gabn.realnamelen = 0;
+ client->gabn.aliaslen = client->aliaslen;
+ LWRES_LIST_INIT(client->gabn.addrs);
+ client->gabn.base = NULL;
+ client->gabn.baselen = 0;
+
+ /*
+ * Set up the internal buffer to point to the receive region.
+ */
+ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
+}
+
+/*
+ * When we are called, we can be assured that:
+ *
+ * client->sockaddr contains the address we need to reply to,
+ *
+ * client->pkt contains the packet header data,
+ *
+ * the packet "checks out" overall -- any MD5 hashes or crypto
+ * bits have been verified,
+ *
+ * "b" points to the remaining data after the packet header
+ * was parsed off.
+ *
+ * We are in a the RECVDONE state.
+ *
+ * From this state we will enter the SEND state if we happen to have
+ * everything we need or we need to return an error packet, or to the
+ * FINDWAIT state if we need to look things up.
+ */
+void
+ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ isc_result_t result;
+ lwres_gabnrequest_t *req;
+ ns_lwdclientmgr_t *cm;
+ isc_buffer_t namebuf;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+
+ cm = client->clientmgr;
+ req = NULL;
+
+ result = lwres_gabnrequest_parse(client->clientmgr->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto out;
+ if (req->name == NULL)
+ goto out;
+
+ isc_buffer_init(&namebuf, req->name, req->namelen);
+ isc_buffer_add(&namebuf, req->namelen);
+
+ dns_fixedname_init(&client->target_name);
+ dns_fixedname_init(&client->query_name);
+ result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
+ &namebuf, NULL, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ ns_lwsearchctx_init(&client->searchctx,
+ cm->listener->manager->search,
+ dns_fixedname_name(&client->query_name),
+ cm->listener->manager->ndots);
+ ns_lwsearchctx_first(&client->searchctx);
+
+ client->find_wanted = req->addrtypes;
+ ns_lwdclient_log(50, "client %p looking for addrtypes %08x",
+ client, client->find_wanted);
+
+ /*
+ * We no longer need to keep this around.
+ */
+ lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
+
+ /*
+ * Start the find.
+ */
+ result = start_find(client);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ return;
+
+ /*
+ * We're screwed. Return an error packet to our caller.
+ */
+ out:
+ if (req != NULL)
+ lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwdgnba.c b/bin/named/lwdgnba.c
new file mode 100644
index 0000000..9e600f5
--- /dev/null
+++ b/bin/named/lwdgnba.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwdgnba.c,v 1.22 2008/01/14 23:46:56 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/byaddr.h>
+#include <dns/result.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+
+static void start_byaddr(ns_lwdclient_t *);
+
+static void
+byaddr_done(isc_task_t *task, isc_event_t *event) {
+ ns_lwdclient_t *client;
+ ns_lwdclientmgr_t *cm;
+ dns_byaddrevent_t *bevent;
+ int lwres;
+ lwres_buffer_t lwb;
+ dns_name_t *name;
+ isc_result_t result;
+ lwres_result_t lwresult;
+ isc_region_t r;
+ isc_buffer_t b;
+ lwres_gnbaresponse_t *gnba;
+ uint16_t naliases;
+
+ UNUSED(task);
+
+ lwb.base = NULL;
+ client = event->ev_arg;
+ cm = client->clientmgr;
+ INSIST(client->byaddr == (dns_byaddr_t *)event->ev_sender);
+
+ bevent = (dns_byaddrevent_t *)event;
+ gnba = &client->gnba;
+
+ ns_lwdclient_log(50, "byaddr event result = %s",
+ isc_result_totext(bevent->result));
+
+ result = bevent->result;
+ if (result != ISC_R_SUCCESS) {
+ dns_byaddr_destroy(&client->byaddr);
+ isc_event_free(&event);
+ bevent = NULL;
+
+ if (client->na.family != AF_INET6 ||
+ (client->options & DNS_BYADDROPT_IPV6INT) != 0) {
+ if (result == DNS_R_NCACHENXDOMAIN ||
+ result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NXRRSET)
+ lwresult = LWRES_R_NOTFOUND;
+ else
+ lwresult = LWRES_R_FAILURE;
+ ns_lwdclient_errorpktsend(client, lwresult);
+ return;
+ }
+
+ /*
+ * Fall back to ip6.int reverse if the default ip6.arpa
+ * fails.
+ */
+ client->options |= DNS_BYADDROPT_IPV6INT;
+
+ start_byaddr(client);
+ return;
+ }
+
+ for (name = ISC_LIST_HEAD(bevent->names);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link))
+ {
+ b = client->recv_buffer;
+
+ result = dns_name_totext(name, true, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ ns_lwdclient_log(50, "found name '%.*s'",
+ (int)(client->recv_buffer.used - b.used),
+ (char *)(b.base) + b.used);
+ if (gnba->realname == NULL) {
+ gnba->realname = (char *)(b.base) + b.used;
+ gnba->realnamelen = client->recv_buffer.used - b.used;
+ } else {
+ naliases = gnba->naliases;
+ if (naliases >= LWRES_MAX_ALIASES)
+ break;
+ gnba->aliases[naliases] = (char *)(b.base) + b.used;
+ gnba->aliaslen[naliases] =
+ client->recv_buffer.used - b.used;
+ gnba->naliases++;
+ }
+ }
+
+ dns_byaddr_destroy(&client->byaddr);
+ isc_event_free(&event);
+
+ /*
+ * Render the packet.
+ */
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = LWRES_R_SUCCESS;
+
+ lwres = lwres_gnbaresponse_render(cm->lwctx,
+ gnba, &client->pkt, &lwb);
+ if (lwres != LWRES_R_SUCCESS)
+ goto out;
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ return;
+
+ out:
+ if (client->byaddr != NULL)
+ dns_byaddr_destroy(&client->byaddr);
+ if (lwb.base != NULL)
+ lwres_context_freemem(cm->lwctx,
+ lwb.base, lwb.length);
+
+ if (event != NULL)
+ isc_event_free(&event);
+}
+
+static void
+start_byaddr(ns_lwdclient_t *client) {
+ isc_result_t result;
+ ns_lwdclientmgr_t *cm;
+
+ cm = client->clientmgr;
+
+ INSIST(client->byaddr == NULL);
+
+ result = dns_byaddr_create(cm->mctx, &client->na, cm->view,
+ client->options, cm->task, byaddr_done,
+ client, &client->byaddr);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+}
+
+static void
+init_gnba(ns_lwdclient_t *client) {
+ int i;
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ for (i = 0; i < LWRES_MAX_ALIASES; i++) {
+ client->aliases[i] = NULL;
+ client->aliaslen[i] = 0;
+ }
+ for (i = 0; i < LWRES_MAX_ADDRS; i++) {
+ client->addrs[i].family = 0;
+ client->addrs[i].length = 0;
+ memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
+ LWRES_LINK_INIT(&client->addrs[i], link);
+ }
+
+ client->gnba.naliases = 0;
+ client->gnba.realname = NULL;
+ client->gnba.aliases = client->aliases;
+ client->gnba.realnamelen = 0;
+ client->gnba.aliaslen = client->aliaslen;
+ client->gnba.base = NULL;
+ client->gnba.baselen = 0;
+ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
+}
+
+void
+ns_lwdclient_processgnba(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ lwres_gnbarequest_t *req;
+ isc_result_t result;
+ isc_sockaddr_t sa;
+ ns_lwdclientmgr_t *cm;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+ INSIST(client->byaddr == NULL);
+
+ cm = client->clientmgr;
+ req = NULL;
+
+ result = lwres_gnbarequest_parse(cm->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto out;
+
+ client->options = 0;
+ if (req->addr.family == LWRES_ADDRTYPE_V4) {
+ client->na.family = AF_INET;
+ if (req->addr.length != 4)
+ goto out;
+ memmove(&client->na.type.in, req->addr.address, 4);
+ } else if (req->addr.family == LWRES_ADDRTYPE_V6) {
+ client->na.family = AF_INET6;
+ if (req->addr.length != 16)
+ goto out;
+ memmove(&client->na.type.in6, req->addr.address, 16);
+ } else {
+ goto out;
+ }
+ isc_sockaddr_fromnetaddr(&sa, &client->na, 53);
+
+ ns_lwdclient_log(50, "client %p looking for addrtype %08x",
+ client, req->addr.family);
+
+ /*
+ * We no longer need to keep this around.
+ */
+ lwres_gnbarequest_free(cm->lwctx, &req);
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ init_gnba(client);
+ client->options = 0;
+
+ /*
+ * Start the find.
+ */
+ start_byaddr(client);
+
+ return;
+
+ /*
+ * We're screwed. Return an error packet to our caller.
+ */
+ out:
+ if (req != NULL)
+ lwres_gnbarequest_free(cm->lwctx, &req);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwdgrbn.c b/bin/named/lwdgrbn.c
new file mode 100644
index 0000000..407267d
--- /dev/null
+++ b/bin/named/lwdgrbn.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwdgrbn.c,v 1.22 2009/09/02 23:48:01 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/lookup.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+#include <named/lwresd.h>
+#include <named/lwsearch.h>
+
+static void start_lookup(ns_lwdclient_t *);
+
+static isc_result_t
+fill_array(int *pos, dns_rdataset_t *rdataset,
+ int size, unsigned char **rdatas, uint16_t *rdatalen)
+{
+ dns_rdata_t rdata;
+ isc_result_t result;
+ isc_region_t r;
+
+ UNUSED(size);
+
+ dns_rdata_init(&rdata);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ INSIST(*pos < size);
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_toregion(&rdata, &r);
+ rdatas[*pos] = r.base;
+ rdatalen[*pos] = r.length;
+ dns_rdata_reset(&rdata);
+ (*pos)++;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+static isc_result_t
+iterate_node(lwres_grbnresponse_t *grbn, dns_db_t *db, dns_dbnode_t *node,
+ isc_mem_t *mctx)
+{
+ int used = 0, count;
+ int size = 8, oldsize = 0;
+ unsigned char **rdatas = NULL, **oldrdatas = NULL, **newrdatas = NULL;
+ uint16_t *lens = NULL, *oldlens = NULL, *newlens = NULL;
+ dns_rdatasetiter_t *iter = NULL;
+ dns_rdataset_t set;
+ dns_ttl_t ttl = INT32_MAX;
+ uint32_t flags = LWRDATA_VALIDATED;
+ isc_result_t result = ISC_R_NOMEMORY;
+
+ result = dns_db_allrdatasets(db, node, NULL, 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ rdatas = isc_mem_get(mctx, size * sizeof(*rdatas));
+ if (rdatas == NULL)
+ goto out;
+ lens = isc_mem_get(mctx, size * sizeof(*lens));
+ if (lens == NULL)
+ goto out;
+
+ for (result = dns_rdatasetiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ result = ISC_R_NOMEMORY;
+ dns_rdataset_init(&set);
+ dns_rdatasetiter_current(iter, &set);
+
+ if (set.type != dns_rdatatype_rrsig) {
+ dns_rdataset_disassociate(&set);
+ continue;
+ }
+
+ count = dns_rdataset_count(&set);
+ if (used + count > size) {
+ /* copy & reallocate */
+ oldsize = size;
+ oldrdatas = rdatas;
+ oldlens = lens;
+ rdatas = NULL;
+ lens = NULL;
+
+ size *= 2;
+
+ rdatas = isc_mem_get(mctx, size * sizeof(*rdatas));
+ if (rdatas == NULL)
+ goto out;
+ lens = isc_mem_get(mctx, size * sizeof(*lens));
+ if (lens == NULL)
+ goto out;
+ memmove(rdatas, oldrdatas, used * sizeof(*rdatas));
+ memmove(lens, oldlens, used * sizeof(*lens));
+ isc_mem_put(mctx, oldrdatas,
+ oldsize * sizeof(*oldrdatas));
+ isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens));
+ oldrdatas = NULL;
+ oldlens = NULL;
+ }
+ if (set.ttl < ttl)
+ ttl = set.ttl;
+ if (set.trust != dns_trust_secure)
+ flags &= (~LWRDATA_VALIDATED);
+ result = fill_array(&used, &set, size, rdatas, lens);
+ dns_rdataset_disassociate(&set);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ dns_rdatasetiter_destroy(&iter);
+
+ /*
+ * If necessary, shrink and copy the arrays.
+ */
+ if (size != used) {
+ result = ISC_R_NOMEMORY;
+ newrdatas = isc_mem_get(mctx, used * sizeof(*rdatas));
+ if (newrdatas == NULL)
+ goto out;
+ newlens = isc_mem_get(mctx, used * sizeof(*lens));
+ if (newlens == NULL)
+ goto out;
+ memmove(newrdatas, rdatas, used * sizeof(*rdatas));
+ memmove(newlens, lens, used * sizeof(*lens));
+ isc_mem_put(mctx, rdatas, size * sizeof(*rdatas));
+ isc_mem_put(mctx, lens, size * sizeof(*lens));
+ grbn->rdatas = newrdatas;
+ grbn->rdatalen = newlens;
+ } else {
+ grbn->rdatas = rdatas;
+ grbn->rdatalen = lens;
+ }
+ grbn->nrdatas = used;
+ grbn->ttl = ttl;
+ grbn->flags = flags;
+ return (ISC_R_SUCCESS);
+
+ out:
+ dns_rdatasetiter_destroy(&iter);
+ if (rdatas != NULL)
+ isc_mem_put(mctx, rdatas, size * sizeof(*rdatas));
+ if (lens != NULL)
+ isc_mem_put(mctx, lens, size * sizeof(*lens));
+ if (oldrdatas != NULL)
+ isc_mem_put(mctx, oldrdatas, oldsize * sizeof(*oldrdatas));
+ if (oldlens != NULL)
+ isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens));
+ if (newrdatas != NULL)
+ isc_mem_put(mctx, newrdatas, used * sizeof(*newrdatas));
+ return (result);
+}
+
+static void
+lookup_done(isc_task_t *task, isc_event_t *event) {
+ ns_lwdclient_t *client;
+ ns_lwdclientmgr_t *cm;
+ dns_lookupevent_t *levent;
+ lwres_buffer_t lwb;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ isc_result_t result;
+ lwres_result_t lwresult;
+ isc_region_t r;
+ isc_buffer_t b;
+ lwres_grbnresponse_t *grbn;
+ int i;
+
+ REQUIRE(event != NULL);
+
+ UNUSED(task);
+
+ lwb.base = NULL;
+ client = event->ev_arg;
+ cm = client->clientmgr;
+ INSIST(client->lookup == (dns_lookup_t *)event->ev_sender);
+
+ levent = (dns_lookupevent_t *)event;
+ grbn = &client->grbn;
+
+ ns_lwdclient_log(50, "lookup event result = %s",
+ isc_result_totext(levent->result));
+
+ result = levent->result;
+ if (result != ISC_R_SUCCESS) {
+ dns_lookup_destroy(&client->lookup);
+ isc_event_free(&event);
+ levent = NULL;
+
+ switch (result) {
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NCACHENXDOMAIN:
+ result = ns_lwsearchctx_next(&client->searchctx);
+ if (result != ISC_R_SUCCESS)
+ lwresult = LWRES_R_NOTFOUND;
+ else {
+ start_lookup(client);
+ return;
+ }
+ break;
+ case DNS_R_NXRRSET:
+ case DNS_R_NCACHENXRRSET:
+ lwresult = LWRES_R_TYPENOTFOUND;
+ break;
+ default:
+ lwresult = LWRES_R_FAILURE;
+ }
+ ns_lwdclient_errorpktsend(client, lwresult);
+ return;
+ }
+
+ name = levent->name;
+ b = client->recv_buffer;
+
+ grbn->flags = 0;
+
+ grbn->nrdatas = 0;
+ grbn->rdatas = NULL;
+ grbn->rdatalen = NULL;
+
+ grbn->nsigs = 0;
+ grbn->sigs = NULL;
+ grbn->siglen = NULL;
+
+ result = dns_name_totext(name, true, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ grbn->realname = (char *)isc_buffer_used(&b);
+ grbn->realnamelen = isc_buffer_usedlength(&client->recv_buffer) -
+ isc_buffer_usedlength(&b);
+ ns_lwdclient_log(50, "found name '%.*s'", grbn->realnamelen,
+ grbn->realname);
+
+ grbn->rdclass = cm->view->rdclass;
+ grbn->rdtype = client->rdtype;
+
+ rdataset = levent->rdataset;
+ if (rdataset != NULL) {
+ /* The normal case */
+ grbn->nrdatas = dns_rdataset_count(rdataset);
+ grbn->rdatas = isc_mem_get(cm->mctx, grbn->nrdatas *
+ sizeof(unsigned char *));
+ if (grbn->rdatas == NULL)
+ goto out;
+ grbn->rdatalen = isc_mem_get(cm->mctx, grbn->nrdatas *
+ sizeof(uint16_t));
+ if (grbn->rdatalen == NULL)
+ goto out;
+
+ i = 0;
+ result = fill_array(&i, rdataset, grbn->nrdatas, grbn->rdatas,
+ grbn->rdatalen);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ INSIST(i == grbn->nrdatas);
+ grbn->ttl = rdataset->ttl;
+ if (rdataset->trust == dns_trust_secure)
+ grbn->flags |= LWRDATA_VALIDATED;
+ } else {
+ /* The SIG query case */
+ result = iterate_node(grbn, levent->db, levent->node,
+ cm->mctx);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ }
+ ns_lwdclient_log(50, "filled in %d rdata%s", grbn->nrdatas,
+ (grbn->nrdatas == 1) ? "" : "s");
+
+ sigrdataset = levent->sigrdataset;
+ if (sigrdataset != NULL) {
+ grbn->nsigs = dns_rdataset_count(sigrdataset);
+ grbn->sigs = isc_mem_get(cm->mctx, grbn->nsigs *
+ sizeof(unsigned char *));
+ if (grbn->sigs == NULL)
+ goto out;
+ grbn->siglen = isc_mem_get(cm->mctx, grbn->nsigs *
+ sizeof(uint16_t));
+ if (grbn->siglen == NULL)
+ goto out;
+
+ i = 0;
+ result = fill_array(&i, sigrdataset, grbn->nsigs, grbn->sigs,
+ grbn->siglen);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ INSIST(i == grbn->nsigs);
+ ns_lwdclient_log(50, "filled in %d signature%s", grbn->nsigs,
+ (grbn->nsigs == 1) ? "" : "s");
+ }
+
+ /*
+ * Render the packet.
+ */
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = LWRES_R_SUCCESS;
+
+ lwresult = lwres_grbnresponse_render(cm->lwctx,
+ grbn, &client->pkt, &lwb);
+ if (lwresult != LWRES_R_SUCCESS)
+ goto out;
+
+ isc_mem_put(cm->mctx, grbn->rdatas,
+ grbn->nrdatas * sizeof(unsigned char *));
+ isc_mem_put(cm->mctx, grbn->rdatalen,
+ grbn->nrdatas * sizeof(uint16_t));
+
+ if (grbn->sigs != NULL)
+ isc_mem_put(cm->mctx, grbn->sigs,
+ grbn->nsigs * sizeof(unsigned char *));
+ if (grbn->siglen != NULL)
+ isc_mem_put(cm->mctx, grbn->siglen,
+ grbn->nsigs * sizeof(uint16_t));
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto out2;
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ dns_lookup_destroy(&client->lookup);
+ isc_event_free(&event);
+
+ return;
+
+ out:
+ if (grbn->rdatas != NULL)
+ isc_mem_put(cm->mctx, grbn->rdatas,
+ grbn->nrdatas * sizeof(unsigned char *));
+ if (grbn->rdatalen != NULL)
+ isc_mem_put(cm->mctx, grbn->rdatalen,
+ grbn->nrdatas * sizeof(uint16_t));
+
+ if (grbn->sigs != NULL)
+ isc_mem_put(cm->mctx, grbn->sigs,
+ grbn->nsigs * sizeof(unsigned char *));
+ if (grbn->siglen != NULL)
+ isc_mem_put(cm->mctx, grbn->siglen,
+ grbn->nsigs * sizeof(uint16_t));
+ out2:
+ if (client->lookup != NULL)
+ dns_lookup_destroy(&client->lookup);
+ if (lwb.base != NULL)
+ lwres_context_freemem(cm->lwctx, lwb.base, lwb.length);
+
+ isc_event_free(&event);
+
+ ns_lwdclient_log(50, "error constructing getrrsetbyname response");
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
+
+static void
+start_lookup(ns_lwdclient_t *client) {
+ isc_result_t result;
+ ns_lwdclientmgr_t *cm;
+ dns_fixedname_t absname;
+
+ cm = client->clientmgr;
+
+ INSIST(client->lookup == NULL);
+
+ dns_fixedname_init(&absname);
+
+ /*
+ * Perform search across all search domains until success
+ * is returned. Return in case of failure.
+ */
+ while (ns_lwsearchctx_current(&client->searchctx,
+ dns_fixedname_name(&absname)) != ISC_R_SUCCESS) {
+ if (ns_lwsearchctx_next(&client->searchctx) != ISC_R_SUCCESS) {
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+ }
+
+ result = dns_lookup_create(cm->mctx,
+ dns_fixedname_name(&absname),
+ client->rdtype, cm->view,
+ client->options, cm->task, lookup_done,
+ client, &client->lookup);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+}
+
+static void
+init_grbn(ns_lwdclient_t *client) {
+ client->grbn.rdclass = 0;
+ client->grbn.rdtype = 0;
+ client->grbn.ttl = 0;
+ client->grbn.nrdatas = 0;
+ client->grbn.realname = NULL;
+ client->grbn.realnamelen = 0;
+ client->grbn.rdatas = 0;
+ client->grbn.rdatalen = 0;
+ client->grbn.base = NULL;
+ client->grbn.baselen = 0;
+ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
+}
+
+void
+ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ lwres_grbnrequest_t *req;
+ isc_result_t result;
+ ns_lwdclientmgr_t *cm;
+ isc_buffer_t namebuf;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+ INSIST(client->byaddr == NULL);
+
+ cm = client->clientmgr;
+ req = NULL;
+
+ result = lwres_grbnrequest_parse(cm->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto out;
+ if (req->name == NULL)
+ goto out;
+
+ client->options = 0;
+ if (req->rdclass != cm->view->rdclass)
+ goto out;
+
+ if (req->rdclass == dns_rdataclass_any ||
+ req->rdtype == dns_rdatatype_any)
+ goto out;
+
+ client->rdtype = req->rdtype;
+
+ isc_buffer_init(&namebuf, req->name, req->namelen);
+ isc_buffer_add(&namebuf, req->namelen);
+
+ dns_fixedname_init(&client->query_name);
+ result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
+ &namebuf, NULL, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ ns_lwsearchctx_init(&client->searchctx,
+ cm->listener->manager->search,
+ dns_fixedname_name(&client->query_name),
+ cm->listener->manager->ndots);
+ ns_lwsearchctx_first(&client->searchctx);
+
+ ns_lwdclient_log(50, "client %p looking for type %d",
+ client, client->rdtype);
+
+ /*
+ * We no longer need to keep this around.
+ */
+ lwres_grbnrequest_free(cm->lwctx, &req);
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ init_grbn(client);
+
+ /*
+ * Start the find.
+ */
+ start_lookup(client);
+
+ return;
+
+ /*
+ * We're screwed. Return an error packet to our caller.
+ */
+ out:
+ if (req != NULL)
+ lwres_grbnrequest_free(cm->lwctx, &req);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwdnoop.c b/bin/named/lwdnoop.c
new file mode 100644
index 0000000..75769c9
--- /dev/null
+++ b/bin/named/lwdnoop.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwdnoop.c,v 1.13 2008/01/22 23:28:04 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/util.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+
+void
+ns_lwdclient_processnoop(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ lwres_nooprequest_t *req;
+ lwres_noopresponse_t resp;
+ isc_result_t result;
+ lwres_result_t lwres;
+ isc_region_t r;
+ lwres_buffer_t lwb;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+ INSIST(client->byaddr == NULL);
+
+ req = NULL;
+
+ result = lwres_nooprequest_parse(client->clientmgr->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto send_error;
+
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = LWRES_R_SUCCESS;
+
+ resp.datalength = req->datalength;
+ resp.data = req->data;
+
+ lwres = lwres_noopresponse_render(client->clientmgr->lwctx, &resp,
+ &client->pkt, &lwb);
+ if (lwres != LWRES_R_SUCCESS)
+ goto cleanup_req;
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lwb;
+
+ /*
+ * We can now destroy request.
+ */
+ lwres_nooprequest_free(client->clientmgr->lwctx, &req);
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ return;
+
+ cleanup_lwb:
+ lwres_context_freemem(client->clientmgr->lwctx, lwb.base, lwb.length);
+
+ cleanup_req:
+ lwres_nooprequest_free(client->clientmgr->lwctx, &req);
+
+ send_error:
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwresd.8 b/bin/named/lwresd.8
new file mode 100644
index 0000000..e0eb0d0
--- /dev/null
+++ b/bin/named/lwresd.8
@@ -0,0 +1,250 @@
+.\" Copyright (C) 2000, 2001, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: lwresd
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-01-20
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "LWRESD" "8" "2009\-01\-20" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+lwresd \- lightweight resolver daemon
+.SH "SYNOPSIS"
+.HP \w'\fBlwresd\fR\ 'u
+\fBlwresd\fR [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-C\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-i\ \fR\fB\fIpid\-file\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-P\ \fR\fB\fIport\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [[\fB\-4\fR] | [\fB\-6\fR]]
+.SH "DESCRIPTION"
+.PP
+\fBlwresd\fR
+is the daemon providing name lookup services to clients that use the BIND 9 lightweight resolver library\&. It is essentially a stripped\-down, caching\-only name server that answers queries using the BIND 9 lightweight resolver protocol rather than the DNS protocol\&.
+.PP
+\fBlwresd\fR
+listens for resolver queries on a UDP port on the IPv4 loopback interface, 127\&.0\&.0\&.1\&. This means that
+\fBlwresd\fR
+can only be used by processes running on the local machine\&. By default, UDP port number 921 is used for lightweight resolver requests and responses\&.
+.PP
+Incoming lightweight resolver requests are decoded by the server which then resolves them using the DNS protocol\&. When the DNS lookup completes,
+\fBlwresd\fR
+encodes the answers in the lightweight resolver format and returns them to the client that made the request\&.
+.PP
+If
+/etc/resolv\&.conf
+contains any
+\fBnameserver\fR
+entries,
+\fBlwresd\fR
+sends recursive DNS queries to those servers\&. This is similar to the use of forwarders in a caching name server\&. If no
+\fBnameserver\fR
+entries are present, or if forwarding fails,
+\fBlwresd\fR
+resolves the queries autonomously starting at the root name servers, using a built\-in list of root server hints\&.
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only even if the host machine is capable of IPv6\&.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive\&.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only even if the host machine is capable of IPv4\&.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive\&.
+.RE
+.PP
+\-c \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+/etc/lwresd\&.conf\&.
+\fB\-c\fR
+can not be used with
+\fB\-C\fR\&.
+.RE
+.PP
+\-C \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+/etc/resolv\&.conf\&.
+\fB\-C\fR
+can not be used with
+\fB\-c\fR\&.
+.RE
+.PP
+\-d \fIdebug\-level\fR
+.RS 4
+Set the daemon\*(Aqs debug level to
+\fIdebug\-level\fR\&. Debugging traces from
+\fBlwresd\fR
+become more verbose as the debug level increases\&.
+.RE
+.PP
+\-f
+.RS 4
+Run the server in the foreground (i\&.e\&. do not daemonize)\&.
+.RE
+.PP
+\-g
+.RS 4
+Run the server in the foreground and force all logging to
+stderr\&.
+.RE
+.PP
+\-i \fIpid\-file\fR
+.RS 4
+Use
+\fIpid\-file\fR
+as the PID file instead of the default,
+/var/run/lwresd/lwresd\&.pid\&.
+.RE
+.PP
+\-m \fIflag\fR
+.RS 4
+Turn on memory usage debugging flags\&. Possible flags are
+\fIusage\fR,
+\fItrace\fR,
+\fIrecord\fR,
+\fIsize\fR, and
+\fImctx\fR\&. These correspond to the ISC_MEM_DEBUGXXXX flags described in
+<isc/mem\&.h>\&.
+.RE
+.PP
+\-n \fI#cpus\fR
+.RS 4
+Create
+\fI#cpus\fR
+worker threads to take advantage of multiple CPUs\&. If not specified,
+\fBlwresd\fR
+will try to determine the number of CPUs present and create one thread per CPU\&. If it is unable to determine the number of CPUs, a single worker thread will be created\&.
+.RE
+.PP
+\-P \fIport\fR
+.RS 4
+Listen for lightweight resolver queries on port
+\fIport\fR\&. If not specified, the default is port 921\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Send DNS lookups to port
+\fIport\fR\&. If not specified, the default is port 53\&. This provides a way of testing the lightweight resolver daemon with a name server that listens for queries on a non\-standard port number\&.
+.RE
+.PP
+\-s
+.RS 4
+Write memory usage statistics to
+stdout
+on exit\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
+This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release\&.
+.sp .5v
+.RE
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+\fIdirectory\fR
+after processing the command line arguments, but before reading the configuration file\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBWarning\fR
+.ps -1
+.br
+This option should be used in conjunction with the
+\fB\-u\fR
+option, as chrooting a process running as root doesn\*(Aqt enhance security on most systems; the way
+\fBchroot(2)\fR
+is defined allows a process with root privileges to escape a chroot jail\&.
+.sp .5v
+.RE
+.RE
+.PP
+\-u \fIuser\fR
+.RS 4
+Setuid to
+\fIuser\fR
+after completing privileged operations, such as creating sockets that listen on privileged ports\&.
+.RE
+.PP
+\-v
+.RS 4
+Report the version number and exit\&.
+.RE
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.RS 4
+The default configuration file\&.
+.RE
+.PP
+/var/run/lwresd\&.pid
+.RS 4
+The default process\-id file\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBlwres\fR(3),
+\fBresolver\fR(5)\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000, 2001, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/named/lwresd.c b/bin/named/lwresd.c
new file mode 100644
index 0000000..cdf11f5
--- /dev/null
+++ b/bin/named/lwresd.c
@@ -0,0 +1,892 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwresd.c,v 1.60 2009/09/02 23:48:01 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Main program for the Lightweight Resolver Daemon.
+ *
+ * To paraphrase the old saying about X11, "It's not a lightweight deamon
+ * for resolvers, it's a deamon for lightweight resolvers".
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <named/config.h>
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/lwaddr.h>
+#include <named/lwresd.h>
+#include <named/lwdclient.h>
+#include <named/lwsearch.h>
+#include <named/server.h>
+
+#define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D')
+#define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC)
+
+#define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L')
+#define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC)
+
+#define LWRESD_NCLIENTS_MAX 32768 /*%< max clients per task */
+
+typedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t;
+
+static ns_lwreslistenerlist_t listeners;
+static isc_mutex_t listeners_lock;
+static isc_once_t once = ISC_ONCE_INIT;
+
+
+static void
+initialize_mutex(void) {
+ RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS);
+}
+
+
+/*%
+ * Wrappers around our memory management stuff, for the lwres functions.
+ */
+void *
+ns__lwresd_memalloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+void
+ns__lwresd_memfree(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
+ } while (0)
+
+static isc_result_t
+buffer_putstr(isc_buffer_t *b, const char *s) {
+ unsigned int len = strlen(s);
+ if (isc_buffer_availablelength(b) <= len)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(b, (const unsigned char *)s, len);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Convert a resolv.conf file into a config structure.
+ */
+isc_result_t
+ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
+ cfg_obj_t **configp)
+{
+ char text[4096];
+ char str[16];
+ isc_buffer_t b;
+ lwres_context_t *lwctx = NULL;
+ lwres_conf_t *lwc = NULL;
+ isc_sockaddr_t sa;
+ isc_netaddr_t na;
+ int i;
+ isc_result_t result;
+ lwres_result_t lwresult;
+
+ lwctx = NULL;
+ lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc,
+ ns__lwresd_memfree,
+ LWRES_CONTEXT_SERVERMODE);
+ if (lwresult != LWRES_R_SUCCESS) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile);
+ if (lwresult != LWRES_R_SUCCESS) {
+ result = DNS_R_SYNTAX;
+ goto cleanup;
+ }
+
+ lwc = lwres_conf_get(lwctx);
+ INSIST(lwc != NULL);
+
+ isc_buffer_init(&b, text, sizeof(text));
+
+ CHECK(buffer_putstr(&b, "options {\n"));
+
+ /*
+ * Build the list of forwarders.
+ */
+ if (lwc->nsnext > 0) {
+ CHECK(buffer_putstr(&b, "\tforwarders {\n"));
+
+ for (i = 0; i < lwc->nsnext; i++) {
+ CHECK(lwaddr_sockaddr_fromlwresaddr(
+ &sa,
+ &lwc->nameservers[i],
+ ns_g_port));
+ isc_netaddr_fromsockaddr(&na, &sa);
+ CHECK(buffer_putstr(&b, "\t\t"));
+ CHECK(isc_netaddr_totext(&na, &b));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+
+ /*
+ * Build the sortlist
+ */
+ if (lwc->sortlistnxt > 0) {
+ CHECK(buffer_putstr(&b, "\tsortlist {\n"));
+ CHECK(buffer_putstr(&b, "\t\t{\n"));
+ CHECK(buffer_putstr(&b, "\t\t\tany;\n"));
+ CHECK(buffer_putstr(&b, "\t\t\t{\n"));
+ for (i = 0; i < lwc->sortlistnxt; i++) {
+ lwres_addr_t *lwaddr = &lwc->sortlist[i].addr;
+ lwres_addr_t *lwmask = &lwc->sortlist[i].mask;
+ unsigned int mask;
+
+ CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0));
+ isc_netaddr_fromsockaddr(&na, &sa);
+ result = isc_netaddr_masktoprefixlen(&na, &mask);
+ if (result != ISC_R_SUCCESS) {
+ char addrtext[ISC_NETADDR_FORMATSIZE];
+ isc_netaddr_format(&na, addrtext,
+ sizeof(addrtext));
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD,
+ ISC_LOG_ERROR,
+ "processing sortlist: '%s' is "
+ "not a valid netmask",
+ addrtext);
+ goto cleanup;
+ }
+
+ CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0));
+ isc_netaddr_fromsockaddr(&na, &sa);
+
+ CHECK(buffer_putstr(&b, "\t\t\t\t"));
+ CHECK(isc_netaddr_totext(&na, &b));
+ snprintf(str, sizeof(str), "%u", mask);
+ CHECK(buffer_putstr(&b, "/"));
+ CHECK(buffer_putstr(&b, str));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t\t\t};\n"));
+ CHECK(buffer_putstr(&b, "\t\t};\n"));
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+
+ CHECK(buffer_putstr(&b, "};\n\n"));
+
+ CHECK(buffer_putstr(&b, "lwres {\n"));
+
+ /*
+ * Build the search path
+ */
+ if (lwc->searchnxt > 0) {
+ if (lwc->searchnxt > 0) {
+ CHECK(buffer_putstr(&b, "\tsearch {\n"));
+ for (i = 0; i < lwc->searchnxt; i++) {
+ CHECK(buffer_putstr(&b, "\t\t\""));
+ CHECK(buffer_putstr(&b, lwc->search[i]));
+ CHECK(buffer_putstr(&b, "\";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+ }
+
+ /*
+ * Build the ndots line
+ */
+ if (lwc->ndots != 1) {
+ CHECK(buffer_putstr(&b, "\tndots "));
+ snprintf(str, sizeof(str), "%u", lwc->ndots);
+ CHECK(buffer_putstr(&b, str));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+
+ /*
+ * Build the listen-on line
+ */
+ if (lwc->lwnext > 0) {
+ CHECK(buffer_putstr(&b, "\tlisten-on {\n"));
+
+ for (i = 0; i < lwc->lwnext; i++) {
+ CHECK(lwaddr_sockaddr_fromlwresaddr(&sa,
+ &lwc->lwservers[i],
+ 0));
+ isc_netaddr_fromsockaddr(&na, &sa);
+ CHECK(buffer_putstr(&b, "\t\t"));
+ CHECK(isc_netaddr_totext(&na, &b));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+
+ CHECK(buffer_putstr(&b, "};\n"));
+
+#if 0
+ printf("%.*s\n",
+ (int)isc_buffer_usedlength(&b),
+ (char *)isc_buffer_base(&b));
+#endif
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp));
+
+ cleanup:
+
+ if (lwctx != NULL) {
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+ }
+
+ return (result);
+}
+
+
+/*
+ * Handle lwresd manager objects
+ */
+isc_result_t
+ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
+ ns_lwresd_t **lwresdp)
+{
+ ns_lwresd_t *lwresd;
+ const char *vname;
+ dns_rdataclass_t vclass;
+ const cfg_obj_t *obj, *viewobj, *searchobj;
+ const cfg_listelt_t *element;
+ isc_result_t result;
+
+ INSIST(lwresdp != NULL && *lwresdp == NULL);
+
+ lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t));
+ if (lwresd == NULL)
+ return (ISC_R_NOMEMORY);
+
+ lwresd->mctx = NULL;
+ isc_mem_attach(mctx, &lwresd->mctx);
+ lwresd->view = NULL;
+ lwresd->search = NULL;
+ lwresd->refs = 1;
+
+ obj = NULL;
+ (void)cfg_map_get(lwres, "ndots", &obj);
+ if (obj != NULL)
+ lwresd->ndots = cfg_obj_asuint32(obj);
+ else
+ lwresd->ndots = 1;
+
+ RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS);
+
+ lwresd->shutting_down = false;
+
+ viewobj = NULL;
+ (void)cfg_map_get(lwres, "view", &viewobj);
+ if (viewobj != NULL) {
+ vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name"));
+ obj = cfg_tuple_get(viewobj, "class");
+ result = ns_config_getclass(obj, dns_rdataclass_in, &vclass);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ } else {
+ vname = "_default";
+ vclass = dns_rdataclass_in;
+ }
+
+ result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass,
+ &lwresd->view);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "couldn't find view %s", vname);
+ goto fail;
+ }
+
+ searchobj = NULL;
+ (void)cfg_map_get(lwres, "search", &searchobj);
+ if (searchobj != NULL) {
+ lwresd->search = NULL;
+ result = ns_lwsearchlist_create(lwresd->mctx,
+ &lwresd->search);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "couldn't create searchlist");
+ goto fail;
+ }
+ for (element = cfg_list_first(searchobj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *search;
+ const char *searchstr;
+ isc_buffer_t namebuf;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+
+ search = cfg_listelt_value(element);
+ searchstr = cfg_obj_asstring(search);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_constinit(&namebuf, searchstr,
+ strlen(searchstr));
+ isc_buffer_add(&namebuf, strlen(searchstr));
+ result = dns_name_fromtext(name, &namebuf,
+ dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD,
+ ISC_LOG_WARNING,
+ "invalid name %s in searchlist",
+ searchstr);
+ continue;
+ }
+
+ result = ns_lwsearchlist_append(lwresd->search, name);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD,
+ ISC_LOG_WARNING,
+ "couldn't update searchlist");
+ goto fail;
+ }
+ }
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(lwres, "lwres-tasks", &obj);
+ if (obj != NULL)
+ lwresd->ntasks = cfg_obj_asuint32(obj);
+ else
+ lwresd->ntasks = ns_g_cpus;
+
+ if (lwresd->ntasks == 0)
+ lwresd->ntasks = 1;
+
+ obj = NULL;
+ (void)cfg_map_get(lwres, "lwres-clients", &obj);
+ if (obj != NULL) {
+ lwresd->nclients = cfg_obj_asuint32(obj);
+ if (lwresd->nclients > LWRESD_NCLIENTS_MAX)
+ lwresd->nclients = LWRESD_NCLIENTS_MAX;
+ } else if (ns_g_lwresdonly)
+ lwresd->nclients = 1024;
+ else
+ lwresd->nclients = 256;
+
+ lwresd->magic = LWRESD_MAGIC;
+
+ *lwresdp = lwresd;
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (lwresd->view != NULL)
+ dns_view_detach(&lwresd->view);
+ if (lwresd->search != NULL)
+ ns_lwsearchlist_detach(&lwresd->search);
+ if (lwresd->mctx != NULL)
+ isc_mem_detach(&lwresd->mctx);
+ isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t));
+ return (result);
+}
+
+void
+ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp) {
+ INSIST(VALID_LWRESD(source));
+ INSIST(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+ source->refs++;
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+ns_lwdmanager_detach(ns_lwresd_t **lwresdp) {
+ ns_lwresd_t *lwresd;
+ isc_mem_t *mctx;
+ bool done = false;
+
+ INSIST(lwresdp != NULL && *lwresdp != NULL);
+ INSIST(VALID_LWRESD(*lwresdp));
+
+ lwresd = *lwresdp;
+ *lwresdp = NULL;
+
+ LOCK(&lwresd->lock);
+ INSIST(lwresd->refs > 0);
+ lwresd->refs--;
+ if (lwresd->refs == 0)
+ done = true;
+ UNLOCK(&lwresd->lock);
+
+ if (!done)
+ return;
+
+ dns_view_detach(&lwresd->view);
+ if (lwresd->search != NULL)
+ ns_lwsearchlist_detach(&lwresd->search);
+ mctx = lwresd->mctx;
+ lwresd->magic = 0;
+ isc_mem_put(mctx, lwresd, sizeof(*lwresd));
+ isc_mem_detach(&mctx);
+}
+
+
+/*
+ * Handle listener objects
+ */
+void
+ns_lwreslistener_attach(ns_lwreslistener_t *source,
+ ns_lwreslistener_t **targetp)
+{
+ INSIST(VALID_LWRESLISTENER(source));
+ INSIST(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+ source->refs++;
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+ns_lwreslistener_detach(ns_lwreslistener_t **listenerp) {
+ ns_lwreslistener_t *listener;
+ isc_mem_t *mctx;
+ bool done = false;
+
+ INSIST(listenerp != NULL && *listenerp != NULL);
+ INSIST(VALID_LWRESLISTENER(*listenerp));
+
+ listener = *listenerp;
+
+ LOCK(&listener->lock);
+ INSIST(listener->refs > 0);
+ listener->refs--;
+ if (listener->refs == 0)
+ done = true;
+ UNLOCK(&listener->lock);
+
+ if (!done)
+ return;
+
+ if (listener->manager != NULL)
+ ns_lwdmanager_detach(&listener->manager);
+
+ if (listener->sock != NULL)
+ isc_socket_detach(&listener->sock);
+
+ listener->magic = 0;
+ mctx = listener->mctx;
+ isc_mem_put(mctx, listener, sizeof(*listener));
+ isc_mem_detach(&mctx);
+ listenerp = NULL;
+}
+
+static isc_result_t
+listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd,
+ ns_lwreslistener_t **listenerp)
+{
+ ns_lwreslistener_t *listener;
+ isc_result_t result;
+
+ REQUIRE(listenerp != NULL && *listenerp == NULL);
+
+ listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t));
+ if (listener == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&listener->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t));
+ return (result);
+ }
+
+ listener->magic = LWRESLISTENER_MAGIC;
+ listener->refs = 1;
+
+ listener->sock = NULL;
+
+ listener->manager = NULL;
+ ns_lwdmanager_attach(lwresd, &listener->manager);
+
+ listener->mctx = NULL;
+ isc_mem_attach(mctx, &listener->mctx);
+
+ ISC_LINK_INIT(listener, link);
+ ISC_LIST_INIT(listener->cmgrs);
+
+ *listenerp = listener;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) {
+ isc_socket_t *sock = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ int pf;
+
+ pf = isc_sockaddr_pf(address);
+ if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+ (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ listener->address = *address;
+
+ if (isc_sockaddr_getport(&listener->address) == 0) {
+ in_port_t port;
+ port = lwresd_g_listenport;
+ if (port == 0)
+ port = LWRES_UDP_PORT;
+ isc_sockaddr_setport(&listener->address, port);
+ }
+
+ sock = NULL;
+ result = isc_socket_create(ns_g_socketmgr, pf,
+ isc_sockettype_udp, &sock);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "failed to create lwres socket: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ result = isc_socket_bind(sock, &listener->address,
+ ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&listener->address, socktext,
+ sizeof(socktext));
+ isc_socket_detach(&sock);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "failed to add lwres socket: %s: %s",
+ socktext, isc_result_totext(result));
+ return (result);
+ }
+ listener->sock = sock;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+listener_copysock(ns_lwreslistener_t *oldlistener,
+ ns_lwreslistener_t *newlistener)
+{
+ newlistener->address = oldlistener->address;
+ isc_socket_attach(oldlistener->sock, &newlistener->sock);
+}
+
+static isc_result_t
+listener_startclients(ns_lwreslistener_t *listener) {
+ ns_lwdclientmgr_t *cm, *next;
+ unsigned int i;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_DEBUG(6),
+ "listener_startclients: creating %d "
+ "managers with %d clients each",
+ listener->manager->ntasks, listener->manager->nclients);
+
+ /*
+ * Create the client managers.
+ */
+ for (i = 0; i < listener->manager->ntasks; i++) {
+ result = ns_lwdclientmgr_create(listener,
+ listener->manager->nclients,
+ ns_g_taskmgr);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+
+ /*
+ * If the list is empty return now with the previous
+ * ns_lwdclientmgr_create() result.
+ */
+ if (ISC_LIST_EMPTY(listener->cmgrs))
+ return (result);
+
+ /*
+ * Walk the list of clients and start each one up.
+ */
+ LOCK(&listener->lock);
+ cm = ISC_LIST_HEAD(listener->cmgrs);
+ while (cm != NULL) {
+ next = ISC_LIST_NEXT(cm, link);
+ result = ns_lwdclient_startrecv(cm);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
+ "could not start lwres "
+ "client handler: %s",
+ isc_result_totext(result));
+ cm = next;
+ }
+ UNLOCK(&listener->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+listener_shutdown(ns_lwreslistener_t *listener) {
+ ns_lwdclientmgr_t *cm;
+
+ cm = ISC_LIST_HEAD(listener->cmgrs);
+ while (cm != NULL) {
+ isc_task_shutdown(cm->task);
+ cm = ISC_LIST_NEXT(cm, link);
+ }
+}
+
+static isc_result_t
+find_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) {
+ ns_lwreslistener_t *listener;
+
+ INSIST(listenerp != NULL && *listenerp == NULL);
+
+ for (listener = ISC_LIST_HEAD(listeners);
+ listener != NULL;
+ listener = ISC_LIST_NEXT(listener, link))
+ {
+ if (!isc_sockaddr_equal(address, &listener->address))
+ continue;
+ *listenerp = listener;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+void
+ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm)
+{
+ REQUIRE(VALID_LWRESLISTENER(listener));
+
+ LOCK(&listener->lock);
+ ISC_LIST_UNLINK(listener->cmgrs, cm, link);
+ UNLOCK(&listener->lock);
+}
+
+void
+ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) {
+ REQUIRE(VALID_LWRESLISTENER(listener));
+
+ /*
+ * This does no locking, since it's called early enough that locking
+ * isn't needed.
+ */
+ ISC_LIST_APPEND(listener->cmgrs, cm, link);
+}
+
+static isc_result_t
+configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd,
+ isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners)
+{
+ ns_lwreslistener_t *listener, *oldlistener = NULL;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_result_t result;
+
+ (void)find_listener(address, &oldlistener);
+ listener = NULL;
+ result = listener_create(mctx, lwresd, &listener);
+ if (result != ISC_R_SUCCESS) {
+ isc_sockaddr_format(address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "lwres failed to configure %s: %s",
+ socktext, isc_result_totext(result));
+ return (result);
+ }
+
+ /*
+ * If there's already a listener, don't rebind the socket.
+ */
+ if (oldlistener == NULL) {
+ result = listener_bind(listener, address);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwreslistener_detach(&listener);
+ return (ISC_R_SUCCESS);
+ }
+ } else
+ listener_copysock(oldlistener, listener);
+
+ result = listener_startclients(listener);
+ if (result != ISC_R_SUCCESS) {
+ isc_sockaddr_format(address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "lwres: failed to start %s: %s", socktext,
+ isc_result_totext(result));
+ ns_lwreslistener_detach(&listener);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (oldlistener != NULL) {
+ /*
+ * Remove the old listener from the old list and shut it down.
+ */
+ ISC_LIST_UNLINK(listeners, oldlistener, link);
+ listener_shutdown(oldlistener);
+ ns_lwreslistener_detach(&oldlistener);
+ } else {
+ isc_sockaddr_format(address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
+ "lwres listening on %s", socktext);
+ }
+
+ ISC_LIST_APPEND(*newlisteners, listener, link);
+ return (result);
+}
+
+isc_result_t
+ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
+ const cfg_obj_t *lwreslist = NULL;
+ const cfg_obj_t *lwres = NULL;
+ const cfg_obj_t *listenerslist = NULL;
+ const cfg_listelt_t *element = NULL;
+ ns_lwreslistener_t *listener;
+ ns_lwreslistenerlist_t newlisteners;
+ isc_result_t result;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t *addrs = NULL;
+ ns_lwresd_t *lwresd = NULL;
+ uint32_t count = 0;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(config != NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
+
+ ISC_LIST_INIT(newlisteners);
+
+ result = cfg_map_get(config, "lwres", &lwreslist);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ LOCK(&listeners_lock);
+ /*
+ * Run through the new lwres address list, noting sockets that
+ * are already being listened on and moving them to the new list.
+ *
+ * Identifying duplicates addr/port combinations is left to either
+ * the underlying config code, or to the bind attempt getting an
+ * address-in-use error.
+ */
+ for (element = cfg_list_first(lwreslist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ in_port_t port;
+
+ lwres = cfg_listelt_value(element);
+ CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd));
+
+ port = lwresd_g_listenport;
+ if (port == 0)
+ port = LWRES_UDP_PORT;
+
+ listenerslist = NULL;
+ (void)cfg_map_get(lwres, "listen-on", &listenerslist);
+ if (listenerslist == NULL) {
+ struct in_addr localhost;
+ isc_sockaddr_t address;
+
+ localhost.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&address, &localhost, port);
+ CHECK(configure_listener(&address, lwresd, mctx,
+ &newlisteners));
+ } else {
+ uint32_t i;
+
+ CHECK(ns_config_getiplist(config, listenerslist,
+ port, mctx, &addrs, NULL,
+ &count));
+ for (i = 0; i < count; i++)
+ CHECK(configure_listener(&addrs[i], lwresd,
+ mctx, &newlisteners));
+ ns_config_putiplist(mctx, &addrs, NULL, count);
+ }
+ ns_lwdmanager_detach(&lwresd);
+ }
+
+ /*
+ * Shutdown everything on the listeners list, and remove them from
+ * the list. Then put all of the new listeners on it.
+ */
+
+ while (!ISC_LIST_EMPTY(listeners)) {
+ listener = ISC_LIST_HEAD(listeners);
+ ISC_LIST_UNLINK(listeners, listener, link);
+
+ isc_sockaddr_format(&listener->address,
+ socktext, sizeof(socktext));
+
+ listener_shutdown(listener);
+ ns_lwreslistener_detach(&listener);
+
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
+ "lwres no longer listening on %s", socktext);
+ }
+
+ cleanup:
+ ISC_LIST_APPENDLIST(listeners, newlisteners, link);
+
+ if (addrs != NULL)
+ ns_config_putiplist(mctx, &addrs, NULL, count);
+
+ if (lwresd != NULL)
+ ns_lwdmanager_detach(&lwresd);
+
+ UNLOCK(&listeners_lock);
+
+ return (result);
+}
+
+void
+ns_lwresd_shutdown(void) {
+ ns_lwreslistener_t *listener;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
+
+ while (!ISC_LIST_EMPTY(listeners)) {
+ listener = ISC_LIST_HEAD(listeners);
+ ISC_LIST_UNLINK(listeners, listener, link);
+ ns_lwreslistener_detach(&listener);
+ }
+}
diff --git a/bin/named/lwresd.docbook b/bin/named/lwresd.docbook
new file mode 100644
index 0000000..f267f0d
--- /dev/null
+++ b/bin/named/lwresd.docbook
@@ -0,0 +1,364 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.lwresd">
+ <info>
+ <date>2009-01-20</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>lwresd</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>lwresd</application></refname>
+ <refpurpose>lightweight resolver daemon</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>lwresd</command>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-C <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-g</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">pid-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">#cpus</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">port</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-u <replaceable class="parameter">user</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+
+ <para><command>lwresd</command>
+ is the daemon providing name lookup
+ services to clients that use the BIND 9 lightweight resolver
+ library. It is essentially a stripped-down, caching-only name
+ server that answers queries using the BIND 9 lightweight
+ resolver protocol rather than the DNS protocol.
+ </para>
+
+ <para><command>lwresd</command>
+ listens for resolver queries on a
+ UDP port on the IPv4 loopback interface, 127.0.0.1. This
+ means that <command>lwresd</command> can only be used by
+ processes running on the local machine. By default, UDP port
+ number 921 is used for lightweight resolver requests and
+ responses.
+ </para>
+ <para>
+ Incoming lightweight resolver requests are decoded by the
+ server which then resolves them using the DNS protocol. When
+ the DNS lookup completes, <command>lwresd</command> encodes
+ the answers in the lightweight resolver format and returns
+ them to the client that made the request.
+ </para>
+ <para>
+ If <filename>/etc/resolv.conf</filename> contains any
+ <option>nameserver</option> entries, <command>lwresd</command>
+ sends recursive DNS queries to those servers. This is similar
+ to the use of forwarders in a caching name server. If no
+ <option>nameserver</option> entries are present, or if
+ forwarding fails, <command>lwresd</command> resolves the
+ queries autonomously starting at the root name servers, using
+ a built-in list of root server hints.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <!-- this is in source but not mentioned? does this matter? -->
+ <varlistentry>
+ <term>-c <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable> as the
+ configuration file instead of the default,
+ <filename>/etc/lwresd.conf</filename>.
+ <!-- Should this be an absolute path name? -->
+ <option>-c</option> can not be used with <option>-C</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable> as the
+ configuration file instead of the default,
+ <filename>/etc/resolv.conf</filename>.
+ <option>-C</option> can not be used with <option>-c</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">debug-level</replaceable></term>
+ <listitem>
+ <para>
+ Set the daemon's debug level to <replaceable class="parameter">debug-level</replaceable>.
+ Debugging traces from <command>lwresd</command> become
+ more verbose as the debug level increases.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Run the server in the foreground (i.e. do not daemonize).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Run the server in the foreground and force all logging
+ to <filename>stderr</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">pid-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">pid-file</replaceable> as the
+ PID file instead of the default,
+ <filename>/var/run/lwresd/lwresd.pid</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Turn on memory usage debugging flags. Possible flags are
+ <replaceable class="parameter">usage</replaceable>,
+ <replaceable class="parameter">trace</replaceable>,
+ <replaceable class="parameter">record</replaceable>,
+ <replaceable class="parameter">size</replaceable>, and
+ <replaceable class="parameter">mctx</replaceable>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <filename>&lt;isc/mem.h&gt;</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">#cpus</replaceable></term>
+ <listitem>
+ <para>
+ Create <replaceable class="parameter">#cpus</replaceable> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <command>lwresd</command> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Listen for lightweight resolver queries on port
+ <replaceable class="parameter">port</replaceable>. If
+ not specified, the default is port 921.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Send DNS lookups to port <replaceable class="parameter">port</replaceable>. If not
+ specified, the default is port 53. This provides a
+ way of testing the lightweight resolver daemon with a
+ name server that listens for queries on a non-standard
+ port number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Write memory usage statistics to <filename>stdout</filename>
+ on exit.
+ </para>
+ <note>
+ <para>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>Chroot
+ to <replaceable class="parameter">directory</replaceable> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </para>
+ <warning>
+ <para>
+ This option should be used in conjunction with the
+ <option>-u</option> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <function>chroot(2)</function> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">user</replaceable></term>
+ <listitem>
+ <para>Setuid
+ to <replaceable class="parameter">user</replaceable> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Report the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+
+ <variablelist>
+
+ <varlistentry>
+ <term><filename>/etc/resolv.conf</filename></term>
+ <listitem>
+ <para>
+ The default configuration file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/var/run/lwresd.pid</filename></term>
+ <listitem>
+ <para>
+ The default process-id file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwres</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>resolver</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/named/lwresd.html b/bin/named/lwresd.html
new file mode 100644
index 0000000..128e89f
--- /dev/null
+++ b/bin/named/lwresd.html
@@ -0,0 +1,295 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000, 2001, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwresd</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.lwresd"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">lwresd</span>
+ &#8212; lightweight resolver daemon
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">lwresd</code>
+ [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>]
+ [<code class="option">-C <em class="replaceable"><code>config-file</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>]
+ [<code class="option">-f</code>]
+ [<code class="option">-g</code>]
+ [<code class="option">-i <em class="replaceable"><code>pid-file</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>]
+ [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>]
+ [<code class="option">-P <em class="replaceable"><code>port</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>port</code></em></code>]
+ [<code class="option">-s</code>]
+ [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-u <em class="replaceable"><code>user</code></em></code>]
+ [<code class="option">-v</code>]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+
+ <p><span class="command"><strong>lwresd</strong></span>
+ is the daemon providing name lookup
+ services to clients that use the BIND 9 lightweight resolver
+ library. It is essentially a stripped-down, caching-only name
+ server that answers queries using the BIND 9 lightweight
+ resolver protocol rather than the DNS protocol.
+ </p>
+
+ <p><span class="command"><strong>lwresd</strong></span>
+ listens for resolver queries on a
+ UDP port on the IPv4 loopback interface, 127.0.0.1. This
+ means that <span class="command"><strong>lwresd</strong></span> can only be used by
+ processes running on the local machine. By default, UDP port
+ number 921 is used for lightweight resolver requests and
+ responses.
+ </p>
+ <p>
+ Incoming lightweight resolver requests are decoded by the
+ server which then resolves them using the DNS protocol. When
+ the DNS lookup completes, <span class="command"><strong>lwresd</strong></span> encodes
+ the answers in the lightweight resolver format and returns
+ them to the client that made the request.
+ </p>
+ <p>
+ If <code class="filename">/etc/resolv.conf</code> contains any
+ <code class="option">nameserver</code> entries, <span class="command"><strong>lwresd</strong></span>
+ sends recursive DNS queries to those servers. This is similar
+ to the use of forwarders in a caching name server. If no
+ <code class="option">nameserver</code> entries are present, or if
+ forwarding fails, <span class="command"><strong>lwresd</strong></span> resolves the
+ queries autonomously starting at the root name servers, using
+ a built-in list of root server hints.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/lwresd.conf</code>.
+
+ <code class="option">-c</code> can not be used with <code class="option">-C</code>.
+ </p>
+ </dd>
+<dt><span class="term">-C <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/resolv.conf</code>.
+ <code class="option">-C</code> can not be used with <code class="option">-c</code>.
+ </p>
+ </dd>
+<dt><span class="term">-d <em class="replaceable"><code>debug-level</code></em></span></dt>
+<dd>
+ <p>
+ Set the daemon's debug level to <em class="replaceable"><code>debug-level</code></em>.
+ Debugging traces from <span class="command"><strong>lwresd</strong></span> become
+ more verbose as the debug level increases.
+ </p>
+ </dd>
+<dt><span class="term">-f</span></dt>
+<dd>
+ <p>
+ Run the server in the foreground (i.e. do not daemonize).
+ </p>
+ </dd>
+<dt><span class="term">-g</span></dt>
+<dd>
+ <p>
+ Run the server in the foreground and force all logging
+ to <code class="filename">stderr</code>.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>pid-file</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>pid-file</code></em> as the
+ PID file instead of the default,
+ <code class="filename">/var/run/lwresd/lwresd.pid</code>.
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd>
+ <p>
+ Turn on memory usage debugging flags. Possible flags are
+ <em class="replaceable"><code>usage</code></em>,
+ <em class="replaceable"><code>trace</code></em>,
+ <em class="replaceable"><code>record</code></em>,
+ <em class="replaceable"><code>size</code></em>, and
+ <em class="replaceable"><code>mctx</code></em>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <code class="filename">&lt;isc/mem.h&gt;</code>.
+ </p>
+ </dd>
+<dt><span class="term">-n <em class="replaceable"><code>#cpus</code></em></span></dt>
+<dd>
+ <p>
+ Create <em class="replaceable"><code>#cpus</code></em> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <span class="command"><strong>lwresd</strong></span> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </p>
+ </dd>
+<dt><span class="term">-P <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Listen for lightweight resolver queries on port
+ <em class="replaceable"><code>port</code></em>. If
+ not specified, the default is port 921.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Send DNS lookups to port <em class="replaceable"><code>port</code></em>. If not
+ specified, the default is port 53. This provides a
+ way of testing the lightweight resolver daemon with a
+ name server that listens for queries on a non-standard
+ port number.
+ </p>
+ </dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+ <p>
+ Write memory usage statistics to <code class="filename">stdout</code>
+ on exit.
+ </p>
+ <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ <p>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </p>
+ </div>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>Chroot
+ to <em class="replaceable"><code>directory</code></em> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </p>
+ <div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+ <p>
+ This option should be used in conjunction with the
+ <code class="option">-u</code> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <code class="function">chroot(2)</code> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </p>
+ </div>
+ </dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd>
+ <p>Setuid
+ to <em class="replaceable"><code>user</code></em> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Report the version number and exit.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>FILES</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="filename">/etc/resolv.conf</code></span></dt>
+<dd>
+ <p>
+ The default configuration file.
+ </p>
+ </dd>
+<dt><span class="term"><code class="filename">/var/run/lwresd.pid</code></span></dt>
+<dd>
+ <p>
+ The default process-id file.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">lwres</span>(3)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">resolver</span>(5)
+ </span>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/named/lwsearch.c b/bin/named/lwsearch.c
new file mode 100644
index 0000000..cd068bd
--- /dev/null
+++ b/bin/named/lwsearch.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwsearch.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/types.h>
+
+#include <named/lwsearch.h>
+#include <named/types.h>
+
+#define LWSEARCHLIST_MAGIC ISC_MAGIC('L', 'W', 'S', 'L')
+#define VALID_LWSEARCHLIST(l) ISC_MAGIC_VALID(l, LWSEARCHLIST_MAGIC)
+
+isc_result_t
+ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp) {
+ ns_lwsearchlist_t *list;
+ isc_result_t result;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(listp != NULL && *listp == NULL);
+
+ list = isc_mem_get(mctx, sizeof(ns_lwsearchlist_t));
+ if (list == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&list->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t));
+ return (result);
+ }
+ list->mctx = NULL;
+ isc_mem_attach(mctx, &list->mctx);
+ list->refs = 1;
+ ISC_LIST_INIT(list->names);
+ list->magic = LWSEARCHLIST_MAGIC;
+
+ *listp = list;
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target) {
+ REQUIRE(VALID_LWSEARCHLIST(source));
+ REQUIRE(target != NULL && *target == NULL);
+
+ LOCK(&source->lock);
+ INSIST(source->refs > 0);
+ source->refs++;
+ INSIST(source->refs != 0);
+ UNLOCK(&source->lock);
+
+ *target = source;
+}
+
+void
+ns_lwsearchlist_detach(ns_lwsearchlist_t **listp) {
+ ns_lwsearchlist_t *list;
+ isc_mem_t *mctx;
+
+ REQUIRE(listp != NULL);
+ list = *listp;
+ REQUIRE(VALID_LWSEARCHLIST(list));
+
+ LOCK(&list->lock);
+ INSIST(list->refs > 0);
+ list->refs--;
+ UNLOCK(&list->lock);
+
+ *listp = NULL;
+ if (list->refs != 0)
+ return;
+
+ mctx = list->mctx;
+ while (!ISC_LIST_EMPTY(list->names)) {
+ dns_name_t *name = ISC_LIST_HEAD(list->names);
+ ISC_LIST_UNLINK(list->names, name, link);
+ dns_name_free(name, list->mctx);
+ isc_mem_put(list->mctx, name, sizeof(dns_name_t));
+ }
+ list->magic = 0;
+ isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t));
+ isc_mem_detach(&mctx);
+}
+
+isc_result_t
+ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name) {
+ dns_name_t *newname;
+ isc_result_t result;
+
+ REQUIRE(VALID_LWSEARCHLIST(list));
+ REQUIRE(name != NULL);
+
+ newname = isc_mem_get(list->mctx, sizeof(dns_name_t));
+ if (newname == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_name_init(newname, NULL);
+ result = dns_name_dup(name, list->mctx, newname);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(list->mctx, newname, sizeof(dns_name_t));
+ return (result);
+ }
+ ISC_LINK_INIT(newname, link);
+ ISC_LIST_APPEND(list->names, newname, link);
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list,
+ dns_name_t *name, unsigned int ndots)
+{
+ INSIST(sctx != NULL);
+ sctx->relname = name;
+ sctx->searchname = NULL;
+ sctx->doneexact = false;
+ sctx->exactfirst = false;
+ sctx->ndots = ndots;
+ if (dns_name_isabsolute(name) || list == NULL) {
+ sctx->list = NULL;
+ return;
+ }
+ sctx->list = list;
+ sctx->searchname = ISC_LIST_HEAD(sctx->list->names);
+ if (dns_name_countlabels(name) > ndots)
+ sctx->exactfirst = true;
+}
+
+void
+ns_lwsearchctx_first(ns_lwsearchctx_t *sctx) {
+ REQUIRE(sctx != NULL);
+ UNUSED(sctx);
+}
+
+isc_result_t
+ns_lwsearchctx_next(ns_lwsearchctx_t *sctx) {
+ REQUIRE(sctx != NULL);
+
+ if (sctx->list == NULL)
+ return (ISC_R_NOMORE);
+
+ if (sctx->searchname == NULL) {
+ if (sctx->exactfirst || sctx->doneexact)
+ return (ISC_R_NOMORE);
+ sctx->doneexact = true;
+ } else {
+ if (sctx->exactfirst && !sctx->doneexact)
+ sctx->doneexact = true;
+ else {
+ sctx->searchname = ISC_LIST_NEXT(sctx->searchname,
+ link);
+ if (sctx->searchname == NULL && sctx->doneexact)
+ return (ISC_R_NOMORE);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname) {
+ dns_name_t *tname;
+ bool useexact = false;
+
+ REQUIRE(sctx != NULL);
+
+ if (sctx->list == NULL ||
+ sctx->searchname == NULL ||
+ (sctx->exactfirst && !sctx->doneexact))
+ useexact = true;
+
+ if (useexact) {
+ if (dns_name_isabsolute(sctx->relname))
+ tname = NULL;
+ else
+ tname = dns_rootname;
+ } else
+ tname = sctx->searchname;
+
+ return (dns_name_concatenate(sctx->relname, tname, absname, NULL));
+}
diff --git a/bin/named/main.c b/bin/named/main.c
new file mode 100644
index 0000000..8cec1ad
--- /dev/null
+++ b/bin/named/main.c
@@ -0,0 +1,1543 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/backtrace.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/httpd.h>
+#include <isc/os.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/resource.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <isccc/result.h>
+
+#include <dns/dispatch.h>
+#include <dns/dyndb.h>
+#include <dns/name.h>
+#include <dns/result.h>
+#include <dns/resolver.h>
+#include <dns/view.h>
+
+#include <dst/result.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#include <dlz/dlz_dlopen_driver.h>
+
+#ifdef HAVE_GPERFTOOLS_PROFILER
+#include <gperftools/profiler.h>
+#endif
+
+
+/*
+ * Defining NS_MAIN provides storage declarations (rather than extern)
+ * for variables in named/globals.h.
+ */
+#define NS_MAIN 1
+
+#include <named/builtin.h>
+#include <named/control.h>
+#include <named/fuzz.h>
+#include <named/globals.h> /* Explicit, though named/log.h includes it. */
+#include <named/interfacemgr.h>
+#include <named/log.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/lwresd.h>
+#include <named/main.h>
+#include <named/seccomp.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
+
+#ifdef OPENSSL
+#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#endif
+#ifdef HAVE_LIBXML2
+#include <libxml/xmlversion.h>
+#endif
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+/*
+ * Include header files for database drivers here.
+ */
+/* #include "xxdb.h" */
+
+#ifdef CONTRIB_DLZ
+/*
+ * Include contributed DLZ drivers if appropriate.
+ */
+#include <dlz/dlz_drivers.h>
+#endif
+
+/*
+ * The maximum number of stack frames to dump on assertion failure.
+ */
+#ifndef BACKTRACE_MAXFRAME
+#define BACKTRACE_MAXFRAME 128
+#endif
+
+LIBISC_EXTERNAL_DATA extern int isc_dscp_check_value;
+LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_hour;
+LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_day;
+LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_month;
+
+static bool want_stats = false;
+static char program_name[ISC_DIR_NAMEMAX] = "named";
+static char absolute_conffile[ISC_DIR_PATHMAX];
+static char saved_command_line[512];
+static char version[512];
+static unsigned int maxsocks = 0;
+static int maxudp = 0;
+
+void
+ns_main_earlywarning(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (ns_g_lctx != NULL) {
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_main_earlyfatal(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (ns_g_lctx != NULL) {
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ format, args);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond) ISC_PLATFORM_NORETURN_POST;
+
+static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond)
+{
+ void *tracebuf[BACKTRACE_MAXFRAME];
+ int i, nframes;
+ isc_result_t result;
+ const char *logsuffix = "";
+ const char *fname;
+
+ /*
+ * Handle assertion failures.
+ */
+
+ if (ns_g_lctx != NULL) {
+ /*
+ * Reset the assertion callback in case it is the log
+ * routines causing the assertion.
+ */
+ isc_assertion_setcallback(NULL);
+
+ result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME,
+ &nframes);
+ if (result == ISC_R_SUCCESS && nframes > 0)
+ logsuffix = ", back trace";
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "%s:%d: %s(%s) failed%s", file, line,
+ isc_assertion_typetotext(type), cond, logsuffix);
+ if (result == ISC_R_SUCCESS) {
+ for (i = 0; i < nframes; i++) {
+ unsigned long offset;
+
+ fname = NULL;
+ result = isc_backtrace_getsymbol(tracebuf[i],
+ &fname,
+ &offset);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN,
+ ISC_LOG_CRITICAL,
+ "#%d %p in %s()+0x%lx", i,
+ tracebuf[i], fname,
+ offset);
+ } else {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN,
+ ISC_LOG_CRITICAL,
+ "#%d %p in ??", i,
+ tracebuf[i]);
+ }
+ }
+ }
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 (ns_g_coreok)
+ abort();
+ exit(1);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+library_fatal_error(const char *file, int line, const char *format,
+ va_list args)
+ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST;
+
+static void
+library_fatal_error(const char *file, int line, const char *format,
+ va_list args)
+{
+ /*
+ * Handle isc_error_fatal() calls from our libraries.
+ */
+
+ if (ns_g_lctx != NULL) {
+ /*
+ * Reset the error callback in case it is the log
+ * routines causing the assertion.
+ */
+ isc_error_setfatal(NULL);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "%s:%d: fatal error:", file, line);
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ format, args);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to fatal error in library)");
+ } else {
+ fprintf(stderr, "%s:%d: fatal error: ", file, line);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+
+ if (ns_g_coreok)
+ abort();
+ exit(1);
+}
+
+static void
+library_unexpected_error(const char *file, int line, const char *format,
+ va_list args) ISC_FORMAT_PRINTF(3, 0);
+
+static void
+library_unexpected_error(const char *file, int line, const char *format,
+ va_list args)
+{
+ /*
+ * Handle isc_error_unexpected() calls from our libraries.
+ */
+
+ if (ns_g_lctx != NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
+ "%s:%d: unexpected error:", file, line);
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
+ format, args);
+ } else {
+ fprintf(stderr, "%s:%d: fatal error: ", file, line);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+static void
+lwresd_usage(void) {
+ fprintf(stderr,
+ "usage: lwresd [-4|-6] [-c conffile | -C resolvconffile] "
+ "[-d debuglevel] [-f|-g]\n"
+ " [-i pidfile] [-n number_of_cpus] "
+ "[-p port] [-P listen-port]\n"
+ " [-s] [-S sockets] [-t chrootdir] [-u username] "
+ "[-U listeners]\n"
+ " [-m {usage|trace|record|size|mctx}]\n"
+ "usage: lwresd [-v|-V]\n");
+}
+
+static void
+usage(void) {
+ if (ns_g_lwresdonly) {
+ lwresd_usage();
+ return;
+ }
+ fprintf(stderr,
+ "usage: named [-4|-6] [-c conffile] [-d debuglevel] "
+ "[-E engine] [-f|-g]\n"
+ " [-n number_of_cpus] [-p port] [-s] "
+ "[-S sockets] [-t chrootdir]\n"
+ " [-u username] [-U listeners] "
+ "[-m {usage|trace|record|size|mctx}]\n"
+ "usage: named [-v|-V]\n");
+}
+
+static void
+save_command_line(int argc, char *argv[]) {
+ int i;
+ char *src;
+ char *dst;
+ char *eob;
+ const char truncated[] = "...";
+ bool quoted = false;
+
+ dst = saved_command_line;
+ eob = saved_command_line + sizeof(saved_command_line);
+
+ for (i = 1; i < argc && dst < eob; i++) {
+ *dst++ = ' ';
+
+ src = argv[i];
+ while (*src != '\0' && dst < eob) {
+ /*
+ * This won't perfectly produce a shell-independent
+ * pastable command line in all circumstances, but
+ * comes close, and for practical purposes will
+ * nearly always be fine.
+ */
+ if (quoted || isalnum(*src & 0xff) ||
+ *src == '-' || *src == '_' ||
+ *src == '.' || *src == '/') {
+ *dst++ = *src++;
+ quoted = false;
+ } else {
+ *dst++ = '\\';
+ quoted = true;
+ }
+ }
+ }
+
+ INSIST(sizeof(saved_command_line) >= sizeof(truncated));
+
+ if (dst == eob)
+ strcpy(eob - sizeof(truncated), truncated);
+ else
+ *dst = '\0';
+}
+
+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')
+ ns_main_earlyfatal("%s '%s' must be numeric", desc, arg);
+ if (tmp < 0 || tmp != ltmp)
+ ns_main_earlyfatal("%s '%s' out of range", desc, arg);
+ return (tmp);
+}
+
+static struct flag_def {
+ const char *name;
+ unsigned int value;
+} mem_debug_flags[] = {
+ { "none", 0},
+ { "trace", ISC_MEM_DEBUGTRACE },
+ { "record", ISC_MEM_DEBUGRECORD },
+ { "usage", ISC_MEM_DEBUGUSAGE },
+ { "size", ISC_MEM_DEBUGSIZE },
+ { "mctx", ISC_MEM_DEBUGCTX },
+ { NULL, 0 }
+};
+
+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;
+ *ret |= def->value;
+ goto found;
+ }
+ }
+ ns_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg);
+ found:
+ if (clear || (*end == '\0'))
+ break;
+ arg = end + 1;
+ }
+
+ if (clear)
+ *ret = 0;
+}
+
+static void
+parse_fuzz_arg(void) {
+ if (!strncmp(isc_commandline_argument, "client:", 7)) {
+ ns_g_fuzz_named_addr = isc_commandline_argument + 7;
+ ns_g_fuzz_type = ns_fuzz_client;
+ } else if (!strncmp(isc_commandline_argument, "tcp:", 4)) {
+ ns_g_fuzz_named_addr = isc_commandline_argument + 4;
+ ns_g_fuzz_type = ns_fuzz_tcpclient;
+ } else if (!strncmp(isc_commandline_argument, "resolver:", 9)) {
+ ns_g_fuzz_named_addr = isc_commandline_argument + 9;
+ ns_g_fuzz_type = ns_fuzz_resolver;
+ } else if (!strncmp(isc_commandline_argument, "http:", 5)) {
+ ns_g_fuzz_named_addr = isc_commandline_argument + 5;
+ ns_g_fuzz_type = ns_fuzz_http;
+ } else if (!strncmp(isc_commandline_argument, "rndc:", 5)) {
+ ns_g_fuzz_named_addr = isc_commandline_argument + 5;
+ ns_g_fuzz_type = ns_fuzz_rndc;
+ } else {
+ ns_main_earlyfatal("unknown fuzzing type '%s'",
+ isc_commandline_argument);
+ }
+}
+
+static void
+parse_T_opt(char *option) {
+ const char *p;
+ /*
+ * force the server to behave (or misbehave) in
+ * specified ways for testing purposes.
+ *
+ * clienttest: make clients single shot with their
+ * own memory context.
+ * delay=xxxx: delay client responses by xxxx ms to
+ * simulate remote servers.
+ * dscp=x: check that dscp values are as
+ * expected and assert otherwise.
+ */
+ if (!strcmp(option, "clienttest")) {
+ ns_g_clienttest = true;
+ } else if (!strncmp(option, "delay=", 6)) {
+ ns_g_delay = atoi(option + 6);
+ } else if (!strcmp(option, "dropedns")) {
+ ns_g_dropedns = true;
+ } else if (!strncmp(option, "dscp=", 5)) {
+ isc_dscp_check_value = atoi(option + 5);
+ } else if (!strcmp(option, "fixedlocal")) {
+ ns_g_fixedlocal = true;
+ } else if (!strcmp(option, "keepstderr")) {
+ ns_g_keepstderr = true;
+ } else if (!strcmp(option, "noaa")) {
+ ns_g_noaa = true;
+ } else if (!strcmp(option, "noedns")) {
+ ns_g_noedns = true;
+ } else if (!strcmp(option, "nonearest")) {
+ ns_g_nonearest = true;
+ } else if (!strcmp(option, "nosoa")) {
+ ns_g_nosoa = true;
+ } else if (!strcmp(option, "nosyslog")) {
+ ns_g_nosyslog = true;
+ } else if (!strcmp(option, "notcp")) {
+ ns_g_notcp = true;
+ } else if (!strcmp(option, "maxudp512")) {
+ maxudp = 512;
+ } else if (!strcmp(option, "maxudp1460")) {
+ maxudp = 1460;
+ } else if (!strncmp(option, "maxudp=", 7)) {
+ maxudp = atoi(option + 7);
+ } else if (!strncmp(option, "mkeytimers=", 11)) {
+ p = strtok(option + 11, "/");
+ if (p == NULL) {
+ ns_main_earlyfatal("bad mkeytimer");
+ }
+
+ dns_zone_mkey_hour = atoi(p);
+ if (dns_zone_mkey_hour == 0) {
+ ns_main_earlyfatal("bad mkeytimer");
+ }
+
+ p = strtok(NULL, "/");
+ 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)
+ ns_main_earlyfatal("bad mkeytimer");
+
+ p = strtok(NULL, "/");
+ 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) {
+ ns_main_earlyfatal("bad mkeytimer");
+ }
+ } else if (!strcmp(option, "sigvalinsecs")) {
+ ns_g_sigvalinsecs = true;
+ } else if (!strncmp(option, "tat=", 4)) {
+ ns_g_tat_interval = atoi(option + 4);
+ } else {
+ fprintf(stderr, "unknown -T flag '%s\n", option);
+ }
+}
+
+static void
+parse_command_line(int argc, char *argv[]) {
+ int ch;
+ int port;
+ const char *p;
+
+ save_command_line(argc, argv);
+
+ /*
+ * NS_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, NS_MAIN_ARGS)) != -1) {
+ switch (ch) {
+ case '4':
+ if (ns_g_disable4)
+ ns_main_earlyfatal("cannot specify -4 and -6");
+ if (isc_net_probeipv4() != ISC_R_SUCCESS)
+ ns_main_earlyfatal("IPv4 not supported by OS");
+ isc_net_disableipv6();
+ ns_g_disable6 = true;
+ break;
+ case '6':
+ if (ns_g_disable6)
+ ns_main_earlyfatal("cannot specify -4 and -6");
+ if (isc_net_probeipv6() != ISC_R_SUCCESS)
+ ns_main_earlyfatal("IPv6 not supported by OS");
+ isc_net_disableipv4();
+ ns_g_disable4 = true;
+ break;
+ case 'A':
+ parse_fuzz_arg();
+ break;
+ case 'c':
+ ns_g_conffile = isc_commandline_argument;
+ lwresd_g_conffile = isc_commandline_argument;
+ if (lwresd_g_useresolvconf)
+ ns_main_earlyfatal("cannot specify -c and -C");
+ ns_g_conffileset = true;
+ break;
+ case 'C':
+ lwresd_g_resolvconffile = isc_commandline_argument;
+ if (ns_g_conffileset)
+ ns_main_earlyfatal("cannot specify -c and -C");
+ lwresd_g_useresolvconf = true;
+ break;
+ case 'd':
+ ns_g_debuglevel = parse_int(isc_commandline_argument,
+ "debug level");
+ break;
+ case 'D':
+ /* Descriptive comment for 'ps'. */
+ break;
+ case 'E':
+ ns_g_engine = isc_commandline_argument;
+ break;
+ case 'f':
+ ns_g_foreground = true;
+ break;
+ case 'g':
+ ns_g_foreground = true;
+ ns_g_logstderr = true;
+ break;
+ /* XXXBEW -i should be removed */
+ case 'i':
+ lwresd_g_defaultpidfile = isc_commandline_argument;
+ break;
+ case 'l':
+ ns_g_lwresdonly = true;
+ break;
+ case 'L':
+ ns_g_logfile = isc_commandline_argument;
+ break;
+ case 'M':
+ if (strcmp(isc_commandline_argument, "external") == 0)
+ isc_mem_defaultflags = 0;
+ break;
+ case 'm':
+ set_flags(isc_commandline_argument, mem_debug_flags,
+ &isc_mem_debugging);
+ break;
+ case 'N': /* Deprecated. */
+ case 'n':
+ ns_g_cpus = parse_int(isc_commandline_argument,
+ "number of cpus");
+ if (ns_g_cpus == 0)
+ ns_g_cpus = 1;
+ break;
+ case 'p':
+ port = parse_int(isc_commandline_argument, "port");
+ if (port < 1 || port > 65535)
+ ns_main_earlyfatal("port '%s' out of range",
+ isc_commandline_argument);
+ ns_g_port = port;
+ break;
+ /* XXXBEW Should -P be removed? */
+ case 'P':
+ port = parse_int(isc_commandline_argument, "port");
+ if (port < 1 || port > 65535)
+ ns_main_earlyfatal("port '%s' out of range",
+ isc_commandline_argument);
+ lwresd_g_listenport = port;
+ break;
+ case 's':
+ /* XXXRTH temporary syntax */
+ want_stats = true;
+ break;
+ case 'S':
+ maxsocks = parse_int(isc_commandline_argument,
+ "max number of sockets");
+ break;
+ case 't':
+ /* XXXJAB should we make a copy? */
+ ns_g_chrootdir = isc_commandline_argument;
+ break;
+ case 'T': /* NOT DOCUMENTED */
+ parse_T_opt(isc_commandline_argument);
+ break;
+ case 'U':
+ ns_g_udpdisp = parse_int(isc_commandline_argument,
+ "number of UDP listeners "
+ "per interface");
+ break;
+ case 'u':
+ ns_g_username = isc_commandline_argument;
+ break;
+ case 'v':
+ printf("%s %s%s%s <id:%s>\n",
+ ns_g_product, ns_g_version,
+ (*ns_g_description != '\0') ? " " : "",
+ ns_g_description, ns_g_srcid);
+ exit(0);
+ case 'V':
+ printf("%s %s%s%s <id:%s>\n", ns_g_product, ns_g_version,
+ (*ns_g_description != '\0') ? " " : "",
+ ns_g_description, ns_g_srcid);
+ printf("running on %s\n", ns_os_uname());
+ printf("built by %s with %s\n",
+ ns_g_builder, ns_g_configargs);
+#ifdef __clang__
+ printf("compiled by CLANG %s\n", __VERSION__);
+#else
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+ printf("compiled by ICC %s\n", __VERSION__);
+#else
+#ifdef __GNUC__
+ printf("compiled by GCC %s\n", __VERSION__);
+#endif
+#endif
+#endif
+#ifdef _MSC_VER
+ printf("compiled by MSVC %d\n", _MSC_VER);
+#endif
+#ifdef __SUNPRO_C
+ printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
+#endif
+#ifdef OPENSSL
+ 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
+ printf("linked to OpenSSL version: %s\n",
+ SSLeay_version(SSLEAY_VERSION));
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+#endif
+#ifdef HAVE_LIBXML2
+ printf("compiled with libxml2 version: %s\n",
+ LIBXML_DOTTED_VERSION);
+ printf("linked to libxml2 version: %s\n",
+ xmlParserVersion);
+#endif
+#if defined(HAVE_JSON) && defined(JSON_C_VERSION)
+ printf("compiled with libjson-c version: %s\n",
+ JSON_C_VERSION);
+ printf("linked to libjson-c version: %s\n",
+ json_c_version());
+#endif
+#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
+#ifdef ISC_PLATFORM_USETHREADS
+ printf("threads support is enabled\n");
+#else
+ printf("threads support is disabled\n");
+#endif
+ exit(0);
+ case 'x':
+ /* Obsolete. No longer in use. Ignore. */
+ break;
+ case 'X':
+ ns_g_forcelock = true;
+ if (strcasecmp(isc_commandline_argument, "none") != 0)
+ ns_g_defaultlockfile = isc_commandline_argument;
+ else
+ ns_g_defaultlockfile = NULL;
+ break;
+ case 'F':
+ /* Reserved for FIPS mode */
+ /* FALLTHROUGH */
+ case '?':
+ usage();
+ if (isc_commandline_option == '?')
+ exit(0);
+ p = strchr(NS_MAIN_ARGS, isc_commandline_option);
+ if (p == NULL || *++p != ':')
+ ns_main_earlyfatal("unknown option '-%c'",
+ isc_commandline_option);
+ else
+ ns_main_earlyfatal("option '-%c' requires "
+ "an argument",
+ isc_commandline_option);
+ /* FALLTHROUGH */
+ default:
+ ns_main_earlyfatal("parsing options returned %d", ch);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc > 0) {
+ usage();
+ ns_main_earlyfatal("extra command line arguments");
+ }
+}
+
+static isc_result_t
+create_managers(void) {
+ isc_result_t result;
+ unsigned int socks;
+
+ INSIST(ns_g_cpus_detected > 0);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (ns_g_cpus == 0)
+ ns_g_cpus = ns_g_cpus_detected;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
+ ns_g_cpus_detected, ns_g_cpus_detected == 1 ? "" : "s",
+ ns_g_cpus, ns_g_cpus == 1 ? "" : "s");
+#else
+ ns_g_cpus = 1;
+#endif
+#ifdef WIN32
+ ns_g_udpdisp = 1;
+#else
+ if (ns_g_udpdisp == 0) {
+ if (ns_g_cpus_detected == 1)
+ ns_g_udpdisp = 1;
+ else
+ ns_g_udpdisp = ns_g_cpus_detected - 1;
+ }
+ if (ns_g_udpdisp > ns_g_cpus)
+ ns_g_udpdisp = ns_g_cpus;
+#endif
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "using %u UDP listener%s per interface",
+ ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s");
+#endif
+
+ result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_taskmgr_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_timermgr_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socketmgr_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ isc__socketmgr_maxudp(ns_g_socketmgr, maxudp);
+ result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "using up to %u sockets", socks);
+ }
+
+ result = isc_entropy_create(ns_g_mctx, &ns_g_entropy);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_entropy_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = isc_hash_create(ns_g_mctx, ns_g_entropy, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_hash_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroy_managers(void) {
+ ns_lwresd_shutdown();
+
+ /*
+ * isc_taskmgr_destroy() will block until all tasks have exited,
+ */
+ isc_taskmgr_destroy(&ns_g_taskmgr);
+ isc_timermgr_destroy(&ns_g_timermgr);
+ isc_socketmgr_destroy(&ns_g_socketmgr);
+
+ /*
+ * isc_hash_destroy() cannot be called as long as a resolver may be
+ * running. Calling this after isc_taskmgr_destroy() ensures the
+ * call is safe.
+ */
+ isc_hash_destroy();
+}
+
+static void
+dump_symboltable(void) {
+ int i;
+ isc_result_t result;
+ const char *fname;
+ const void *addr;
+
+ if (isc__backtrace_nsymbols == 0)
+ return;
+
+ if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99)))
+ return;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_DEBUG(99), "Symbol table:");
+
+ for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) {
+ addr = NULL;
+ fname = NULL;
+ result = isc_backtrace_getsymbolfromindex(i, &addr, &fname);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99),
+ "[%d] %p %s", i, addr, fname);
+ }
+ }
+}
+
+#ifdef HAVE_LIBSECCOMP
+static void
+setup_seccomp() {
+ scmp_filter_ctx ctx;
+ unsigned int i;
+ int ret;
+
+ /* Make sure the lists are in sync */
+ INSIST((sizeof(scmp_syscalls) / sizeof(int)) ==
+ (sizeof(scmp_syscall_names) / sizeof(const char *)));
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
+ "libseccomp activation failed");
+ return;
+ }
+
+ for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) {
+ ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
+ scmp_syscalls[i], 0);
+ if (ret < 0)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
+ "libseccomp rule failed: %s",
+ scmp_syscall_names[i]);
+
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9),
+ "added libseccomp rule: %s",
+ scmp_syscall_names[i]);
+ }
+
+ ret = seccomp_load(ctx);
+ if (ret < 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
+ "libseccomp unable to load filter");
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "libseccomp sandboxing active");
+ }
+
+ /*
+ * Release filter in ctx. Filters already loaded are not
+ * affected.
+ */
+ seccomp_release(ctx);
+}
+#endif /* HAVE_LIBSECCOMP */
+
+static void
+setup(void) {
+ isc_result_t result;
+ isc_resourcevalue_t old_openfiles;
+#ifdef HAVE_LIBSCF
+ char *instance = NULL;
+#endif
+
+ /*
+ * 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.
+ */
+ ns_os_inituserinfo(ns_g_username);
+
+ /*
+ * Initialize time conversion information
+ */
+ ns_os_tzset();
+
+ ns_os_opendevnull();
+
+#ifdef HAVE_LIBSCF
+ /* Check if named is under smf control, before chroot. */
+ result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
+ /* We don't care about instance, just check if we got one. */
+ if (result == ISC_R_SUCCESS)
+ ns_smf_got_instance = 1;
+ else
+ ns_smf_got_instance = 0;
+ if (instance != NULL)
+ isc_mem_free(ns_g_mctx, instance);
+#endif /* HAVE_LIBSCF */
+
+#ifdef PATH_RANDOMDEV
+ /*
+ * Initialize system's random device as fallback entropy source
+ * if running chroot'ed.
+ */
+ if (ns_g_chrootdir != NULL) {
+ result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_entropy_create() failed: %s",
+ isc_result_totext(result));
+
+ result = isc_entropy_createfilesource(ns_g_fallbackentropy,
+ PATH_RANDOMDEV);
+ if (result != ISC_R_SUCCESS) {
+ ns_main_earlywarning("could not open pre-chroot "
+ "entropy source %s: %s",
+ PATH_RANDOMDEV,
+ isc_result_totext(result));
+ isc_entropy_detach(&ns_g_fallbackentropy);
+ }
+ }
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Check for the number of cpu's before ns_os_chroot().
+ */
+ ns_g_cpus_detected = isc_os_ncpus();
+#endif
+
+ ns_os_chroot(ns_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.)
+ */
+ ns_os_minprivs();
+
+ result = ns_log_init((ns_g_username != NULL));
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("ns_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 (!ns_g_foreground)
+ ns_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)
+ ns_main_earlyfatal("isc_app_start() failed: %s",
+ isc_result_totext(result));
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "starting %s %s%s%s <id:%s>",
+ ns_g_product, ns_g_version,
+ *ns_g_description ? " " : "", ns_g_description,
+ ns_g_srcid);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "running on %s", ns_os_uname());
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "built with %s", ns_g_configargs);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "running as: %s%s",
+ program_name, saved_command_line);
+#ifdef __clang__
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by CLANG %s", __VERSION__);
+#else
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by ICC %s", __VERSION__);
+#else
+#ifdef __GNUC__
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by GCC %s", __VERSION__);
+#endif
+#endif
+#endif
+#ifdef _MSC_VER
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by MSVC %d", _MSC_VER);
+#endif
+#ifdef __SUNPRO_C
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by Solaris Studio %x", __SUNPRO_C);
+#endif
+#ifdef OPENSSL
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to OpenSSL version: %s",
+ OpenSSL_version(OPENSSL_VERSION));
+#else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to OpenSSL version: %s",
+ SSLeay_version(SSLEAY_VERSION));
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+#endif
+#ifdef HAVE_LIBXML2
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with libxml2 version: %s",
+ LIBXML_DOTTED_VERSION);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to libxml2 version: %s", xmlParserVersion);
+#endif
+#if defined(HAVE_JSON) && defined(JSON_C_VERSION)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with libjson-c version: %s", JSON_C_VERSION);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to libjson-c version: %s", json_c_version());
+#endif
+#if defined(HAVE_ZLIB) && defined(ZLIB_VERSION)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with zlib version: %s", ZLIB_VERSION);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to zlib version: %s", zlibVersion());
+#endif
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "threads support is enabled");
+#else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "threads support is disabled");
+#endif
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE,
+ "----------------------------------------------------");
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE,
+ "BIND 9 is maintained by Internet Systems Consortium,");
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE,
+ "Inc. (ISC), a non-profit 501(c)(3) public-benefit ");
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE,
+ "corporation. Support and training for BIND 9 are ");
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE,
+ "available at https://www.isc.org/support");
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE,
+ "----------------------------------------------------");
+
+ dump_symboltable();
+
+ /*
+ * Get the initial resource limits.
+ */
+ (void)isc_resource_getlimit(isc_resource_stacksize,
+ &ns_g_initstacksize);
+ (void)isc_resource_getlimit(isc_resource_datasize,
+ &ns_g_initdatasize);
+ (void)isc_resource_getlimit(isc_resource_coresize,
+ &ns_g_initcoresize);
+ (void)isc_resource_getlimit(isc_resource_openfiles,
+ &ns_g_initopenfiles);
+
+ /*
+ * System resources cannot effectively be tuned on some systems.
+ * Raise the limit in such cases for safety.
+ */
+ old_openfiles = ns_g_initopenfiles;
+ ns_os_adjustnofile();
+ (void)isc_resource_getlimit(isc_resource_openfiles,
+ &ns_g_initopenfiles);
+ if (old_openfiles != ns_g_initopenfiles) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "adjusted limit on open files from "
+ "%" PRIu64 " to "
+ "%" PRIu64,
+ old_openfiles, ns_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(ns_g_conffile)) {
+ result = isc_file_absolutepath(ns_g_conffile,
+ absolute_conffile,
+ sizeof(absolute_conffile));
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("could not construct absolute path "
+ "of configuration file: %s",
+ isc_result_totext(result));
+ ns_g_conffile = absolute_conffile;
+ }
+
+ /*
+ * Record the server's startup time.
+ */
+ result = isc_time_now(&ns_g_boottime);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_time_now() failed: %s",
+ isc_result_totext(result));
+
+ result = create_managers();
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("create_managers() failed: %s",
+ isc_result_totext(result));
+
+ ns_builtin_init();
+
+ /*
+ * Add calls to register sdb drivers here.
+ */
+ /* xxdb_init(); */
+
+#ifdef ISC_DLZ_DLOPEN
+ /*
+ * Register the DLZ "dlopen" driver.
+ */
+ result = dlz_dlopen_init(ns_g_mctx);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("dlz_dlopen_init() failed: %s",
+ isc_result_totext(result));
+#endif
+
+#if CONTRIB_DLZ
+ /*
+ * Register any other contributed DLZ drivers.
+ */
+ result = dlz_drivers_init();
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("dlz_drivers_init() failed: %s",
+ isc_result_totext(result));
+#endif
+
+ ns_server_create(ns_g_mctx, &ns_g_server);
+
+#ifdef HAVE_LIBSECCOMP
+ setup_seccomp();
+#endif /* HAVE_LIBSECCOMP */
+}
+
+static void
+cleanup(void) {
+ destroy_managers();
+
+ if (ns_g_mapped != NULL)
+ dns_acl_detach(&ns_g_mapped);
+
+ ns_server_destroy(&ns_g_server);
+
+ isc_entropy_detach(&ns_g_entropy);
+ if (ns_g_fallbackentropy != NULL)
+ isc_entropy_detach(&ns_g_fallbackentropy);
+
+ ns_builtin_deinit();
+
+ /*
+ * Add calls to unregister sdb drivers here.
+ */
+ /* xxdb_clear(); */
+
+#ifdef CONTRIB_DLZ
+ /*
+ * Unregister contributed DLZ drivers.
+ */
+ dlz_drivers_clear();
+#endif
+#ifdef ISC_DLZ_DLOPEN
+ /*
+ * Unregister "dlopen" DLZ driver.
+ */
+ dlz_dlopen_clear();
+#endif
+
+ dns_name_destroy();
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "exiting");
+ ns_log_shutdown();
+}
+
+static char *memstats = NULL;
+
+void
+ns_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
+ns_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(__FILE__, __LINE__,
+ "scf_handle_create() failed: %s",
+ scf_strerror(scf_error()));
+ return (ISC_R_FAILURE);
+ }
+
+ if (scf_handle_bind(h) == -1) {
+ if (debug)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "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(__FILE__, __LINE__,
+ "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(__FILE__, __LINE__,
+ "ns_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(__FILE__, __LINE__,
+ "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_GPERFTOOLS_PROFILER
+ (void) ProfilerStart(NULL);
+#endif
+
+ /*
+ * Record version in core image.
+ * strings named.core | grep "named version:"
+ */
+ strlcat(version,
+#if defined(NO_VERSION_DATE) || !defined(__DATE__)
+ "named version: BIND " VERSION " <" SRCID ">",
+#else
+ "named version: BIND " VERSION " <" SRCID "> (" __DATE__ ")",
+#endif
+ sizeof(version));
+ result = isc_file_progname(*argv, program_name, sizeof(program_name));
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("program name too long");
+
+ if (strcmp(program_name, "lwresd") == 0)
+ ns_g_lwresdonly = true;
+
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("failed to build internal symbol table");
+
+ isc_assertion_setcallback(assertion_failed);
+ isc_error_setfatal(library_fatal_error);
+ isc_error_setunexpected(library_unexpected_error);
+
+ ns_os_init(program_name);
+
+ dns_result_register();
+ dst_result_register();
+ isccc_result_register();
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+
+ parse_command_line(argc, argv);
+
+#ifdef ENABLE_AFL
+ if (ns_g_fuzz_type != ns_fuzz_none) {
+ named_fuzz_setup();
+ }
+
+ if (ns_g_fuzz_type == ns_fuzz_resolver) {
+ dns_resolver_setfuzzing();
+ } else if (ns_g_fuzz_type == ns_fuzz_http) {
+ isc_httpd_setfinishhook(named_fuzz_notify);
+ }
+#endif
+ /*
+ * Warn about common configuration error.
+ */
+ if (ns_g_chrootdir != NULL) {
+ int len = strlen(ns_g_chrootdir);
+ if (strncmp(ns_g_chrootdir, ns_g_conffile, len) == 0 &&
+ (ns_g_conffile[len] == '/' || ns_g_conffile[len] == '\\'))
+ ns_main_earlywarning("config filename (-c %s) contains "
+ "chroot path (-t %s)",
+ ns_g_conffile, ns_g_chrootdir);
+ }
+
+ result = isc_mem_create(0, 0, &ns_g_mctx);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_mem_create() failed: %s",
+ isc_result_totext(result));
+ isc_mem_setname(ns_g_mctx, "main", NULL);
+
+ setup();
+
+ /*
+ * Start things running and then wait for a shutdown request
+ * or reload.
+ */
+ do {
+ result = isc_app_run();
+
+ if (result == ISC_R_RELOAD) {
+ ns_server_reloadwanted(ns_g_server);
+ } else if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_run(): %s",
+ isc_result_totext(result));
+ /*
+ * Force exit.
+ */
+ result = ISC_R_SUCCESS;
+ }
+ } while (result != ISC_R_SUCCESS);
+
+#ifdef HAVE_LIBSCF
+ if (ns_smf_want_disable == 1) {
+ result = ns_smf_get_instance(&instance, 1, ns_g_mctx);
+ if (result == ISC_R_SUCCESS && instance != NULL) {
+ if (smf_disable_instance(instance, 0) != 0)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "smf_disable_instance() "
+ "failed for %s : %s",
+ instance,
+ scf_strerror(scf_error()));
+ }
+ if (instance != NULL)
+ isc_mem_free(ns_g_mctx, instance);
+ }
+#endif /* HAVE_LIBSCF */
+
+ cleanup();
+
+ if (want_stats) {
+ isc_mem_stats(ns_g_mctx, stdout);
+ isc_mutex_stats(stdout);
+ }
+
+ if (ns_g_memstatistics && memstats != NULL) {
+ FILE *fp = NULL;
+ result = isc_stdio_open(memstats, "w", &fp);
+ if (result == ISC_R_SUCCESS) {
+ isc_mem_stats(ns_g_mctx, fp);
+ isc_mutex_stats(fp);
+ (void) isc_stdio_close(fp);
+ }
+ }
+ isc_mem_destroy(&ns_g_mctx);
+ isc_mem_checkdestroyed(stderr);
+
+ ns_main_setmemstats(NULL);
+
+ isc_app_finish();
+
+ ns_os_closedevnull();
+
+ ns_os_shutdown();
+
+#ifdef HAVE_GPERFTOOLS_PROFILER
+ ProfilerStop();
+#endif
+
+ return (0);
+}
diff --git a/bin/named/named.8 b/bin/named/named.8
new file mode 100644
index 0000000..341580d
--- /dev/null
+++ b/bin/named/named.8
@@ -0,0 +1,379 @@
+.\" Copyright (C) 2000, 2001, 2003-2009, 2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-02-19
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NAMED" "8" "2014\-02\-19" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named \- Internet domain name server
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\fR\ 'u
+\fBnamed\fR [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-D\ \fR\fB\fIstring\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-L\ \fR\fB\fIlogfile\fR\fR] [\fB\-M\ \fR\fB\fIoption\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-U\ \fR\fB\fI#listeners\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-X\ \fR\fB\fIlock\-file\fR\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR]
+.SH "DESCRIPTION"
+.PP
+\fBnamed\fR
+is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC\&. For more information on the DNS, see RFCs 1033, 1034, and 1035\&.
+.PP
+When invoked without arguments,
+\fBnamed\fR
+will read the default configuration file
+/etc/named\&.conf, read any initial data, and listen for queries\&.
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only even if the host machine is capable of IPv6\&.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive\&.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only even if the host machine is capable of IPv4\&.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive\&.
+.RE
+.PP
+\-c \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+/etc/named\&.conf\&. To ensure that reloading the configuration file continues to work after the server has changed its working directory due to to a possible
+\fBdirectory\fR
+option in the configuration file,
+\fIconfig\-file\fR
+should be an absolute pathname\&.
+.RE
+.PP
+\-d \fIdebug\-level\fR
+.RS 4
+Set the daemon\*(Aqs debug level to
+\fIdebug\-level\fR\&. Debugging traces from
+\fBnamed\fR
+become more verbose as the debug level increases\&.
+.RE
+.PP
+\-D \fIstring\fR
+.RS 4
+Specifies a string that is used to identify a instance of
+\fBnamed\fR
+in a process listing\&. The contents of
+\fIstring\fR
+are not examined\&.
+.RE
+.PP
+\-E \fIengine\-name\fR
+.RS 4
+When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing\&.
+.sp
+When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&.
+.RE
+.PP
+\-f
+.RS 4
+Run the server in the foreground (i\&.e\&. do not daemonize)\&.
+.RE
+.PP
+\-g
+.RS 4
+Run the server in the foreground and force all logging to
+stderr\&.
+.RE
+.PP
+\-L \fIlogfile\fR
+.RS 4
+Log to the file
+\fBlogfile\fR
+by default instead of the system log\&.
+.RE
+.PP
+\-M \fIoption\fR
+.RS 4
+Sets the default memory context options\&. Currently the only supported option is
+\fIexternal\fR, which causes the internal memory manager to be bypassed in favor of system\-provided memory allocation functions\&.
+.RE
+.PP
+\-m \fIflag\fR
+.RS 4
+Turn on memory usage debugging flags\&. Possible flags are
+\fIusage\fR,
+\fItrace\fR,
+\fIrecord\fR,
+\fIsize\fR, and
+\fImctx\fR\&. These correspond to the ISC_MEM_DEBUGXXXX flags described in
+<isc/mem\&.h>\&.
+.RE
+.PP
+\-n \fI#cpus\fR
+.RS 4
+Create
+\fI#cpus\fR
+worker threads to take advantage of multiple CPUs\&. If not specified,
+\fBnamed\fR
+will try to determine the number of CPUs present and create one thread per CPU\&. If it is unable to determine the number of CPUs, a single worker thread will be created\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Listen for queries on port
+\fIport\fR\&. If not specified, the default is port 53\&.
+.RE
+.PP
+\-s
+.RS 4
+Write memory usage statistics to
+stdout
+on exit\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
+This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release\&.
+.sp .5v
+.RE
+.RE
+.PP
+\-S \fI#max\-socks\fR
+.RS 4
+Allow
+\fBnamed\fR
+to use up to
+\fI#max\-socks\fR
+sockets\&. The default value is 4096 on systems built with default configuration options, and 21000 on systems built with "configure \-\-with\-tuning=large"\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBWarning\fR
+.ps -1
+.br
+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 a little fewer than the specified value because
+\fBnamed\fR
+reserves some file descriptors for its internal use\&.
+.sp .5v
+.RE
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+\fIdirectory\fR
+after processing the command line arguments, but before reading the configuration file\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBWarning\fR
+.ps -1
+.br
+This option should be used in conjunction with the
+\fB\-u\fR
+option, as chrooting a process running as root doesn\*(Aqt enhance security on most systems; the way
+\fBchroot(2)\fR
+is defined allows a process with root privileges to escape a chroot jail\&.
+.sp .5v
+.RE
+.RE
+.PP
+\-U \fI#listeners\fR
+.RS 4
+Use
+\fI#listeners\fR
+worker threads to listen for incoming UDP packets on each address\&. If not specified,
+\fBnamed\fR
+will calculate 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
+\fB\-n\fR
+has been set to a higher value than the number of detected CPUs, then
+\fB\-U\fR
+may be increased as high as that value, but no higher\&. On Windows, the number of UDP listeners is hardwired to 1 and this option has no effect\&.
+.RE
+.PP
+\-u \fIuser\fR
+.RS 4
+Setuid to
+\fIuser\fR
+after completing privileged operations, such as creating sockets that listen on privileged ports\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
+On Linux,
+\fBnamed\fR
+uses the kernel\*(Aqs capability mechanism to drop all root privileges except the ability to
+\fBbind(2)\fR
+to a privileged port and set process resource limits\&. Unfortunately, this means that the
+\fB\-u\fR
+option only works when
+\fBnamed\fR
+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
+\fBsetuid(2)\fR\&.
+.sp .5v
+.RE
+.RE
+.PP
+\-v
+.RS 4
+Report the version number and exit\&.
+.RE
+.PP
+\-V
+.RS 4
+Report the version number and build options, and exit\&.
+.RE
+.PP
+\-X \fIlock\-file\fR
+.RS 4
+Acquire a lock on the specified file at runtime; this helps to prevent duplicate
+\fBnamed\fR
+instances from running simultaneously\&. Use of this option overrides the
+\fBlock\-file\fR
+option in
+named\&.conf\&. If set to
+none, the lock file check is disabled\&.
+.RE
+.PP
+\-x \fIcache\-file\fR
+.RS 4
+Load data from
+\fIcache\-file\fR
+into the cache of the default view\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBWarning\fR
+.ps -1
+.br
+This option must not be used\&. It is only of interest to BIND 9 developers and may be removed or changed in a future release\&.
+.sp .5v
+.RE
+.RE
+.SH "SIGNALS"
+.PP
+In routine operation, signals should not be used to control the nameserver;
+\fBrndc\fR
+should be used instead\&.
+.PP
+SIGHUP
+.RS 4
+Force a reload of the server\&.
+.RE
+.PP
+SIGINT, SIGTERM
+.RS 4
+Shut down the server\&.
+.RE
+.PP
+The result of sending any other signals to the server is undefined\&.
+.SH "CONFIGURATION"
+.PP
+The
+\fBnamed\fR
+configuration file is too complex to describe in detail here\&. A complete description is provided in the
+BIND 9 Administrator Reference Manual\&.
+.PP
+\fBnamed\fR
+inherits the
+\fBumask\fR
+(file creation mode mask) from the parent process\&. If files created by
+\fBnamed\fR, such as journal files, need to have custom permissions, the
+\fBumask\fR
+should be set explicitly in the script used to start the
+\fBnamed\fR
+process\&.
+.SH "FILES"
+.PP
+/etc/named\&.conf
+.RS 4
+The default configuration file\&.
+.RE
+.PP
+/var/run/named/named\&.pid
+.RS 4
+The default process\-id file\&.
+.RE
+.SH "SEE ALSO"
+.PP
+RFC 1033,
+RFC 1034,
+RFC 1035,
+\fBnamed-checkconf\fR(8),
+\fBnamed-checkzone\fR(8),
+\fBrndc\fR(8),
+\fBlwresd\fR(8),
+\fBnamed.conf\fR(5),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000, 2001, 2003-2009, 2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/named/named.conf.5 b/bin/named/named.conf.5
new file mode 100644
index 0000000..471f0f5
--- /dev/null
+++ b/bin/named/named.conf.5
@@ -0,0 +1,1028 @@
+.\" Copyright (C) 2004-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named.conf
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2018-06-21
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NAMED\&.CONF" "5" "2018\-06\-21" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named.conf \- configuration file for \fBnamed\fR
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\&.conf\fR\ 'u
+\fBnamed\&.conf\fR
+.SH "DESCRIPTION"
+.PP
+named\&.conf
+is the configuration file for
+\fBnamed\fR\&. 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:
+.PP
+C style: /* */
+.PP
+C++ style: // to end of line
+.PP
+Unix style: # to end of line
+.SH "ACL"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+acl \fIstring\fR { \fIaddress_match_element\fR; \&.\&.\&. };
+.fi
+.if n \{\
+.RE
+.\}
+.SH "CONTROLS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+controls {
+ inet ( \fIipv4_address\fR | \fIipv6_address\fR |
+ * ) [ port ( \fIinteger\fR | * ) ] allow
+ { \fIaddress_match_element\fR; \&.\&.\&. } [
+ keys { \fIstring\fR; \&.\&.\&. } ] [ read\-only
+ \fIboolean\fR ];
+ unix \fIquoted_string\fR perm \fIinteger\fR
+ owner \fIinteger\fR group \fIinteger\fR [
+ keys { \fIstring\fR; \&.\&.\&. } ] [ read\-only
+ \fIboolean\fR ];
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "DLZ"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+dlz \fIstring\fR {
+ database \fIstring\fR;
+ search \fIboolean\fR;
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "DYNDB"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+dyndb \fIstring\fR \fIquoted_string\fR {
+ \fIunspecified\-text\fR };
+.fi
+.if n \{\
+.RE
+.\}
+.SH "KEY"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+key \fIstring\fR {
+ algorithm \fIstring\fR;
+ secret \fIstring\fR;
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "LOGGING"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+logging {
+ category \fIstring\fR { \fIstring\fR; \&.\&.\&. };
+ channel \fIstring\fR {
+ buffered \fIboolean\fR;
+ file \fIquoted_string\fR [ versions ( "unlimited" | \fIinteger\fR )
+ ] [ size \fIsize\fR ];
+ null;
+ print\-category \fIboolean\fR;
+ print\-severity \fIboolean\fR;
+ print\-time \fIboolean\fR;
+ severity \fIlog_severity\fR;
+ stderr;
+ syslog [ \fIsyslog_facility\fR ];
+ };
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "LWRES"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+lwres {
+ listen\-on [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR
+ | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. };
+ lwres\-clients \fIinteger\fR;
+ lwres\-tasks \fIinteger\fR;
+ ndots \fIinteger\fR;
+ search { \fIstring\fR; \&.\&.\&. };
+ view \fIstring\fR [ \fIclass\fR ];
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "MANAGED-KEYS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+managed\-keys { \fIstring\fR \fIstring\fR \fIinteger\fR
+ \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; \&.\&.\&. };
+.fi
+.if n \{\
+.RE
+.\}
+.SH "MASTERS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+masters \fIstring\fR [ port \fIinteger\fR ] [ dscp
+ \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [
+ port \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. };
+.fi
+.if n \{\
+.RE
+.\}
+.SH "OPTIONS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+options {
+ acache\-cleaning\-interval \fIinteger\fR;
+ acache\-enable \fIboolean\fR;
+ additional\-from\-auth \fIboolean\fR;
+ additional\-from\-cache \fIboolean\fR;
+ allow\-new\-zones \fIboolean\fR;
+ allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-cache { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-cache\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-recursion { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-recursion\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. };
+ also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR |
+ \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. };
+ alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR |
+ * ) ] [ dscp \fIinteger\fR ];
+ answer\-cookie \fIboolean\fR;
+ attach\-cache \fIstring\fR;
+ auth\-nxdomain \fIboolean\fR; // default changed
+ auto\-dnssec ( allow | maintain | off );
+ automatic\-interface\-scan \fIboolean\fR;
+ avoid\-v4\-udp\-ports { \fIportrange\fR; \&.\&.\&. };
+ avoid\-v6\-udp\-ports { \fIportrange\fR; \&.\&.\&. };
+ bindkeys\-file \fIquoted_string\fR;
+ blackhole { \fIaddress_match_element\fR; \&.\&.\&. };
+ cache\-file \fIquoted_string\fR;
+ catalog\-zones { zone \fIquoted_string\fR [ default\-masters [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [
+ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key
+ \fIstring\fR ]; \&.\&.\&. } ] [ zone\-directory \fIquoted_string\fR ] [
+ in\-memory \fIboolean\fR ] [ min\-update\-interval \fIinteger\fR ]; \&.\&.\&. };
+ check\-dup\-records ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx ( fail | warn | ignore );
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-names ( master | slave | response
+ ) ( fail | warn | ignore );
+ check\-sibling \fIboolean\fR;
+ check\-spf ( warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ check\-wildcard \fIboolean\fR;
+ cleaning\-interval \fIinteger\fR;
+ clients\-per\-query \fIinteger\fR;
+ cookie\-algorithm ( aes | sha1 | sha256 );
+ cookie\-secret \fIstring\fR;
+ coresize ( default | unlimited | \fIsizeval\fR );
+ datasize ( default | unlimited | \fIsizeval\fR );
+ deny\-answer\-addresses { \fIaddress_match_element\fR; \&.\&.\&. } [
+ except\-from { \fIquoted_string\fR; \&.\&.\&. } ];
+ deny\-answer\-aliases { \fIquoted_string\fR; \&.\&.\&. } [ except\-from {
+ \fIquoted_string\fR; \&.\&.\&. } ];
+ dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR );
+ directory \fIquoted_string\fR;
+ disable\-algorithms \fIstring\fR { \fIstring\fR;
+ \&.\&.\&. };
+ disable\-ds\-digests \fIstring\fR { \fIstring\fR;
+ \&.\&.\&. };
+ disable\-empty\-zone \fIstring\fR;
+ dns64 \fInetprefix\fR {
+ break\-dnssec \fIboolean\fR;
+ clients { \fIaddress_match_element\fR; \&.\&.\&. };
+ exclude { \fIaddress_match_element\fR; \&.\&.\&. };
+ mapped { \fIaddress_match_element\fR; \&.\&.\&. };
+ recursive\-only \fIboolean\fR;
+ suffix \fIipv6_address\fR;
+ };
+ dns64\-contact \fIstring\fR;
+ dns64\-server \fIstring\fR;
+ dnssec\-accept\-expired \fIboolean\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
+ dnssec\-enable \fIboolean\fR;
+ dnssec\-loadkeys\-interval \fIinteger\fR;
+ dnssec\-lookaside ( \fIstring\fR trust\-anchor
+ \fIstring\fR | auto | no );
+ dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
+ dnssec\-update\-mode ( maintain | no\-resign );
+ dnssec\-validation ( yes | no | auto );
+ dnstap { ( all | auth | client | forwarder |
+ resolver ) [ ( query | response ) ]; \&.\&.\&. };
+ dnstap\-identity ( \fIquoted_string\fR | none |
+ hostname );
+ dnstap\-output ( file | unix ) \fIquoted_string\fR;
+ dnstap\-version ( \fIquoted_string\fR | none );
+ dscp \fIinteger\fR;
+ dual\-stack\-servers [ port \fIinteger\fR ] { ( \fIquoted_string\fR [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv4_address\fR [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] ); \&.\&.\&. };
+ dump\-file \fIquoted_string\fR;
+ edns\-udp\-size \fIinteger\fR;
+ empty\-contact \fIstring\fR;
+ empty\-server \fIstring\fR;
+ empty\-zones\-enable \fIboolean\fR;
+ fetch\-quota\-params \fIinteger\fR \fIfixedpoint\fR \fIfixedpoint\fR \fIfixedpoint\fR;
+ fetches\-per\-server \fIinteger\fR [ ( drop | fail ) ];
+ fetches\-per\-zone \fIinteger\fR [ ( drop | fail ) ];
+ files ( default | unlimited | \fIsizeval\fR );
+ filter\-aaaa { \fIaddress_match_element\fR; \&.\&.\&. };
+ filter\-aaaa\-on\-v4 ( break\-dnssec | \fIboolean\fR );
+ filter\-aaaa\-on\-v6 ( break\-dnssec | \fIboolean\fR );
+ flush\-zones\-on\-shutdown \fIboolean\fR;
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR
+ | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. };
+ fstrm\-set\-buffer\-hint \fIinteger\fR;
+ fstrm\-set\-flush\-timeout \fIinteger\fR;
+ fstrm\-set\-input\-queue\-size \fIinteger\fR;
+ fstrm\-set\-output\-notify\-threshold \fIinteger\fR;
+ fstrm\-set\-output\-queue\-model ( mpsc | spsc );
+ fstrm\-set\-output\-queue\-size \fIinteger\fR;
+ fstrm\-set\-reopen\-interval \fIinteger\fR;
+ geoip\-directory ( \fIquoted_string\fR | none );
+ geoip\-use\-ecs \fIboolean\fR;
+ heartbeat\-interval \fIinteger\fR;
+ hostname ( \fIquoted_string\fR | none );
+ inline\-signing \fIboolean\fR;
+ interface\-interval \fIinteger\fR;
+ ixfr\-from\-differences ( master | slave | \fIboolean\fR );
+ keep\-response\-order { \fIaddress_match_element\fR; \&.\&.\&. };
+ key\-directory \fIquoted_string\fR;
+ lame\-ttl \fIttlval\fR;
+ listen\-on [ port \fIinteger\fR ] [ dscp
+ \fIinteger\fR ] {
+ \fIaddress_match_element\fR; \&.\&.\&. };
+ listen\-on\-v6 [ port \fIinteger\fR ] [ dscp
+ \fIinteger\fR ] {
+ \fIaddress_match_element\fR; \&.\&.\&. };
+ lmdb\-mapsize \fIsizeval\fR;
+ lock\-file ( \fIquoted_string\fR | none );
+ managed\-keys\-directory \fIquoted_string\fR;
+ masterfile\-format ( map | raw | text );
+ masterfile\-style ( full | relative );
+ match\-mapped\-addresses \fIboolean\fR;
+ max\-acache\-size ( unlimited | \fIsizeval\fR );
+ max\-cache\-size ( default | unlimited | \fIsizeval\fR | \fIpercentage\fR );
+ max\-cache\-ttl \fIinteger\fR;
+ max\-clients\-per\-query \fIinteger\fR;
+ max\-journal\-size ( unlimited | \fIsizeval\fR );
+ max\-ncache\-ttl \fIinteger\fR;
+ max\-records \fIinteger\fR;
+ max\-recursion\-depth \fIinteger\fR;
+ max\-recursion\-queries \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ max\-rsa\-exponent\-size \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-udp\-size \fIinteger\fR;
+ max\-zone\-ttl ( unlimited | \fIttlval\fR );
+ memstatistics \fIboolean\fR;
+ memstatistics\-file \fIquoted_string\fR;
+ message\-compression \fIboolean\fR;
+ min\-refresh\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ minimal\-any \fIboolean\fR;
+ minimal\-responses ( no\-auth | no\-auth\-recursive | \fIboolean\fR );
+ multi\-master \fIboolean\fR;
+ no\-case\-compress { \fIaddress_match_element\fR; \&.\&.\&. };
+ nocookie\-udp\-size \fIinteger\fR;
+ notify ( explicit | master\-only | \fIboolean\fR );
+ notify\-delay \fIinteger\fR;
+ notify\-rate \fIinteger\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ]
+ [ dscp \fIinteger\fR ];
+ notify\-to\-soa \fIboolean\fR;
+ nta\-lifetime \fIttlval\fR;
+ nta\-recheck \fIttlval\fR;
+ nxdomain\-redirect \fIstring\fR;
+ pid\-file ( \fIquoted_string\fR | none );
+ port \fIinteger\fR;
+ preferred\-glue \fIstring\fR;
+ prefetch \fIinteger\fR [ \fIinteger\fR ];
+ provide\-ixfr \fIboolean\fR;
+ query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ]
+ port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ];
+ query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ]
+ port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ];
+ querylog \fIboolean\fR;
+ random\-device \fIquoted_string\fR;
+ rate\-limit {
+ all\-per\-second \fIinteger\fR;
+ errors\-per\-second \fIinteger\fR;
+ exempt\-clients { \fIaddress_match_element\fR; \&.\&.\&. };
+ ipv4\-prefix\-length \fIinteger\fR;
+ ipv6\-prefix\-length \fIinteger\fR;
+ log\-only \fIboolean\fR;
+ max\-table\-size \fIinteger\fR;
+ min\-table\-size \fIinteger\fR;
+ nodata\-per\-second \fIinteger\fR;
+ nxdomains\-per\-second \fIinteger\fR;
+ qps\-scale \fIinteger\fR;
+ referrals\-per\-second \fIinteger\fR;
+ responses\-per\-second \fIinteger\fR;
+ slip \fIinteger\fR;
+ window \fIinteger\fR;
+ };
+ recursing\-file \fIquoted_string\fR;
+ recursion \fIboolean\fR;
+ recursive\-clients \fIinteger\fR;
+ request\-expire \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ request\-nsid \fIboolean\fR;
+ require\-server\-cookie \fIboolean\fR;
+ reserved\-sockets \fIinteger\fR;
+ resolver\-query\-timeout \fIinteger\fR;
+ response\-policy { zone \fIquoted_string\fR [ log \fIboolean\fR ] [
+ max\-policy\-ttl \fIinteger\fR ] [ policy ( cname | disabled | drop |
+ given | no\-op | nodata | nxdomain | passthru | tcp\-only
+ \fIquoted_string\fR ) ] [ recursive\-only \fIboolean\fR ]; \&.\&.\&. } [
+ break\-dnssec \fIboolean\fR ] [ max\-policy\-ttl \fIinteger\fR ] [
+ min\-ns\-dots \fIinteger\fR ] [ nsip\-wait\-recurse \fIboolean\fR ] [
+ qname\-wait\-recurse \fIboolean\fR ] [ recursive\-only \fIboolean\fR ];
+ root\-delegation\-only [ exclude { \fIquoted_string\fR; \&.\&.\&. } ];
+ root\-key\-sentinel \fIboolean\fR;
+ rrset\-order { [ class \fIstring\fR ] [ type \fIstring\fR ] [ name
+ \fIquoted_string\fR ] \fIstring\fR \fIstring\fR; \&.\&.\&. };
+ secroots\-file \fIquoted_string\fR;
+ send\-cookie \fIboolean\fR;
+ serial\-query\-rate \fIinteger\fR;
+ serial\-update\-method ( date | increment | unixtime );
+ server\-id ( \fIquoted_string\fR | none | hostname );
+ servfail\-ttl \fIttlval\fR;
+ session\-keyalg \fIstring\fR;
+ session\-keyfile ( \fIquoted_string\fR | none );
+ session\-keyname \fIstring\fR;
+ sig\-signing\-nodes \fIinteger\fR;
+ sig\-signing\-signatures \fIinteger\fR;
+ sig\-signing\-type \fIinteger\fR;
+ sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ];
+ sortlist { \fIaddress_match_element\fR; \&.\&.\&. };
+ stacksize ( default | unlimited | \fIsizeval\fR );
+ startup\-notify\-rate \fIinteger\fR;
+ statistics\-file \fIquoted_string\fR;
+ tcp\-clients \fIinteger\fR;
+ tcp\-listen\-queue \fIinteger\fR;
+ tkey\-dhkey \fIquoted_string\fR \fIinteger\fR;
+ tkey\-domain \fIquoted_string\fR;
+ tkey\-gssapi\-credential \fIquoted_string\fR;
+ tkey\-gssapi\-keytab \fIquoted_string\fR;
+ transfer\-format ( many\-answers | one\-answer );
+ transfer\-message\-size \fIinteger\fR;
+ transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ transfers\-in \fIinteger\fR;
+ transfers\-out \fIinteger\fR;
+ transfers\-per\-ns \fIinteger\fR;
+ trust\-anchor\-telemetry \fIboolean\fR; // experimental
+ try\-tcp\-refresh \fIboolean\fR;
+ update\-check\-ksk \fIboolean\fR;
+ use\-alt\-transfer\-source \fIboolean\fR;
+ use\-v4\-udp\-ports { \fIportrange\fR; \&.\&.\&. };
+ use\-v6\-udp\-ports { \fIportrange\fR; \&.\&.\&. };
+ v6\-bias \fIinteger\fR;
+ version ( \fIquoted_string\fR | none );
+ zero\-no\-soa\-ttl \fIboolean\fR;
+ zero\-no\-soa\-ttl\-cache \fIboolean\fR;
+ zone\-statistics ( full | terse | none | \fIboolean\fR );
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "SERVER"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+server \fInetprefix\fR {
+ bogus \fIboolean\fR;
+ edns \fIboolean\fR;
+ edns\-udp\-size \fIinteger\fR;
+ edns\-version \fIinteger\fR;
+ keys \fIserver_key\fR;
+ max\-udp\-size \fIinteger\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ]
+ [ dscp \fIinteger\fR ];
+ provide\-ixfr \fIboolean\fR;
+ query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ]
+ port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ];
+ query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ]
+ port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ];
+ request\-expire \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ request\-nsid \fIboolean\fR;
+ send\-cookie \fIboolean\fR;
+ tcp\-only \fIboolean\fR;
+ transfer\-format ( many\-answers | one\-answer );
+ transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ transfers \fIinteger\fR;
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "STATISTICS-CHANNELS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+statistics\-channels {
+ inet ( \fIipv4_address\fR | \fIipv6_address\fR |
+ * ) [ port ( \fIinteger\fR | * ) ] [
+ allow { \fIaddress_match_element\fR; \&.\&.\&.
+ } ];
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "TRUSTED-KEYS"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+trusted\-keys { \fIstring\fR \fIinteger\fR \fIinteger\fR
+ \fIinteger\fR \fIquoted_string\fR; \&.\&.\&. };
+.fi
+.if n \{\
+.RE
+.\}
+.SH "VIEW"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+view \fIstring\fR [ \fIclass\fR ] {
+ acache\-cleaning\-interval \fIinteger\fR;
+ acache\-enable \fIboolean\fR;
+ additional\-from\-auth \fIboolean\fR;
+ additional\-from\-cache \fIboolean\fR;
+ allow\-new\-zones \fIboolean\fR;
+ allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-cache { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-cache\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-recursion { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-recursion\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. };
+ also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR |
+ \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. };
+ alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR |
+ * ) ] [ dscp \fIinteger\fR ];
+ attach\-cache \fIstring\fR;
+ auth\-nxdomain \fIboolean\fR; // default changed
+ auto\-dnssec ( allow | maintain | off );
+ cache\-file \fIquoted_string\fR;
+ catalog\-zones { zone \fIquoted_string\fR [ default\-masters [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [
+ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key
+ \fIstring\fR ]; \&.\&.\&. } ] [ zone\-directory \fIquoted_string\fR ] [
+ in\-memory \fIboolean\fR ] [ min\-update\-interval \fIinteger\fR ]; \&.\&.\&. };
+ check\-dup\-records ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx ( fail | warn | ignore );
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-names ( master | slave | response
+ ) ( fail | warn | ignore );
+ check\-sibling \fIboolean\fR;
+ check\-spf ( warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ check\-wildcard \fIboolean\fR;
+ cleaning\-interval \fIinteger\fR;
+ clients\-per\-query \fIinteger\fR;
+ deny\-answer\-addresses { \fIaddress_match_element\fR; \&.\&.\&. } [
+ except\-from { \fIquoted_string\fR; \&.\&.\&. } ];
+ deny\-answer\-aliases { \fIquoted_string\fR; \&.\&.\&. } [ except\-from {
+ \fIquoted_string\fR; \&.\&.\&. } ];
+ dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR );
+ disable\-algorithms \fIstring\fR { \fIstring\fR;
+ \&.\&.\&. };
+ disable\-ds\-digests \fIstring\fR { \fIstring\fR;
+ \&.\&.\&. };
+ disable\-empty\-zone \fIstring\fR;
+ dlz \fIstring\fR {
+ database \fIstring\fR;
+ search \fIboolean\fR;
+ };
+ dns64 \fInetprefix\fR {
+ break\-dnssec \fIboolean\fR;
+ clients { \fIaddress_match_element\fR; \&.\&.\&. };
+ exclude { \fIaddress_match_element\fR; \&.\&.\&. };
+ mapped { \fIaddress_match_element\fR; \&.\&.\&. };
+ recursive\-only \fIboolean\fR;
+ suffix \fIipv6_address\fR;
+ };
+ dns64\-contact \fIstring\fR;
+ dns64\-server \fIstring\fR;
+ dnssec\-accept\-expired \fIboolean\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
+ dnssec\-enable \fIboolean\fR;
+ dnssec\-loadkeys\-interval \fIinteger\fR;
+ dnssec\-lookaside ( \fIstring\fR trust\-anchor
+ \fIstring\fR | auto | no );
+ dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
+ dnssec\-update\-mode ( maintain | no\-resign );
+ dnssec\-validation ( yes | no | auto );
+ dnstap { ( all | auth | client | forwarder |
+ resolver ) [ ( query | response ) ]; \&.\&.\&. };
+ dual\-stack\-servers [ port \fIinteger\fR ] { ( \fIquoted_string\fR [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv4_address\fR [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] [ dscp \fIinteger\fR ] ); \&.\&.\&. };
+ dyndb \fIstring\fR \fIquoted_string\fR {
+ \fIunspecified\-text\fR };
+ edns\-udp\-size \fIinteger\fR;
+ empty\-contact \fIstring\fR;
+ empty\-server \fIstring\fR;
+ empty\-zones\-enable \fIboolean\fR;
+ fetch\-quota\-params \fIinteger\fR \fIfixedpoint\fR \fIfixedpoint\fR \fIfixedpoint\fR;
+ fetches\-per\-server \fIinteger\fR [ ( drop | fail ) ];
+ fetches\-per\-zone \fIinteger\fR [ ( drop | fail ) ];
+ filter\-aaaa { \fIaddress_match_element\fR; \&.\&.\&. };
+ filter\-aaaa\-on\-v4 ( break\-dnssec | \fIboolean\fR );
+ filter\-aaaa\-on\-v6 ( break\-dnssec | \fIboolean\fR );
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR
+ | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. };
+ inline\-signing \fIboolean\fR;
+ ixfr\-from\-differences ( master | slave | \fIboolean\fR );
+ key \fIstring\fR {
+ algorithm \fIstring\fR;
+ secret \fIstring\fR;
+ };
+ key\-directory \fIquoted_string\fR;
+ lame\-ttl \fIttlval\fR;
+ lmdb\-mapsize \fIsizeval\fR;
+ managed\-keys { \fIstring\fR \fIstring\fR
+ \fIinteger\fR \fIinteger\fR \fIinteger\fR
+ \fIquoted_string\fR; \&.\&.\&. };
+ masterfile\-format ( map | raw | text );
+ masterfile\-style ( full | relative );
+ match\-clients { \fIaddress_match_element\fR; \&.\&.\&. };
+ match\-destinations { \fIaddress_match_element\fR; \&.\&.\&. };
+ match\-recursive\-only \fIboolean\fR;
+ max\-acache\-size ( unlimited | \fIsizeval\fR );
+ max\-cache\-size ( default | unlimited | \fIsizeval\fR | \fIpercentage\fR );
+ max\-cache\-ttl \fIinteger\fR;
+ max\-clients\-per\-query \fIinteger\fR;
+ max\-journal\-size ( unlimited | \fIsizeval\fR );
+ max\-ncache\-ttl \fIinteger\fR;
+ max\-records \fIinteger\fR;
+ max\-recursion\-depth \fIinteger\fR;
+ max\-recursion\-queries \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-udp\-size \fIinteger\fR;
+ max\-zone\-ttl ( unlimited | \fIttlval\fR );
+ message\-compression \fIboolean\fR;
+ min\-refresh\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ minimal\-any \fIboolean\fR;
+ minimal\-responses ( no\-auth | no\-auth\-recursive | \fIboolean\fR );
+ multi\-master \fIboolean\fR;
+ no\-case\-compress { \fIaddress_match_element\fR; \&.\&.\&. };
+ nocookie\-udp\-size \fIinteger\fR;
+ notify ( explicit | master\-only | \fIboolean\fR );
+ notify\-delay \fIinteger\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ]
+ [ dscp \fIinteger\fR ];
+ notify\-to\-soa \fIboolean\fR;
+ nta\-lifetime \fIttlval\fR;
+ nta\-recheck \fIttlval\fR;
+ nxdomain\-redirect \fIstring\fR;
+ preferred\-glue \fIstring\fR;
+ prefetch \fIinteger\fR [ \fIinteger\fR ];
+ provide\-ixfr \fIboolean\fR;
+ query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ]
+ port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ];
+ query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ]
+ port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ];
+ rate\-limit {
+ all\-per\-second \fIinteger\fR;
+ errors\-per\-second \fIinteger\fR;
+ exempt\-clients { \fIaddress_match_element\fR; \&.\&.\&. };
+ ipv4\-prefix\-length \fIinteger\fR;
+ ipv6\-prefix\-length \fIinteger\fR;
+ log\-only \fIboolean\fR;
+ max\-table\-size \fIinteger\fR;
+ min\-table\-size \fIinteger\fR;
+ nodata\-per\-second \fIinteger\fR;
+ nxdomains\-per\-second \fIinteger\fR;
+ qps\-scale \fIinteger\fR;
+ referrals\-per\-second \fIinteger\fR;
+ responses\-per\-second \fIinteger\fR;
+ slip \fIinteger\fR;
+ window \fIinteger\fR;
+ };
+ recursion \fIboolean\fR;
+ request\-expire \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ request\-nsid \fIboolean\fR;
+ require\-server\-cookie \fIboolean\fR;
+ resolver\-query\-timeout \fIinteger\fR;
+ response\-policy { zone \fIquoted_string\fR [ log \fIboolean\fR ] [
+ max\-policy\-ttl \fIinteger\fR ] [ policy ( cname | disabled | drop |
+ given | no\-op | nodata | nxdomain | passthru | tcp\-only
+ \fIquoted_string\fR ) ] [ recursive\-only \fIboolean\fR ]; \&.\&.\&. } [
+ break\-dnssec \fIboolean\fR ] [ max\-policy\-ttl \fIinteger\fR ] [
+ min\-ns\-dots \fIinteger\fR ] [ nsip\-wait\-recurse \fIboolean\fR ] [
+ qname\-wait\-recurse \fIboolean\fR ] [ recursive\-only \fIboolean\fR ];
+ root\-delegation\-only [ exclude { \fIquoted_string\fR; \&.\&.\&. } ];
+ root\-key\-sentinel \fIboolean\fR;
+ rrset\-order { [ class \fIstring\fR ] [ type \fIstring\fR ] [ name
+ \fIquoted_string\fR ] \fIstring\fR \fIstring\fR; \&.\&.\&. };
+ send\-cookie \fIboolean\fR;
+ serial\-update\-method ( date | increment | unixtime );
+ server \fInetprefix\fR {
+ bogus \fIboolean\fR;
+ edns \fIboolean\fR;
+ edns\-udp\-size \fIinteger\fR;
+ edns\-version \fIinteger\fR;
+ keys \fIserver_key\fR;
+ max\-udp\-size \fIinteger\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | *
+ ) ] [ dscp \fIinteger\fR ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR
+ | * ) ] [ dscp \fIinteger\fR ];
+ provide\-ixfr \fIboolean\fR;
+ query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port
+ ( \fIinteger\fR | * ) ] ) | ( [ [ address ] (
+ \fIipv4_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [
+ dscp \fIinteger\fR ];
+ query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [
+ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] (
+ \fIipv6_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [
+ dscp \fIinteger\fR ];
+ request\-expire \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ request\-nsid \fIboolean\fR;
+ send\-cookie \fIboolean\fR;
+ tcp\-only \fIboolean\fR;
+ transfer\-format ( many\-answers | one\-answer );
+ transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR |
+ * ) ] [ dscp \fIinteger\fR ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ];
+ transfers \fIinteger\fR;
+ };
+ servfail\-ttl \fIttlval\fR;
+ sig\-signing\-nodes \fIinteger\fR;
+ sig\-signing\-signatures \fIinteger\fR;
+ sig\-signing\-type \fIinteger\fR;
+ sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ];
+ sortlist { \fIaddress_match_element\fR; \&.\&.\&. };
+ transfer\-format ( many\-answers | one\-answer );
+ transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ trust\-anchor\-telemetry \fIboolean\fR; // experimental
+ trusted\-keys { \fIstring\fR \fIinteger\fR
+ \fIinteger\fR \fIinteger\fR \fIquoted_string\fR;
+ \&.\&.\&. };
+ try\-tcp\-refresh \fIboolean\fR;
+ update\-check\-ksk \fIboolean\fR;
+ use\-alt\-transfer\-source \fIboolean\fR;
+ v6\-bias \fIinteger\fR;
+ zero\-no\-soa\-ttl \fIboolean\fR;
+ zero\-no\-soa\-ttl\-cache \fIboolean\fR;
+ zone \fIstring\fR [ \fIclass\fR ] {
+ allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. };
+ also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { (
+ \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] |
+ \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ];
+ \&.\&.\&. };
+ alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ];
+ auto\-dnssec ( allow | maintain | off );
+ check\-dup\-records ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx ( fail | warn | ignore );
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-names ( fail | warn | ignore );
+ check\-sibling \fIboolean\fR;
+ check\-spf ( warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ check\-wildcard \fIboolean\fR;
+ database \fIstring\fR;
+ delegation\-only \fIboolean\fR;
+ dialup ( notify | notify\-passive | passive | refresh |
+ \fIboolean\fR );
+ dlz \fIstring\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
+ dnssec\-loadkeys\-interval \fIinteger\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
+ dnssec\-update\-mode ( maintain | no\-resign );
+ file \fIquoted_string\fR;
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { (
+ \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ] [
+ dscp \fIinteger\fR ]; \&.\&.\&. };
+ in\-view \fIstring\fR;
+ inline\-signing \fIboolean\fR;
+ ixfr\-from\-differences \fIboolean\fR;
+ journal \fIquoted_string\fR;
+ key\-directory \fIquoted_string\fR;
+ masterfile\-format ( map | raw | text );
+ masterfile\-style ( full | relative );
+ masters [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR
+ | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [
+ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. };
+ max\-ixfr\-log\-size ( default | unlimited |
+ max\-journal\-size ( unlimited | \fIsizeval\fR );
+ max\-records \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-zone\-ttl ( unlimited | \fIttlval\fR );
+ min\-refresh\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ multi\-master \fIboolean\fR;
+ notify ( explicit | master\-only | \fIboolean\fR );
+ notify\-delay \fIinteger\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | *
+ ) ] [ dscp \fIinteger\fR ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR
+ | * ) ] [ dscp \fIinteger\fR ];
+ notify\-to\-soa \fIboolean\fR;
+ pubkey \fIinteger\fR
+ \fIinteger\fR
+ \fIinteger\fR
+ request\-expire \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ serial\-update\-method ( date | increment | unixtime );
+ server\-addresses { ( \fIipv4_address\fR | \fIipv6_address\fR ) [
+ port \fIinteger\fR ]; \&.\&.\&. };
+ server\-names { \fIquoted_string\fR; \&.\&.\&. };
+ sig\-signing\-nodes \fIinteger\fR;
+ sig\-signing\-signatures \fIinteger\fR;
+ sig\-signing\-type \fIinteger\fR;
+ sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ];
+ transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR |
+ * ) ] [ dscp \fIinteger\fR ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port (
+ \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ];
+ try\-tcp\-refresh \fIboolean\fR;
+ type ( delegation\-only | forward | hint | master | redirect
+ | slave | static\-stub | stub );
+ update\-check\-ksk \fIboolean\fR;
+ update\-policy ( local | { ( deny | grant ) \fIstring\fR (
+ 6to4\-self | external | krb5\-self | krb5\-selfsub |
+ krb5\-subdomain | ms\-self | ms\-selfsub | ms\-subdomain |
+ name | self | selfsub | selfwild | subdomain | tcp\-self
+ | wildcard | zonesub ) [ \fIstring\fR ] \fIrrtypelist\fR; \&.\&.\&. };
+ use\-alt\-transfer\-source \fIboolean\fR;
+ zero\-no\-soa\-ttl \fIboolean\fR;
+ zone\-statistics ( full | terse | none | \fIboolean\fR );
+ };
+ zone\-statistics ( full | terse | none | \fIboolean\fR );
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "ZONE"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+zone \fIstring\fR [ \fIclass\fR ] {
+ allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update { \fIaddress_match_element\fR; \&.\&.\&. };
+ allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. };
+ also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR |
+ \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. };
+ alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR |
+ * ) ] [ dscp \fIinteger\fR ];
+ auto\-dnssec ( allow | maintain | off );
+ check\-dup\-records ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx ( fail | warn | ignore );
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-names ( fail | warn | ignore );
+ check\-sibling \fIboolean\fR;
+ check\-spf ( warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ check\-wildcard \fIboolean\fR;
+ database \fIstring\fR;
+ delegation\-only \fIboolean\fR;
+ dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR );
+ dlz \fIstring\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
+ dnssec\-loadkeys\-interval \fIinteger\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
+ dnssec\-update\-mode ( maintain | no\-resign );
+ file \fIquoted_string\fR;
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR
+ | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. };
+ in\-view \fIstring\fR;
+ inline\-signing \fIboolean\fR;
+ ixfr\-from\-differences \fIboolean\fR;
+ journal \fIquoted_string\fR;
+ key\-directory \fIquoted_string\fR;
+ masterfile\-format ( map | raw | text );
+ masterfile\-style ( full | relative );
+ masters [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR |
+ \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port
+ \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. };
+ max\-journal\-size ( unlimited | \fIsizeval\fR );
+ max\-records \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-zone\-ttl ( unlimited | \fIttlval\fR );
+ min\-refresh\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ multi\-master \fIboolean\fR;
+ notify ( explicit | master\-only | \fIboolean\fR );
+ notify\-delay \fIinteger\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ]
+ [ dscp \fIinteger\fR ];
+ notify\-to\-soa \fIboolean\fR;
+ pubkey \fIinteger\fR \fIinteger\fR
+ request\-expire \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ serial\-update\-method ( date | increment | unixtime );
+ server\-addresses { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port
+ \fIinteger\fR ]; \&.\&.\&. };
+ server\-names { \fIquoted_string\fR; \&.\&.\&. };
+ sig\-signing\-nodes \fIinteger\fR;
+ sig\-signing\-signatures \fIinteger\fR;
+ sig\-signing\-type \fIinteger\fR;
+ sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ];
+ transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [
+ dscp \fIinteger\fR ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * )
+ ] [ dscp \fIinteger\fR ];
+ try\-tcp\-refresh \fIboolean\fR;
+ type ( delegation\-only | forward | hint | master | redirect | slave
+ | static\-stub | stub );
+ update\-check\-ksk \fIboolean\fR;
+ update\-policy ( local | { ( deny | grant ) \fIstring\fR ( 6to4\-self |
+ external | krb5\-self | krb5\-selfsub | krb5\-subdomain | ms\-self
+ | ms\-selfsub | ms\-subdomain | name | self | selfsub | selfwild
+ | subdomain | tcp\-self | wildcard | zonesub ) [ \fIstring\fR ]
+ \fIrrtypelist\fR; \&.\&.\&. };
+ use\-alt\-transfer\-source \fIboolean\fR;
+ zero\-no\-soa\-ttl \fIboolean\fR;
+ zone\-statistics ( full | terse | none | \fIboolean\fR );
+};
+.fi
+.if n \{\
+.RE
+.\}
+.SH "FILES"
+.PP
+/etc/named\&.conf
+.SH "SEE ALSO"
+.PP
+\fBddns-confgen\fR(8),
+\fBnamed\fR(8),
+\fBnamed-checkconf\fR(8),
+\fBrndc\fR(8),
+\fBrndc-confgen\fR(8),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2004-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook
new file mode 100644
index 0000000..113b990
--- /dev/null
+++ b/bin/named/named.conf.docbook
@@ -0,0 +1,1006 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Generated by doc/misc/docbook-options.pl -->
+
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named.conf">
+ <info>
+ <date>2018-06-21</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><filename>named.conf</filename></refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><filename>named.conf</filename></refname>
+ <refpurpose>configuration file for <command>named</command></refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>named.conf</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><filename>named.conf</filename> is the configuration file
+ for
+ <command>named</command>. 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:
+ </para>
+ <para>
+ C style: /* */
+ </para>
+ <para>
+ C++ style: // to end of line
+ </para>
+ <para>
+ Unix style: # to end of line
+ </para>
+ </refsection>
+
+ <refsection><info><title>ACL</title></info>
+
+ <literallayout class="normal">
+acl <replaceable>string</replaceable> { <replaceable>address_match_element</replaceable>; ... };
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>CONTROLS</title></info>
+
+ <literallayout class="normal">
+controls {
+ inet ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> |
+ * ) [ port ( <replaceable>integer</replaceable> | * ) ] allow
+ { <replaceable>address_match_element</replaceable>; ... } [
+ keys { <replaceable>string</replaceable>; ... } ] [ read-only
+ <replaceable>boolean</replaceable> ];
+ unix <replaceable>quoted_string</replaceable> perm <replaceable>integer</replaceable>
+ owner <replaceable>integer</replaceable> group <replaceable>integer</replaceable> [
+ keys { <replaceable>string</replaceable>; ... } ] [ read-only
+ <replaceable>boolean</replaceable> ];
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>DLZ</title></info>
+
+ <literallayout class="normal">
+dlz <replaceable>string</replaceable> {
+ database <replaceable>string</replaceable>;
+ search <replaceable>boolean</replaceable>;
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>DYNDB</title></info>
+
+ <literallayout class="normal">
+dyndb <replaceable>string</replaceable> <replaceable>quoted_string</replaceable> {
+ <replaceable>unspecified-text</replaceable> };
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>KEY</title></info>
+
+ <literallayout class="normal">
+key <replaceable>string</replaceable> {
+ algorithm <replaceable>string</replaceable>;
+ secret <replaceable>string</replaceable>;
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>LOGGING</title></info>
+
+ <literallayout class="normal">
+logging {
+ category <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
+ channel <replaceable>string</replaceable> {
+ buffered <replaceable>boolean</replaceable>;
+ file <replaceable>quoted_string</replaceable> [ versions ( "unlimited" | <replaceable>integer</replaceable> )
+ ] [ size <replaceable>size</replaceable> ];
+ null;
+ print-category <replaceable>boolean</replaceable>;
+ print-severity <replaceable>boolean</replaceable>;
+ print-time <replaceable>boolean</replaceable>;
+ severity <replaceable>log_severity</replaceable>;
+ stderr;
+ syslog [ <replaceable>syslog_facility</replaceable> ];
+ };
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>LWRES</title></info>
+
+ <literallayout class="normal">
+lwres {
+ listen-on [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>ipv4_address</replaceable>
+ | <replaceable>ipv6_address</replaceable> ) [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ]; ... };
+ lwres-clients <replaceable>integer</replaceable>;
+ lwres-tasks <replaceable>integer</replaceable>;
+ ndots <replaceable>integer</replaceable>;
+ search { <replaceable>string</replaceable>; ... };
+ view <replaceable>string</replaceable> [ <replaceable>class</replaceable> ];
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>MANAGED-KEYS</title></info>
+
+ <literallayout class="normal">
+managed-keys { <replaceable>string</replaceable> <replaceable>string</replaceable> <replaceable>integer</replaceable>
+ <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ... };
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>MASTERS</title></info>
+
+ <literallayout class="normal">
+masters <replaceable>string</replaceable> [ port <replaceable>integer</replaceable> ] [ dscp
+ <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> | <replaceable>ipv4_address</replaceable> [
+ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ]; ... };
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+ <literallayout class="normal">
+options {
+ acache-cleaning-interval <replaceable>integer</replaceable>;
+ acache-enable <replaceable>boolean</replaceable>;
+ additional-from-auth <replaceable>boolean</replaceable>;
+ additional-from-cache <replaceable>boolean</replaceable>;
+ allow-new-zones <replaceable>boolean</replaceable>;
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-recursion { <replaceable>address_match_element</replaceable>; ... };
+ allow-recursion-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ also-notify [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> |
+ <replaceable>ipv4_address</replaceable> [ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ]; ... };
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> |
+ * ) ] [ dscp <replaceable>integer</replaceable> ];
+ answer-cookie <replaceable>boolean</replaceable>;
+ attach-cache <replaceable>string</replaceable>;
+ auth-nxdomain <replaceable>boolean</replaceable>; // default changed
+ auto-dnssec ( allow | maintain | off );
+ automatic-interface-scan <replaceable>boolean</replaceable>;
+ avoid-v4-udp-ports { <replaceable>portrange</replaceable>; ... };
+ avoid-v6-udp-ports { <replaceable>portrange</replaceable>; ... };
+ bindkeys-file <replaceable>quoted_string</replaceable>;
+ blackhole { <replaceable>address_match_element</replaceable>; ... };
+ cache-file <replaceable>quoted_string</replaceable>;
+ catalog-zones { zone <replaceable>quoted_string</replaceable> [ default-masters [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> | <replaceable>ipv4_address</replaceable> [
+ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port <replaceable>integer</replaceable> ] ) [ key
+ <replaceable>string</replaceable> ]; ... } ] [ zone-directory <replaceable>quoted_string</replaceable> ] [
+ in-memory <replaceable>boolean</replaceable> ] [ min-update-interval <replaceable>integer</replaceable> ]; ... };
+ check-dup-records ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( master | slave | response
+ ) ( fail | warn | ignore );
+ check-sibling <replaceable>boolean</replaceable>;
+ check-spf ( warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <replaceable>boolean</replaceable>;
+ cleaning-interval <replaceable>integer</replaceable>;
+ clients-per-query <replaceable>integer</replaceable>;
+ cookie-algorithm ( aes | sha1 | sha256 );
+ cookie-secret <replaceable>string</replaceable>;
+ coresize ( default | unlimited | <replaceable>sizeval</replaceable> );
+ datasize ( default | unlimited | <replaceable>sizeval</replaceable> );
+ deny-answer-addresses { <replaceable>address_match_element</replaceable>; ... } [
+ except-from { <replaceable>quoted_string</replaceable>; ... } ];
+ deny-answer-aliases { <replaceable>quoted_string</replaceable>; ... } [ except-from {
+ <replaceable>quoted_string</replaceable>; ... } ];
+ dialup ( notify | notify-passive | passive | refresh | <replaceable>boolean</replaceable> );
+ directory <replaceable>quoted_string</replaceable>;
+ disable-algorithms <replaceable>string</replaceable> { <replaceable>string</replaceable>;
+ ... };
+ disable-ds-digests <replaceable>string</replaceable> { <replaceable>string</replaceable>;
+ ... };
+ disable-empty-zone <replaceable>string</replaceable>;
+ dns64 <replaceable>netprefix</replaceable> {
+ break-dnssec <replaceable>boolean</replaceable>;
+ clients { <replaceable>address_match_element</replaceable>; ... };
+ exclude { <replaceable>address_match_element</replaceable>; ... };
+ mapped { <replaceable>address_match_element</replaceable>; ... };
+ recursive-only <replaceable>boolean</replaceable>;
+ suffix <replaceable>ipv6_address</replaceable>;
+ };
+ dns64-contact <replaceable>string</replaceable>;
+ dns64-server <replaceable>string</replaceable>;
+ dnssec-accept-expired <replaceable>boolean</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
+ dnssec-enable <replaceable>boolean</replaceable>;
+ dnssec-loadkeys-interval <replaceable>integer</replaceable>;
+ dnssec-lookaside ( <replaceable>string</replaceable> trust-anchor
+ <replaceable>string</replaceable> | auto | no );
+ dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
+ dnssec-update-mode ( maintain | no-resign );
+ dnssec-validation ( yes | no | auto );
+ dnstap { ( all | auth | client | forwarder |
+ resolver ) [ ( query | response ) ]; ... };
+ dnstap-identity ( <replaceable>quoted_string</replaceable> | none |
+ hostname );
+ dnstap-output ( file | unix ) <replaceable>quoted_string</replaceable>;
+ dnstap-version ( <replaceable>quoted_string</replaceable> | none );
+ dscp <replaceable>integer</replaceable>;
+ dual-stack-servers [ port <replaceable>integer</replaceable> ] { ( <replaceable>quoted_string</replaceable> [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] | <replaceable>ipv4_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] ); ... };
+ dump-file <replaceable>quoted_string</replaceable>;
+ edns-udp-size <replaceable>integer</replaceable>;
+ empty-contact <replaceable>string</replaceable>;
+ empty-server <replaceable>string</replaceable>;
+ empty-zones-enable <replaceable>boolean</replaceable>;
+ fetch-quota-params <replaceable>integer</replaceable> <replaceable>fixedpoint</replaceable> <replaceable>fixedpoint</replaceable> <replaceable>fixedpoint</replaceable>;
+ fetches-per-server <replaceable>integer</replaceable> [ ( drop | fail ) ];
+ fetches-per-zone <replaceable>integer</replaceable> [ ( drop | fail ) ];
+ files ( default | unlimited | <replaceable>sizeval</replaceable> );
+ filter-aaaa { <replaceable>address_match_element</replaceable>; ... };
+ filter-aaaa-on-v4 ( break-dnssec | <replaceable>boolean</replaceable> );
+ filter-aaaa-on-v6 ( break-dnssec | <replaceable>boolean</replaceable> );
+ flush-zones-on-shutdown <replaceable>boolean</replaceable>;
+ forward ( first | only );
+ forwarders [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>ipv4_address</replaceable>
+ | <replaceable>ipv6_address</replaceable> ) [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ]; ... };
+ fstrm-set-buffer-hint <replaceable>integer</replaceable>;
+ fstrm-set-flush-timeout <replaceable>integer</replaceable>;
+ fstrm-set-input-queue-size <replaceable>integer</replaceable>;
+ fstrm-set-output-notify-threshold <replaceable>integer</replaceable>;
+ fstrm-set-output-queue-model ( mpsc | spsc );
+ fstrm-set-output-queue-size <replaceable>integer</replaceable>;
+ fstrm-set-reopen-interval <replaceable>integer</replaceable>;
+ geoip-directory ( <replaceable>quoted_string</replaceable> | none );
+ geoip-use-ecs <replaceable>boolean</replaceable>;
+ heartbeat-interval <replaceable>integer</replaceable>;
+ hostname ( <replaceable>quoted_string</replaceable> | none );
+ inline-signing <replaceable>boolean</replaceable>;
+ interface-interval <replaceable>integer</replaceable>;
+ ixfr-from-differences ( master | slave | <replaceable>boolean</replaceable> );
+ keep-response-order { <replaceable>address_match_element</replaceable>; ... };
+ key-directory <replaceable>quoted_string</replaceable>;
+ lame-ttl <replaceable>ttlval</replaceable>;
+ listen-on [ port <replaceable>integer</replaceable> ] [ dscp
+ <replaceable>integer</replaceable> ] {
+ <replaceable>address_match_element</replaceable>; ... };
+ listen-on-v6 [ port <replaceable>integer</replaceable> ] [ dscp
+ <replaceable>integer</replaceable> ] {
+ <replaceable>address_match_element</replaceable>; ... };
+ lmdb-mapsize <replaceable>sizeval</replaceable>;
+ lock-file ( <replaceable>quoted_string</replaceable> | none );
+ managed-keys-directory <replaceable>quoted_string</replaceable>;
+ masterfile-format ( map | raw | text );
+ masterfile-style ( full | relative );
+ match-mapped-addresses <replaceable>boolean</replaceable>;
+ max-acache-size ( unlimited | <replaceable>sizeval</replaceable> );
+ max-cache-size ( default | unlimited | <replaceable>sizeval</replaceable> | <replaceable>percentage</replaceable> );
+ max-cache-ttl <replaceable>integer</replaceable>;
+ max-clients-per-query <replaceable>integer</replaceable>;
+ max-journal-size ( unlimited | <replaceable>sizeval</replaceable> );
+ max-ncache-ttl <replaceable>integer</replaceable>;
+ max-records <replaceable>integer</replaceable>;
+ max-recursion-depth <replaceable>integer</replaceable>;
+ max-recursion-queries <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ max-rsa-exponent-size <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ max-zone-ttl ( unlimited | <replaceable>ttlval</replaceable> );
+ memstatistics <replaceable>boolean</replaceable>;
+ memstatistics-file <replaceable>quoted_string</replaceable>;
+ message-compression <replaceable>boolean</replaceable>;
+ min-refresh-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ minimal-any <replaceable>boolean</replaceable>;
+ minimal-responses ( no-auth | no-auth-recursive | <replaceable>boolean</replaceable> );
+ multi-master <replaceable>boolean</replaceable>;
+ no-case-compress { <replaceable>address_match_element</replaceable>; ... };
+ nocookie-udp-size <replaceable>integer</replaceable>;
+ notify ( explicit | master-only | <replaceable>boolean</replaceable> );
+ notify-delay <replaceable>integer</replaceable>;
+ notify-rate <replaceable>integer</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ]
+ [ dscp <replaceable>integer</replaceable> ];
+ notify-to-soa <replaceable>boolean</replaceable>;
+ nta-lifetime <replaceable>ttlval</replaceable>;
+ nta-recheck <replaceable>ttlval</replaceable>;
+ nxdomain-redirect <replaceable>string</replaceable>;
+ pid-file ( <replaceable>quoted_string</replaceable> | none );
+ port <replaceable>integer</replaceable>;
+ preferred-glue <replaceable>string</replaceable>;
+ prefetch <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ];
+ provide-ixfr <replaceable>boolean</replaceable>;
+ query-source ( ( [ address ] ( <replaceable>ipv4_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] ( <replaceable>ipv4_address</replaceable> | * ) ]
+ port ( <replaceable>integer</replaceable> | * ) ) ) [ dscp <replaceable>integer</replaceable> ];
+ query-source-v6 ( ( [ address ] ( <replaceable>ipv6_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] ( <replaceable>ipv6_address</replaceable> | * ) ]
+ port ( <replaceable>integer</replaceable> | * ) ) ) [ dscp <replaceable>integer</replaceable> ];
+ querylog <replaceable>boolean</replaceable>;
+ random-device <replaceable>quoted_string</replaceable>;
+ rate-limit {
+ all-per-second <replaceable>integer</replaceable>;
+ errors-per-second <replaceable>integer</replaceable>;
+ exempt-clients { <replaceable>address_match_element</replaceable>; ... };
+ ipv4-prefix-length <replaceable>integer</replaceable>;
+ ipv6-prefix-length <replaceable>integer</replaceable>;
+ log-only <replaceable>boolean</replaceable>;
+ max-table-size <replaceable>integer</replaceable>;
+ min-table-size <replaceable>integer</replaceable>;
+ nodata-per-second <replaceable>integer</replaceable>;
+ nxdomains-per-second <replaceable>integer</replaceable>;
+ qps-scale <replaceable>integer</replaceable>;
+ referrals-per-second <replaceable>integer</replaceable>;
+ responses-per-second <replaceable>integer</replaceable>;
+ slip <replaceable>integer</replaceable>;
+ window <replaceable>integer</replaceable>;
+ };
+ recursing-file <replaceable>quoted_string</replaceable>;
+ recursion <replaceable>boolean</replaceable>;
+ recursive-clients <replaceable>integer</replaceable>;
+ request-expire <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ request-nsid <replaceable>boolean</replaceable>;
+ require-server-cookie <replaceable>boolean</replaceable>;
+ reserved-sockets <replaceable>integer</replaceable>;
+ resolver-query-timeout <replaceable>integer</replaceable>;
+ response-policy { zone <replaceable>quoted_string</replaceable> [ log <replaceable>boolean</replaceable> ] [
+ max-policy-ttl <replaceable>integer</replaceable> ] [ policy ( cname | disabled | drop |
+ given | no-op | nodata | nxdomain | passthru | tcp-only
+ <replaceable>quoted_string</replaceable> ) ] [ recursive-only <replaceable>boolean</replaceable> ]; ... } [
+ break-dnssec <replaceable>boolean</replaceable> ] [ max-policy-ttl <replaceable>integer</replaceable> ] [
+ min-ns-dots <replaceable>integer</replaceable> ] [ nsip-wait-recurse <replaceable>boolean</replaceable> ] [
+ qname-wait-recurse <replaceable>boolean</replaceable> ] [ recursive-only <replaceable>boolean</replaceable> ];
+ root-delegation-only [ exclude { <replaceable>quoted_string</replaceable>; ... } ];
+ root-key-sentinel <replaceable>boolean</replaceable>;
+ rrset-order { [ class <replaceable>string</replaceable> ] [ type <replaceable>string</replaceable> ] [ name
+ <replaceable>quoted_string</replaceable> ] <replaceable>string</replaceable> <replaceable>string</replaceable>; ... };
+ secroots-file <replaceable>quoted_string</replaceable>;
+ send-cookie <replaceable>boolean</replaceable>;
+ serial-query-rate <replaceable>integer</replaceable>;
+ serial-update-method ( date | increment | unixtime );
+ server-id ( <replaceable>quoted_string</replaceable> | none | hostname );
+ servfail-ttl <replaceable>ttlval</replaceable>;
+ session-keyalg <replaceable>string</replaceable>;
+ session-keyfile ( <replaceable>quoted_string</replaceable> | none );
+ session-keyname <replaceable>string</replaceable>;
+ sig-signing-nodes <replaceable>integer</replaceable>;
+ sig-signing-signatures <replaceable>integer</replaceable>;
+ sig-signing-type <replaceable>integer</replaceable>;
+ sig-validity-interval <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ];
+ sortlist { <replaceable>address_match_element</replaceable>; ... };
+ stacksize ( default | unlimited | <replaceable>sizeval</replaceable> );
+ startup-notify-rate <replaceable>integer</replaceable>;
+ statistics-file <replaceable>quoted_string</replaceable>;
+ tcp-clients <replaceable>integer</replaceable>;
+ tcp-listen-queue <replaceable>integer</replaceable>;
+ tkey-dhkey <replaceable>quoted_string</replaceable> <replaceable>integer</replaceable>;
+ tkey-domain <replaceable>quoted_string</replaceable>;
+ tkey-gssapi-credential <replaceable>quoted_string</replaceable>;
+ tkey-gssapi-keytab <replaceable>quoted_string</replaceable>;
+ transfer-format ( many-answers | one-answer );
+ transfer-message-size <replaceable>integer</replaceable>;
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ transfers-in <replaceable>integer</replaceable>;
+ transfers-out <replaceable>integer</replaceable>;
+ transfers-per-ns <replaceable>integer</replaceable>;
+ trust-anchor-telemetry <replaceable>boolean</replaceable>; // experimental
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ update-check-ksk <replaceable>boolean</replaceable>;
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+ use-v4-udp-ports { <replaceable>portrange</replaceable>; ... };
+ use-v6-udp-ports { <replaceable>portrange</replaceable>; ... };
+ v6-bias <replaceable>integer</replaceable>;
+ version ( <replaceable>quoted_string</replaceable> | none );
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl-cache <replaceable>boolean</replaceable>;
+ zone-statistics ( full | terse | none | <replaceable>boolean</replaceable> );
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>SERVER</title></info>
+
+ <literallayout class="normal">
+server <replaceable>netprefix</replaceable> {
+ bogus <replaceable>boolean</replaceable>;
+ edns <replaceable>boolean</replaceable>;
+ edns-udp-size <replaceable>integer</replaceable>;
+ edns-version <replaceable>integer</replaceable>;
+ keys <replaceable>server_key</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ]
+ [ dscp <replaceable>integer</replaceable> ];
+ provide-ixfr <replaceable>boolean</replaceable>;
+ query-source ( ( [ address ] ( <replaceable>ipv4_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] ( <replaceable>ipv4_address</replaceable> | * ) ]
+ port ( <replaceable>integer</replaceable> | * ) ) ) [ dscp <replaceable>integer</replaceable> ];
+ query-source-v6 ( ( [ address ] ( <replaceable>ipv6_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] ( <replaceable>ipv6_address</replaceable> | * ) ]
+ port ( <replaceable>integer</replaceable> | * ) ) ) [ dscp <replaceable>integer</replaceable> ];
+ request-expire <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ request-nsid <replaceable>boolean</replaceable>;
+ send-cookie <replaceable>boolean</replaceable>;
+ tcp-only <replaceable>boolean</replaceable>;
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ transfers <replaceable>integer</replaceable>;
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>STATISTICS-CHANNELS</title></info>
+
+ <literallayout class="normal">
+statistics-channels {
+ inet ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> |
+ * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ allow { <replaceable>address_match_element</replaceable>; ...
+ } ];
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>TRUSTED-KEYS</title></info>
+
+ <literallayout class="normal">
+trusted-keys { <replaceable>string</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
+ <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ... };
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>VIEW</title></info>
+
+ <literallayout class="normal">
+view <replaceable>string</replaceable> [ <replaceable>class</replaceable> ] {
+ acache-cleaning-interval <replaceable>integer</replaceable>;
+ acache-enable <replaceable>boolean</replaceable>;
+ additional-from-auth <replaceable>boolean</replaceable>;
+ additional-from-cache <replaceable>boolean</replaceable>;
+ allow-new-zones <replaceable>boolean</replaceable>;
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-recursion { <replaceable>address_match_element</replaceable>; ... };
+ allow-recursion-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ also-notify [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> |
+ <replaceable>ipv4_address</replaceable> [ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ]; ... };
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> |
+ * ) ] [ dscp <replaceable>integer</replaceable> ];
+ attach-cache <replaceable>string</replaceable>;
+ auth-nxdomain <replaceable>boolean</replaceable>; // default changed
+ auto-dnssec ( allow | maintain | off );
+ cache-file <replaceable>quoted_string</replaceable>;
+ catalog-zones { zone <replaceable>quoted_string</replaceable> [ default-masters [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> | <replaceable>ipv4_address</replaceable> [
+ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port <replaceable>integer</replaceable> ] ) [ key
+ <replaceable>string</replaceable> ]; ... } ] [ zone-directory <replaceable>quoted_string</replaceable> ] [
+ in-memory <replaceable>boolean</replaceable> ] [ min-update-interval <replaceable>integer</replaceable> ]; ... };
+ check-dup-records ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( master | slave | response
+ ) ( fail | warn | ignore );
+ check-sibling <replaceable>boolean</replaceable>;
+ check-spf ( warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <replaceable>boolean</replaceable>;
+ cleaning-interval <replaceable>integer</replaceable>;
+ clients-per-query <replaceable>integer</replaceable>;
+ deny-answer-addresses { <replaceable>address_match_element</replaceable>; ... } [
+ except-from { <replaceable>quoted_string</replaceable>; ... } ];
+ deny-answer-aliases { <replaceable>quoted_string</replaceable>; ... } [ except-from {
+ <replaceable>quoted_string</replaceable>; ... } ];
+ dialup ( notify | notify-passive | passive | refresh | <replaceable>boolean</replaceable> );
+ disable-algorithms <replaceable>string</replaceable> { <replaceable>string</replaceable>;
+ ... };
+ disable-ds-digests <replaceable>string</replaceable> { <replaceable>string</replaceable>;
+ ... };
+ disable-empty-zone <replaceable>string</replaceable>;
+ dlz <replaceable>string</replaceable> {
+ database <replaceable>string</replaceable>;
+ search <replaceable>boolean</replaceable>;
+ };
+ dns64 <replaceable>netprefix</replaceable> {
+ break-dnssec <replaceable>boolean</replaceable>;
+ clients { <replaceable>address_match_element</replaceable>; ... };
+ exclude { <replaceable>address_match_element</replaceable>; ... };
+ mapped { <replaceable>address_match_element</replaceable>; ... };
+ recursive-only <replaceable>boolean</replaceable>;
+ suffix <replaceable>ipv6_address</replaceable>;
+ };
+ dns64-contact <replaceable>string</replaceable>;
+ dns64-server <replaceable>string</replaceable>;
+ dnssec-accept-expired <replaceable>boolean</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
+ dnssec-enable <replaceable>boolean</replaceable>;
+ dnssec-loadkeys-interval <replaceable>integer</replaceable>;
+ dnssec-lookaside ( <replaceable>string</replaceable> trust-anchor
+ <replaceable>string</replaceable> | auto | no );
+ dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
+ dnssec-update-mode ( maintain | no-resign );
+ dnssec-validation ( yes | no | auto );
+ dnstap { ( all | auth | client | forwarder |
+ resolver ) [ ( query | response ) ]; ... };
+ dual-stack-servers [ port <replaceable>integer</replaceable> ] { ( <replaceable>quoted_string</replaceable> [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] | <replaceable>ipv4_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] ); ... };
+ dyndb <replaceable>string</replaceable> <replaceable>quoted_string</replaceable> {
+ <replaceable>unspecified-text</replaceable> };
+ edns-udp-size <replaceable>integer</replaceable>;
+ empty-contact <replaceable>string</replaceable>;
+ empty-server <replaceable>string</replaceable>;
+ empty-zones-enable <replaceable>boolean</replaceable>;
+ fetch-quota-params <replaceable>integer</replaceable> <replaceable>fixedpoint</replaceable> <replaceable>fixedpoint</replaceable> <replaceable>fixedpoint</replaceable>;
+ fetches-per-server <replaceable>integer</replaceable> [ ( drop | fail ) ];
+ fetches-per-zone <replaceable>integer</replaceable> [ ( drop | fail ) ];
+ filter-aaaa { <replaceable>address_match_element</replaceable>; ... };
+ filter-aaaa-on-v4 ( break-dnssec | <replaceable>boolean</replaceable> );
+ filter-aaaa-on-v6 ( break-dnssec | <replaceable>boolean</replaceable> );
+ forward ( first | only );
+ forwarders [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>ipv4_address</replaceable>
+ | <replaceable>ipv6_address</replaceable> ) [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ]; ... };
+ inline-signing <replaceable>boolean</replaceable>;
+ ixfr-from-differences ( master | slave | <replaceable>boolean</replaceable> );
+ key <replaceable>string</replaceable> {
+ algorithm <replaceable>string</replaceable>;
+ secret <replaceable>string</replaceable>;
+ };
+ key-directory <replaceable>quoted_string</replaceable>;
+ lame-ttl <replaceable>ttlval</replaceable>;
+ lmdb-mapsize <replaceable>sizeval</replaceable>;
+ managed-keys { <replaceable>string</replaceable> <replaceable>string</replaceable>
+ <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
+ <replaceable>quoted_string</replaceable>; ... };
+ masterfile-format ( map | raw | text );
+ masterfile-style ( full | relative );
+ match-clients { <replaceable>address_match_element</replaceable>; ... };
+ match-destinations { <replaceable>address_match_element</replaceable>; ... };
+ match-recursive-only <replaceable>boolean</replaceable>;
+ max-acache-size ( unlimited | <replaceable>sizeval</replaceable> );
+ max-cache-size ( default | unlimited | <replaceable>sizeval</replaceable> | <replaceable>percentage</replaceable> );
+ max-cache-ttl <replaceable>integer</replaceable>;
+ max-clients-per-query <replaceable>integer</replaceable>;
+ max-journal-size ( unlimited | <replaceable>sizeval</replaceable> );
+ max-ncache-ttl <replaceable>integer</replaceable>;
+ max-records <replaceable>integer</replaceable>;
+ max-recursion-depth <replaceable>integer</replaceable>;
+ max-recursion-queries <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ max-zone-ttl ( unlimited | <replaceable>ttlval</replaceable> );
+ message-compression <replaceable>boolean</replaceable>;
+ min-refresh-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ minimal-any <replaceable>boolean</replaceable>;
+ minimal-responses ( no-auth | no-auth-recursive | <replaceable>boolean</replaceable> );
+ multi-master <replaceable>boolean</replaceable>;
+ no-case-compress { <replaceable>address_match_element</replaceable>; ... };
+ nocookie-udp-size <replaceable>integer</replaceable>;
+ notify ( explicit | master-only | <replaceable>boolean</replaceable> );
+ notify-delay <replaceable>integer</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ]
+ [ dscp <replaceable>integer</replaceable> ];
+ notify-to-soa <replaceable>boolean</replaceable>;
+ nta-lifetime <replaceable>ttlval</replaceable>;
+ nta-recheck <replaceable>ttlval</replaceable>;
+ nxdomain-redirect <replaceable>string</replaceable>;
+ preferred-glue <replaceable>string</replaceable>;
+ prefetch <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ];
+ provide-ixfr <replaceable>boolean</replaceable>;
+ query-source ( ( [ address ] ( <replaceable>ipv4_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] ( <replaceable>ipv4_address</replaceable> | * ) ]
+ port ( <replaceable>integer</replaceable> | * ) ) ) [ dscp <replaceable>integer</replaceable> ];
+ query-source-v6 ( ( [ address ] ( <replaceable>ipv6_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] ( <replaceable>ipv6_address</replaceable> | * ) ]
+ port ( <replaceable>integer</replaceable> | * ) ) ) [ dscp <replaceable>integer</replaceable> ];
+ rate-limit {
+ all-per-second <replaceable>integer</replaceable>;
+ errors-per-second <replaceable>integer</replaceable>;
+ exempt-clients { <replaceable>address_match_element</replaceable>; ... };
+ ipv4-prefix-length <replaceable>integer</replaceable>;
+ ipv6-prefix-length <replaceable>integer</replaceable>;
+ log-only <replaceable>boolean</replaceable>;
+ max-table-size <replaceable>integer</replaceable>;
+ min-table-size <replaceable>integer</replaceable>;
+ nodata-per-second <replaceable>integer</replaceable>;
+ nxdomains-per-second <replaceable>integer</replaceable>;
+ qps-scale <replaceable>integer</replaceable>;
+ referrals-per-second <replaceable>integer</replaceable>;
+ responses-per-second <replaceable>integer</replaceable>;
+ slip <replaceable>integer</replaceable>;
+ window <replaceable>integer</replaceable>;
+ };
+ recursion <replaceable>boolean</replaceable>;
+ request-expire <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ request-nsid <replaceable>boolean</replaceable>;
+ require-server-cookie <replaceable>boolean</replaceable>;
+ resolver-query-timeout <replaceable>integer</replaceable>;
+ response-policy { zone <replaceable>quoted_string</replaceable> [ log <replaceable>boolean</replaceable> ] [
+ max-policy-ttl <replaceable>integer</replaceable> ] [ policy ( cname | disabled | drop |
+ given | no-op | nodata | nxdomain | passthru | tcp-only
+ <replaceable>quoted_string</replaceable> ) ] [ recursive-only <replaceable>boolean</replaceable> ]; ... } [
+ break-dnssec <replaceable>boolean</replaceable> ] [ max-policy-ttl <replaceable>integer</replaceable> ] [
+ min-ns-dots <replaceable>integer</replaceable> ] [ nsip-wait-recurse <replaceable>boolean</replaceable> ] [
+ qname-wait-recurse <replaceable>boolean</replaceable> ] [ recursive-only <replaceable>boolean</replaceable> ];
+ root-delegation-only [ exclude { <replaceable>quoted_string</replaceable>; ... } ];
+ root-key-sentinel <replaceable>boolean</replaceable>;
+ rrset-order { [ class <replaceable>string</replaceable> ] [ type <replaceable>string</replaceable> ] [ name
+ <replaceable>quoted_string</replaceable> ] <replaceable>string</replaceable> <replaceable>string</replaceable>; ... };
+ send-cookie <replaceable>boolean</replaceable>;
+ serial-update-method ( date | increment | unixtime );
+ server <replaceable>netprefix</replaceable> {
+ bogus <replaceable>boolean</replaceable>;
+ edns <replaceable>boolean</replaceable>;
+ edns-udp-size <replaceable>integer</replaceable>;
+ edns-version <replaceable>integer</replaceable>;
+ keys <replaceable>server_key</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | *
+ ) ] [ dscp <replaceable>integer</replaceable> ];
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable>
+ | * ) ] [ dscp <replaceable>integer</replaceable> ];
+ provide-ixfr <replaceable>boolean</replaceable>;
+ query-source ( ( [ address ] ( <replaceable>ipv4_address</replaceable> | * ) [ port
+ ( <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] (
+ <replaceable>ipv4_address</replaceable> | * ) ] port ( <replaceable>integer</replaceable> | * ) ) ) [
+ dscp <replaceable>integer</replaceable> ];
+ query-source-v6 ( ( [ address ] ( <replaceable>ipv6_address</replaceable> | * ) [
+ port ( <replaceable>integer</replaceable> | * ) ] ) | ( [ [ address ] (
+ <replaceable>ipv6_address</replaceable> | * ) ] port ( <replaceable>integer</replaceable> | * ) ) ) [
+ dscp <replaceable>integer</replaceable> ];
+ request-expire <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ request-nsid <replaceable>boolean</replaceable>;
+ send-cookie <replaceable>boolean</replaceable>;
+ tcp-only <replaceable>boolean</replaceable>;
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> |
+ * ) ] [ dscp <replaceable>integer</replaceable> ];
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] [ dscp <replaceable>integer</replaceable> ];
+ transfers <replaceable>integer</replaceable>;
+ };
+ servfail-ttl <replaceable>ttlval</replaceable>;
+ sig-signing-nodes <replaceable>integer</replaceable>;
+ sig-signing-signatures <replaceable>integer</replaceable>;
+ sig-signing-type <replaceable>integer</replaceable>;
+ sig-validity-interval <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ];
+ sortlist { <replaceable>address_match_element</replaceable>; ... };
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ trust-anchor-telemetry <replaceable>boolean</replaceable>; // experimental
+ trusted-keys { <replaceable>string</replaceable> <replaceable>integer</replaceable>
+ <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>;
+ ... };
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ update-check-ksk <replaceable>boolean</replaceable>;
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+ v6-bias <replaceable>integer</replaceable>;
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl-cache <replaceable>boolean</replaceable>;
+ zone <replaceable>string</replaceable> [ <replaceable>class</replaceable> ] {
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ also-notify [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { (
+ <replaceable>masters</replaceable> | <replaceable>ipv4_address</replaceable> [ port <replaceable>integer</replaceable> ] |
+ <replaceable>ipv6_address</replaceable> [ port <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ];
+ ... };
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] [ dscp <replaceable>integer</replaceable> ];
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] [ dscp <replaceable>integer</replaceable> ];
+ auto-dnssec ( allow | maintain | off );
+ check-dup-records ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( fail | warn | ignore );
+ check-sibling <replaceable>boolean</replaceable>;
+ check-spf ( warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <replaceable>boolean</replaceable>;
+ database <replaceable>string</replaceable>;
+ delegation-only <replaceable>boolean</replaceable>;
+ dialup ( notify | notify-passive | passive | refresh |
+ <replaceable>boolean</replaceable> );
+ dlz <replaceable>string</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
+ dnssec-loadkeys-interval <replaceable>integer</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
+ dnssec-update-mode ( maintain | no-resign );
+ file <replaceable>quoted_string</replaceable>;
+ forward ( first | only );
+ forwarders [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { (
+ <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) [ port <replaceable>integer</replaceable> ] [
+ dscp <replaceable>integer</replaceable> ]; ... };
+ in-view <replaceable>string</replaceable>;
+ inline-signing <replaceable>boolean</replaceable>;
+ ixfr-from-differences <replaceable>boolean</replaceable>;
+ journal <replaceable>quoted_string</replaceable>;
+ key-directory <replaceable>quoted_string</replaceable>;
+ masterfile-format ( map | raw | text );
+ masterfile-style ( full | relative );
+ masters [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable>
+ | <replaceable>ipv4_address</replaceable> [ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [
+ port <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ]; ... };
+ max-ixfr-log-size ( default | unlimited |
+ max-journal-size ( unlimited | <replaceable>sizeval</replaceable> );
+ max-records <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-zone-ttl ( unlimited | <replaceable>ttlval</replaceable> );
+ min-refresh-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ multi-master <replaceable>boolean</replaceable>;
+ notify ( explicit | master-only | <replaceable>boolean</replaceable> );
+ notify-delay <replaceable>integer</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | *
+ ) ] [ dscp <replaceable>integer</replaceable> ];
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable>
+ | * ) ] [ dscp <replaceable>integer</replaceable> ];
+ notify-to-soa <replaceable>boolean</replaceable>;
+ pubkey <replaceable>integer</replaceable>
+ <replaceable>integer</replaceable>
+ <replaceable>integer</replaceable>
+ request-expire <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ serial-update-method ( date | increment | unixtime );
+ server-addresses { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) [
+ port <replaceable>integer</replaceable> ]; ... };
+ server-names { <replaceable>quoted_string</replaceable>; ... };
+ sig-signing-nodes <replaceable>integer</replaceable>;
+ sig-signing-signatures <replaceable>integer</replaceable>;
+ sig-signing-type <replaceable>integer</replaceable>;
+ sig-validity-interval <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ];
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> |
+ * ) ] [ dscp <replaceable>integer</replaceable> ];
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port (
+ <replaceable>integer</replaceable> | * ) ] [ dscp <replaceable>integer</replaceable> ];
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ type ( delegation-only | forward | hint | master | redirect
+ | slave | static-stub | stub );
+ update-check-ksk <replaceable>boolean</replaceable>;
+ update-policy ( local | { ( deny | grant ) <replaceable>string</replaceable> (
+ 6to4-self | external | krb5-self | krb5-selfsub |
+ krb5-subdomain | ms-self | ms-selfsub | ms-subdomain |
+ name | self | selfsub | selfwild | subdomain | tcp-self
+ | wildcard | zonesub ) [ <replaceable>string</replaceable> ] <replaceable>rrtypelist</replaceable>; ... };
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ zone-statistics ( full | terse | none | <replaceable>boolean</replaceable> );
+ };
+ zone-statistics ( full | terse | none | <replaceable>boolean</replaceable> );
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>ZONE</title></info>
+
+ <literallayout class="normal">
+zone <replaceable>string</replaceable> [ <replaceable>class</replaceable> ] {
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ also-notify [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> |
+ <replaceable>ipv4_address</replaceable> [ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ]; ... };
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> |
+ * ) ] [ dscp <replaceable>integer</replaceable> ];
+ auto-dnssec ( allow | maintain | off );
+ check-dup-records ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( fail | warn | ignore );
+ check-sibling <replaceable>boolean</replaceable>;
+ check-spf ( warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <replaceable>boolean</replaceable>;
+ database <replaceable>string</replaceable>;
+ delegation-only <replaceable>boolean</replaceable>;
+ dialup ( notify | notify-passive | passive | refresh | <replaceable>boolean</replaceable> );
+ dlz <replaceable>string</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
+ dnssec-loadkeys-interval <replaceable>integer</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
+ dnssec-update-mode ( maintain | no-resign );
+ file <replaceable>quoted_string</replaceable>;
+ forward ( first | only );
+ forwarders [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>ipv4_address</replaceable>
+ | <replaceable>ipv6_address</replaceable> ) [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ]; ... };
+ in-view <replaceable>string</replaceable>;
+ inline-signing <replaceable>boolean</replaceable>;
+ ixfr-from-differences <replaceable>boolean</replaceable>;
+ journal <replaceable>quoted_string</replaceable>;
+ key-directory <replaceable>quoted_string</replaceable>;
+ masterfile-format ( map | raw | text );
+ masterfile-style ( full | relative );
+ masters [ port <replaceable>integer</replaceable> ] [ dscp <replaceable>integer</replaceable> ] { ( <replaceable>masters</replaceable> |
+ <replaceable>ipv4_address</replaceable> [ port <replaceable>integer</replaceable> ] | <replaceable>ipv6_address</replaceable> [ port
+ <replaceable>integer</replaceable> ] ) [ key <replaceable>string</replaceable> ]; ... };
+ max-journal-size ( unlimited | <replaceable>sizeval</replaceable> );
+ max-records <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-zone-ttl ( unlimited | <replaceable>ttlval</replaceable> );
+ min-refresh-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ multi-master <replaceable>boolean</replaceable>;
+ notify ( explicit | master-only | <replaceable>boolean</replaceable> );
+ notify-delay <replaceable>integer</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ]
+ [ dscp <replaceable>integer</replaceable> ];
+ notify-to-soa <replaceable>boolean</replaceable>;
+ pubkey <replaceable>integer</replaceable> <replaceable>integer</replaceable>
+ request-expire <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ serial-update-method ( date | increment | unixtime );
+ server-addresses { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) [ port
+ <replaceable>integer</replaceable> ]; ... };
+ server-names { <replaceable>quoted_string</replaceable>; ... };
+ sig-signing-nodes <replaceable>integer</replaceable>;
+ sig-signing-signatures <replaceable>integer</replaceable>;
+ sig-signing-type <replaceable>integer</replaceable>;
+ sig-validity-interval <replaceable>integer</replaceable> [ <replaceable>integer</replaceable> ];
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * ) ] [
+ dscp <replaceable>integer</replaceable> ];
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) [ port ( <replaceable>integer</replaceable> | * )
+ ] [ dscp <replaceable>integer</replaceable> ];
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ type ( delegation-only | forward | hint | master | redirect | slave
+ | static-stub | stub );
+ update-check-ksk <replaceable>boolean</replaceable>;
+ update-policy ( local | { ( deny | grant ) <replaceable>string</replaceable> ( 6to4-self |
+ external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self
+ | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild
+ | subdomain | tcp-self | wildcard | zonesub ) [ <replaceable>string</replaceable> ]
+ <replaceable>rrtypelist</replaceable>; ... };
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ zone-statistics ( full | terse | none | <replaceable>boolean</replaceable> );
+};
+</literallayout>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/named.conf</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>ddns-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkconf</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/named/named.conf.html b/bin/named/named.conf.html
new file mode 100644
index 0000000..537eafc
--- /dev/null
+++ b/bin/named/named.conf.html
@@ -0,0 +1,1002 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2004-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named.conf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named.conf"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <code class="filename">named.conf</code>
+ &#8212; configuration file for <span class="command"><strong>named</strong></span>
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named.conf</code>
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><code class="filename">named.conf</code> is the configuration file
+ for
+ <span class="command"><strong>named</strong></span>. 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:
+ </p>
+ <p>
+ C style: /* */
+ </p>
+ <p>
+ C++ style: // to end of line
+ </p>
+ <p>
+ Unix style: # to end of line
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ACL</h2>
+
+ <div class="literallayout"><p><br>
+acl <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>CONTROLS</h2>
+
+ <div class="literallayout"><p><br>
+controls {<br>
+ inet ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> |<br>
+     * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] allow<br>
+     { <em class="replaceable"><code>address_match_element</code></em>; ... } [<br>
+     keys { <em class="replaceable"><code>string</code></em>; ... } ] [ read-only<br>
+     <em class="replaceable"><code>boolean</code></em> ];<br>
+ unix <em class="replaceable"><code>quoted_string</code></em> perm <em class="replaceable"><code>integer</code></em><br>
+     owner <em class="replaceable"><code>integer</code></em> group <em class="replaceable"><code>integer</code></em> [<br>
+     keys { <em class="replaceable"><code>string</code></em>; ... } ] [ read-only<br>
+     <em class="replaceable"><code>boolean</code></em> ];<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>DLZ</h2>
+
+ <div class="literallayout"><p><br>
+dlz <em class="replaceable"><code>string</code></em> {<br>
+ database <em class="replaceable"><code>string</code></em>;<br>
+ search <em class="replaceable"><code>boolean</code></em>;<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>DYNDB</h2>
+
+ <div class="literallayout"><p><br>
+dyndb <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>quoted_string</code></em> {<br>
+    <em class="replaceable"><code>unspecified-text</code></em> };<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>KEY</h2>
+
+ <div class="literallayout"><p><br>
+key <em class="replaceable"><code>string</code></em> {<br>
+ algorithm <em class="replaceable"><code>string</code></em>;<br>
+ secret <em class="replaceable"><code>string</code></em>;<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.13"></a><h2>LOGGING</h2>
+
+ <div class="literallayout"><p><br>
+logging {<br>
+ category <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>; ... };<br>
+ channel <em class="replaceable"><code>string</code></em> {<br>
+ buffered <em class="replaceable"><code>boolean</code></em>;<br>
+ file <em class="replaceable"><code>quoted_string</code></em> [ versions ( "unlimited" | <em class="replaceable"><code>integer</code></em> )<br>
+     ] [ size <em class="replaceable"><code>size</code></em> ];<br>
+ null;<br>
+ print-category <em class="replaceable"><code>boolean</code></em>;<br>
+ print-severity <em class="replaceable"><code>boolean</code></em>;<br>
+ print-time <em class="replaceable"><code>boolean</code></em>;<br>
+ severity <em class="replaceable"><code>log_severity</code></em>;<br>
+ stderr;<br>
+ syslog [ <em class="replaceable"><code>syslog_facility</code></em> ];<br>
+ };<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.14"></a><h2>LWRES</h2>
+
+ <div class="literallayout"><p><br>
+lwres {<br>
+ listen-on [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>ipv4_address</code></em><br>
+     | <em class="replaceable"><code>ipv6_address</code></em> ) [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ lwres-clients <em class="replaceable"><code>integer</code></em>;<br>
+ lwres-tasks <em class="replaceable"><code>integer</code></em>;<br>
+ ndots <em class="replaceable"><code>integer</code></em>;<br>
+ search { <em class="replaceable"><code>string</code></em>; ... };<br>
+ view <em class="replaceable"><code>string</code></em> [ <em class="replaceable"><code>class</code></em> ];<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.15"></a><h2>MANAGED-KEYS</h2>
+
+ <div class="literallayout"><p><br>
+managed-keys { <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em><br>
+    <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>; ... };<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.16"></a><h2>MASTERS</h2>
+
+ <div class="literallayout"><p><br>
+masters <em class="replaceable"><code>string</code></em> [ port <em class="replaceable"><code>integer</code></em> ] [ dscp<br>
+    <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<br>
+    port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+    <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ]; ... };<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.17"></a><h2>OPTIONS</h2>
+
+ <div class="literallayout"><p><br>
+options {<br>
+ acache-cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ acache-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ additional-from-auth <em class="replaceable"><code>boolean</code></em>;<br>
+ additional-from-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ allow-new-zones <em class="replaceable"><code>boolean</code></em>;<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-recursion { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-recursion-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ also-notify [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> |<br>
+     <em class="replaceable"><code>ipv4_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ]; ... };<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> |<br>
+     * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ answer-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ attach-cache <em class="replaceable"><code>string</code></em>;<br>
+ auth-nxdomain <em class="replaceable"><code>boolean</code></em>; // default changed<br>
+ auto-dnssec ( allow | maintain | off );<br>
+ automatic-interface-scan <em class="replaceable"><code>boolean</code></em>;<br>
+ avoid-v4-udp-ports { <em class="replaceable"><code>portrange</code></em>; ... };<br>
+ avoid-v6-udp-ports { <em class="replaceable"><code>portrange</code></em>; ... };<br>
+ bindkeys-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ blackhole { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ cache-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ catalog-zones { zone <em class="replaceable"><code>quoted_string</code></em> [ default-masters [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<br>
+     port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] ) [ key<br>
+     <em class="replaceable"><code>string</code></em> ]; ... } ] [ zone-directory <em class="replaceable"><code>quoted_string</code></em> ] [<br>
+     in-memory <em class="replaceable"><code>boolean</code></em> ] [ min-update-interval <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ check-dup-records ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-names ( master | slave | response<br>
+     ) ( fail | warn | ignore );<br>
+ check-sibling <em class="replaceable"><code>boolean</code></em>;<br>
+ check-spf ( warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ check-wildcard <em class="replaceable"><code>boolean</code></em>;<br>
+ cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ clients-per-query <em class="replaceable"><code>integer</code></em>;<br>
+ cookie-algorithm ( aes | sha1 | sha256 );<br>
+ cookie-secret <em class="replaceable"><code>string</code></em>;<br>
+ coresize ( default | unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ datasize ( default | unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ deny-answer-addresses { <em class="replaceable"><code>address_match_element</code></em>; ... } [<br>
+     except-from { <em class="replaceable"><code>quoted_string</code></em>; ... } ];<br>
+ deny-answer-aliases { <em class="replaceable"><code>quoted_string</code></em>; ... } [ except-from {<br>
+     <em class="replaceable"><code>quoted_string</code></em>; ... } ];<br>
+ dialup ( notify | notify-passive | passive | refresh | <em class="replaceable"><code>boolean</code></em> );<br>
+ directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ disable-algorithms <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>;<br>
+     ... };<br>
+ disable-ds-digests <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>;<br>
+     ... };<br>
+ disable-empty-zone <em class="replaceable"><code>string</code></em>;<br>
+ dns64 <em class="replaceable"><code>netprefix</code></em> {<br>
+ break-dnssec <em class="replaceable"><code>boolean</code></em>;<br>
+ clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ exclude { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ mapped { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ recursive-only <em class="replaceable"><code>boolean</code></em>;<br>
+ suffix <em class="replaceable"><code>ipv6_address</code></em>;<br>
+ };<br>
+ dns64-contact <em class="replaceable"><code>string</code></em>;<br>
+ dns64-server <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-loadkeys-interval <em class="replaceable"><code>integer</code></em>;<br>
+ dnssec-lookaside ( <em class="replaceable"><code>string</code></em> trust-anchor<br>
+     <em class="replaceable"><code>string</code></em> | auto | no );<br>
+ dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-update-mode ( maintain | no-resign );<br>
+ dnssec-validation ( yes | no | auto );<br>
+ dnstap { ( all | auth | client | forwarder |<br>
+     resolver ) [ ( query | response ) ]; ... };<br>
+ dnstap-identity ( <em class="replaceable"><code>quoted_string</code></em> | none |<br>
+     hostname );<br>
+ dnstap-output ( file | unix ) <em class="replaceable"><code>quoted_string</code></em>;<br>
+ dnstap-version ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ dscp <em class="replaceable"><code>integer</code></em>;<br>
+ dual-stack-servers [ port <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>quoted_string</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv4_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] ); ... };<br>
+ dump-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ empty-contact <em class="replaceable"><code>string</code></em>;<br>
+ empty-server <em class="replaceable"><code>string</code></em>;<br>
+ empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ fetch-quota-params <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>fixedpoint</code></em> <em class="replaceable"><code>fixedpoint</code></em> <em class="replaceable"><code>fixedpoint</code></em>;<br>
+ fetches-per-server <em class="replaceable"><code>integer</code></em> [ ( drop | fail ) ];<br>
+ fetches-per-zone <em class="replaceable"><code>integer</code></em> [ ( drop | fail ) ];<br>
+ files ( default | unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ filter-aaaa { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ filter-aaaa-on-v4 ( break-dnssec | <em class="replaceable"><code>boolean</code></em> );<br>
+ filter-aaaa-on-v6 ( break-dnssec | <em class="replaceable"><code>boolean</code></em> );<br>
+ flush-zones-on-shutdown <em class="replaceable"><code>boolean</code></em>;<br>
+ forward ( first | only );<br>
+ forwarders [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>ipv4_address</code></em><br>
+     | <em class="replaceable"><code>ipv6_address</code></em> ) [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ fstrm-set-buffer-hint <em class="replaceable"><code>integer</code></em>;<br>
+ fstrm-set-flush-timeout <em class="replaceable"><code>integer</code></em>;<br>
+ fstrm-set-input-queue-size <em class="replaceable"><code>integer</code></em>;<br>
+ fstrm-set-output-notify-threshold <em class="replaceable"><code>integer</code></em>;<br>
+ fstrm-set-output-queue-model ( mpsc | spsc );<br>
+ fstrm-set-output-queue-size <em class="replaceable"><code>integer</code></em>;<br>
+ fstrm-set-reopen-interval <em class="replaceable"><code>integer</code></em>;<br>
+ geoip-directory ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ geoip-use-ecs <em class="replaceable"><code>boolean</code></em>;<br>
+ heartbeat-interval <em class="replaceable"><code>integer</code></em>;<br>
+ hostname ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ inline-signing <em class="replaceable"><code>boolean</code></em>;<br>
+ interface-interval <em class="replaceable"><code>integer</code></em>;<br>
+ ixfr-from-differences ( master | slave | <em class="replaceable"><code>boolean</code></em> );<br>
+ keep-response-order { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ lame-ttl <em class="replaceable"><code>ttlval</code></em>;<br>
+ listen-on [ port <em class="replaceable"><code>integer</code></em> ] [ dscp<br>
+     <em class="replaceable"><code>integer</code></em> ] {<br>
+     <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ listen-on-v6 [ port <em class="replaceable"><code>integer</code></em> ] [ dscp<br>
+     <em class="replaceable"><code>integer</code></em> ] {<br>
+     <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ lmdb-mapsize <em class="replaceable"><code>sizeval</code></em>;<br>
+ lock-file ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ managed-keys-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ masterfile-format ( map | raw | text );<br>
+ masterfile-style ( full | relative );<br>
+ match-mapped-addresses <em class="replaceable"><code>boolean</code></em>;<br>
+ max-acache-size ( unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ max-cache-size ( default | unlimited | <em class="replaceable"><code>sizeval</code></em> | <em class="replaceable"><code>percentage</code></em> );<br>
+ max-cache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-clients-per-query <em class="replaceable"><code>integer</code></em>;<br>
+ max-journal-size ( unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-records <em class="replaceable"><code>integer</code></em>;<br>
+ max-recursion-depth <em class="replaceable"><code>integer</code></em>;<br>
+ max-recursion-queries <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-rsa-exponent-size <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ max-zone-ttl ( unlimited | <em class="replaceable"><code>ttlval</code></em> );<br>
+ memstatistics <em class="replaceable"><code>boolean</code></em>;<br>
+ memstatistics-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ message-compression <em class="replaceable"><code>boolean</code></em>;<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ minimal-any <em class="replaceable"><code>boolean</code></em>;<br>
+ minimal-responses ( no-auth | no-auth-recursive | <em class="replaceable"><code>boolean</code></em> );<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+ no-case-compress { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ nocookie-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ notify ( explicit | master-only | <em class="replaceable"><code>boolean</code></em> );<br>
+ notify-delay <em class="replaceable"><code>integer</code></em>;<br>
+ notify-rate <em class="replaceable"><code>integer</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ]<br>
+     [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ nta-lifetime <em class="replaceable"><code>ttlval</code></em>;<br>
+ nta-recheck <em class="replaceable"><code>ttlval</code></em>;<br>
+ nxdomain-redirect <em class="replaceable"><code>string</code></em>;<br>
+ pid-file ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ port <em class="replaceable"><code>integer</code></em>;<br>
+ preferred-glue <em class="replaceable"><code>string</code></em>;<br>
+ prefetch <em class="replaceable"><code>integer</code></em> [ <em class="replaceable"><code>integer</code></em> ];<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ query-source ( ( [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) ]<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ query-source-v6 ( ( [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) ]<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ querylog <em class="replaceable"><code>boolean</code></em>;<br>
+ random-device <em class="replaceable"><code>quoted_string</code></em>;<br>
+ rate-limit {<br>
+ all-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ errors-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ exempt-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ ipv4-prefix-length <em class="replaceable"><code>integer</code></em>;<br>
+ ipv6-prefix-length <em class="replaceable"><code>integer</code></em>;<br>
+ log-only <em class="replaceable"><code>boolean</code></em>;<br>
+ max-table-size <em class="replaceable"><code>integer</code></em>;<br>
+ min-table-size <em class="replaceable"><code>integer</code></em>;<br>
+ nodata-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ nxdomains-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ qps-scale <em class="replaceable"><code>integer</code></em>;<br>
+ referrals-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ responses-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ slip <em class="replaceable"><code>integer</code></em>;<br>
+ window <em class="replaceable"><code>integer</code></em>;<br>
+ };<br>
+ recursing-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ recursion <em class="replaceable"><code>boolean</code></em>;<br>
+ recursive-clients <em class="replaceable"><code>integer</code></em>;<br>
+ request-expire <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-nsid <em class="replaceable"><code>boolean</code></em>;<br>
+ require-server-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ reserved-sockets <em class="replaceable"><code>integer</code></em>;<br>
+ resolver-query-timeout <em class="replaceable"><code>integer</code></em>;<br>
+ response-policy { zone <em class="replaceable"><code>quoted_string</code></em> [ log <em class="replaceable"><code>boolean</code></em> ] [<br>
+     max-policy-ttl <em class="replaceable"><code>integer</code></em> ] [ policy ( cname | disabled | drop |<br>
+     given | no-op | nodata | nxdomain | passthru | tcp-only<br>
+     <em class="replaceable"><code>quoted_string</code></em> ) ] [ recursive-only <em class="replaceable"><code>boolean</code></em> ]; ... } [<br>
+     break-dnssec <em class="replaceable"><code>boolean</code></em> ] [ max-policy-ttl <em class="replaceable"><code>integer</code></em> ] [<br>
+     min-ns-dots <em class="replaceable"><code>integer</code></em> ] [ nsip-wait-recurse <em class="replaceable"><code>boolean</code></em> ] [<br>
+     qname-wait-recurse <em class="replaceable"><code>boolean</code></em> ] [ recursive-only <em class="replaceable"><code>boolean</code></em> ];<br>
+ root-delegation-only [ exclude { <em class="replaceable"><code>quoted_string</code></em>; ... } ];<br>
+ root-key-sentinel <em class="replaceable"><code>boolean</code></em>;<br>
+ rrset-order { [ class <em class="replaceable"><code>string</code></em> ] [ type <em class="replaceable"><code>string</code></em> ] [ name<br>
+     <em class="replaceable"><code>quoted_string</code></em> ] <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>string</code></em>; ... };<br>
+ secroots-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ send-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ serial-query-rate <em class="replaceable"><code>integer</code></em>;<br>
+ serial-update-method ( date | increment | unixtime );<br>
+ server-id ( <em class="replaceable"><code>quoted_string</code></em> | none | hostname );<br>
+ servfail-ttl <em class="replaceable"><code>ttlval</code></em>;<br>
+ session-keyalg <em class="replaceable"><code>string</code></em>;<br>
+ session-keyfile ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ session-keyname <em class="replaceable"><code>string</code></em>;<br>
+ sig-signing-nodes <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-signatures <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-type <em class="replaceable"><code>integer</code></em>;<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em> [ <em class="replaceable"><code>integer</code></em> ];<br>
+ sortlist { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ stacksize ( default | unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ startup-notify-rate <em class="replaceable"><code>integer</code></em>;<br>
+ statistics-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ tcp-clients <em class="replaceable"><code>integer</code></em>;<br>
+ tcp-listen-queue <em class="replaceable"><code>integer</code></em>;<br>
+ tkey-dhkey <em class="replaceable"><code>quoted_string</code></em> <em class="replaceable"><code>integer</code></em>;<br>
+ tkey-domain <em class="replaceable"><code>quoted_string</code></em>;<br>
+ tkey-gssapi-credential <em class="replaceable"><code>quoted_string</code></em>;<br>
+ tkey-gssapi-keytab <em class="replaceable"><code>quoted_string</code></em>;<br>
+ transfer-format ( many-answers | one-answer );<br>
+ transfer-message-size <em class="replaceable"><code>integer</code></em>;<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfers-in <em class="replaceable"><code>integer</code></em>;<br>
+ transfers-out <em class="replaceable"><code>integer</code></em>;<br>
+ transfers-per-ns <em class="replaceable"><code>integer</code></em>;<br>
+ trust-anchor-telemetry <em class="replaceable"><code>boolean</code></em>; // experimental<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+ use-v4-udp-ports { <em class="replaceable"><code>portrange</code></em>; ... };<br>
+ use-v6-udp-ports { <em class="replaceable"><code>portrange</code></em>; ... };<br>
+ v6-bias <em class="replaceable"><code>integer</code></em>;<br>
+ version ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ zone-statistics ( full | terse | none | <em class="replaceable"><code>boolean</code></em> );<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.18"></a><h2>SERVER</h2>
+
+ <div class="literallayout"><p><br>
+server <em class="replaceable"><code>netprefix</code></em> {<br>
+ bogus <em class="replaceable"><code>boolean</code></em>;<br>
+ edns <em class="replaceable"><code>boolean</code></em>;<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ edns-version <em class="replaceable"><code>integer</code></em>;<br>
+ keys <em class="replaceable"><code>server_key</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ]<br>
+     [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ query-source ( ( [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) ]<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ query-source-v6 ( ( [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) ]<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ request-expire <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-nsid <em class="replaceable"><code>boolean</code></em>;<br>
+ send-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ tcp-only <em class="replaceable"><code>boolean</code></em>;<br>
+ transfer-format ( many-answers | one-answer );<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfers <em class="replaceable"><code>integer</code></em>;<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.19"></a><h2>STATISTICS-CHANNELS</h2>
+
+ <div class="literallayout"><p><br>
+statistics-channels {<br>
+ inet ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> |<br>
+     * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     allow { <em class="replaceable"><code>address_match_element</code></em>; ...<br>
+     } ];<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.20"></a><h2>TRUSTED-KEYS</h2>
+
+ <div class="literallayout"><p><br>
+trusted-keys { <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em><br>
+    <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>; ... };<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.21"></a><h2>VIEW</h2>
+
+ <div class="literallayout"><p><br>
+view <em class="replaceable"><code>string</code></em> [ <em class="replaceable"><code>class</code></em> ] {<br>
+ acache-cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ acache-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ additional-from-auth <em class="replaceable"><code>boolean</code></em>;<br>
+ additional-from-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ allow-new-zones <em class="replaceable"><code>boolean</code></em>;<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-recursion { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-recursion-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ also-notify [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> |<br>
+     <em class="replaceable"><code>ipv4_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ]; ... };<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> |<br>
+     * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ attach-cache <em class="replaceable"><code>string</code></em>;<br>
+ auth-nxdomain <em class="replaceable"><code>boolean</code></em>; // default changed<br>
+ auto-dnssec ( allow | maintain | off );<br>
+ cache-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ catalog-zones { zone <em class="replaceable"><code>quoted_string</code></em> [ default-masters [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<br>
+     port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] ) [ key<br>
+     <em class="replaceable"><code>string</code></em> ]; ... } ] [ zone-directory <em class="replaceable"><code>quoted_string</code></em> ] [<br>
+     in-memory <em class="replaceable"><code>boolean</code></em> ] [ min-update-interval <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ check-dup-records ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-names ( master | slave | response<br>
+     ) ( fail | warn | ignore );<br>
+ check-sibling <em class="replaceable"><code>boolean</code></em>;<br>
+ check-spf ( warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ check-wildcard <em class="replaceable"><code>boolean</code></em>;<br>
+ cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ clients-per-query <em class="replaceable"><code>integer</code></em>;<br>
+ deny-answer-addresses { <em class="replaceable"><code>address_match_element</code></em>; ... } [<br>
+     except-from { <em class="replaceable"><code>quoted_string</code></em>; ... } ];<br>
+ deny-answer-aliases { <em class="replaceable"><code>quoted_string</code></em>; ... } [ except-from {<br>
+     <em class="replaceable"><code>quoted_string</code></em>; ... } ];<br>
+ dialup ( notify | notify-passive | passive | refresh | <em class="replaceable"><code>boolean</code></em> );<br>
+ disable-algorithms <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>;<br>
+     ... };<br>
+ disable-ds-digests <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>;<br>
+     ... };<br>
+ disable-empty-zone <em class="replaceable"><code>string</code></em>;<br>
+ dlz <em class="replaceable"><code>string</code></em> {<br>
+ database <em class="replaceable"><code>string</code></em>;<br>
+ search <em class="replaceable"><code>boolean</code></em>;<br>
+ };<br>
+ dns64 <em class="replaceable"><code>netprefix</code></em> {<br>
+ break-dnssec <em class="replaceable"><code>boolean</code></em>;<br>
+ clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ exclude { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ mapped { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ recursive-only <em class="replaceable"><code>boolean</code></em>;<br>
+ suffix <em class="replaceable"><code>ipv6_address</code></em>;<br>
+ };<br>
+ dns64-contact <em class="replaceable"><code>string</code></em>;<br>
+ dns64-server <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-loadkeys-interval <em class="replaceable"><code>integer</code></em>;<br>
+ dnssec-lookaside ( <em class="replaceable"><code>string</code></em> trust-anchor<br>
+     <em class="replaceable"><code>string</code></em> | auto | no );<br>
+ dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-update-mode ( maintain | no-resign );<br>
+ dnssec-validation ( yes | no | auto );<br>
+ dnstap { ( all | auth | client | forwarder |<br>
+     resolver ) [ ( query | response ) ]; ... };<br>
+ dual-stack-servers [ port <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>quoted_string</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv4_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] ); ... };<br>
+ dyndb <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>quoted_string</code></em> {<br>
+     <em class="replaceable"><code>unspecified-text</code></em> };<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ empty-contact <em class="replaceable"><code>string</code></em>;<br>
+ empty-server <em class="replaceable"><code>string</code></em>;<br>
+ empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ fetch-quota-params <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>fixedpoint</code></em> <em class="replaceable"><code>fixedpoint</code></em> <em class="replaceable"><code>fixedpoint</code></em>;<br>
+ fetches-per-server <em class="replaceable"><code>integer</code></em> [ ( drop | fail ) ];<br>
+ fetches-per-zone <em class="replaceable"><code>integer</code></em> [ ( drop | fail ) ];<br>
+ filter-aaaa { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ filter-aaaa-on-v4 ( break-dnssec | <em class="replaceable"><code>boolean</code></em> );<br>
+ filter-aaaa-on-v6 ( break-dnssec | <em class="replaceable"><code>boolean</code></em> );<br>
+ forward ( first | only );<br>
+ forwarders [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>ipv4_address</code></em><br>
+     | <em class="replaceable"><code>ipv6_address</code></em> ) [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ inline-signing <em class="replaceable"><code>boolean</code></em>;<br>
+ ixfr-from-differences ( master | slave | <em class="replaceable"><code>boolean</code></em> );<br>
+ key <em class="replaceable"><code>string</code></em> {<br>
+ algorithm <em class="replaceable"><code>string</code></em>;<br>
+ secret <em class="replaceable"><code>string</code></em>;<br>
+ };<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ lame-ttl <em class="replaceable"><code>ttlval</code></em>;<br>
+ lmdb-mapsize <em class="replaceable"><code>sizeval</code></em>;<br>
+ managed-keys { <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>string</code></em><br>
+     <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em><br>
+     <em class="replaceable"><code>quoted_string</code></em>; ... };<br>
+ masterfile-format ( map | raw | text );<br>
+ masterfile-style ( full | relative );<br>
+ match-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ match-destinations { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ match-recursive-only <em class="replaceable"><code>boolean</code></em>;<br>
+ max-acache-size ( unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ max-cache-size ( default | unlimited | <em class="replaceable"><code>sizeval</code></em> | <em class="replaceable"><code>percentage</code></em> );<br>
+ max-cache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-clients-per-query <em class="replaceable"><code>integer</code></em>;<br>
+ max-journal-size ( unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-records <em class="replaceable"><code>integer</code></em>;<br>
+ max-recursion-depth <em class="replaceable"><code>integer</code></em>;<br>
+ max-recursion-queries <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ max-zone-ttl ( unlimited | <em class="replaceable"><code>ttlval</code></em> );<br>
+ message-compression <em class="replaceable"><code>boolean</code></em>;<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ minimal-any <em class="replaceable"><code>boolean</code></em>;<br>
+ minimal-responses ( no-auth | no-auth-recursive | <em class="replaceable"><code>boolean</code></em> );<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+ no-case-compress { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ nocookie-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ notify ( explicit | master-only | <em class="replaceable"><code>boolean</code></em> );<br>
+ notify-delay <em class="replaceable"><code>integer</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ]<br>
+     [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ nta-lifetime <em class="replaceable"><code>ttlval</code></em>;<br>
+ nta-recheck <em class="replaceable"><code>ttlval</code></em>;<br>
+ nxdomain-redirect <em class="replaceable"><code>string</code></em>;<br>
+ preferred-glue <em class="replaceable"><code>string</code></em>;<br>
+ prefetch <em class="replaceable"><code>integer</code></em> [ <em class="replaceable"><code>integer</code></em> ];<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ query-source ( ( [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) ]<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ query-source-v6 ( ( [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) ]<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ rate-limit {<br>
+ all-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ errors-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ exempt-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ ipv4-prefix-length <em class="replaceable"><code>integer</code></em>;<br>
+ ipv6-prefix-length <em class="replaceable"><code>integer</code></em>;<br>
+ log-only <em class="replaceable"><code>boolean</code></em>;<br>
+ max-table-size <em class="replaceable"><code>integer</code></em>;<br>
+ min-table-size <em class="replaceable"><code>integer</code></em>;<br>
+ nodata-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ nxdomains-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ qps-scale <em class="replaceable"><code>integer</code></em>;<br>
+ referrals-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ responses-per-second <em class="replaceable"><code>integer</code></em>;<br>
+ slip <em class="replaceable"><code>integer</code></em>;<br>
+ window <em class="replaceable"><code>integer</code></em>;<br>
+ };<br>
+ recursion <em class="replaceable"><code>boolean</code></em>;<br>
+ request-expire <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-nsid <em class="replaceable"><code>boolean</code></em>;<br>
+ require-server-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ resolver-query-timeout <em class="replaceable"><code>integer</code></em>;<br>
+ response-policy { zone <em class="replaceable"><code>quoted_string</code></em> [ log <em class="replaceable"><code>boolean</code></em> ] [<br>
+     max-policy-ttl <em class="replaceable"><code>integer</code></em> ] [ policy ( cname | disabled | drop |<br>
+     given | no-op | nodata | nxdomain | passthru | tcp-only<br>
+     <em class="replaceable"><code>quoted_string</code></em> ) ] [ recursive-only <em class="replaceable"><code>boolean</code></em> ]; ... } [<br>
+     break-dnssec <em class="replaceable"><code>boolean</code></em> ] [ max-policy-ttl <em class="replaceable"><code>integer</code></em> ] [<br>
+     min-ns-dots <em class="replaceable"><code>integer</code></em> ] [ nsip-wait-recurse <em class="replaceable"><code>boolean</code></em> ] [<br>
+     qname-wait-recurse <em class="replaceable"><code>boolean</code></em> ] [ recursive-only <em class="replaceable"><code>boolean</code></em> ];<br>
+ root-delegation-only [ exclude { <em class="replaceable"><code>quoted_string</code></em>; ... } ];<br>
+ root-key-sentinel <em class="replaceable"><code>boolean</code></em>;<br>
+ rrset-order { [ class <em class="replaceable"><code>string</code></em> ] [ type <em class="replaceable"><code>string</code></em> ] [ name<br>
+     <em class="replaceable"><code>quoted_string</code></em> ] <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>string</code></em>; ... };<br>
+ send-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ serial-update-method ( date | increment | unixtime );<br>
+ server <em class="replaceable"><code>netprefix</code></em> {<br>
+ bogus <em class="replaceable"><code>boolean</code></em>;<br>
+ edns <em class="replaceable"><code>boolean</code></em>;<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ edns-version <em class="replaceable"><code>integer</code></em>;<br>
+ keys <em class="replaceable"><code>server_key</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | *<br>
+     ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em><br>
+     | * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ query-source ( ( [ address ] ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port<br>
+     ( <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] (<br>
+     <em class="replaceable"><code>ipv4_address</code></em> | * ) ] port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ query-source-v6 ( ( [ address ] ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [<br>
+     port ( <em class="replaceable"><code>integer</code></em> | * ) ] ) | ( [ [ address ] (<br>
+     <em class="replaceable"><code>ipv6_address</code></em> | * ) ] port ( <em class="replaceable"><code>integer</code></em> | * ) ) ) [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ request-expire <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-nsid <em class="replaceable"><code>boolean</code></em>;<br>
+ send-cookie <em class="replaceable"><code>boolean</code></em>;<br>
+ tcp-only <em class="replaceable"><code>boolean</code></em>;<br>
+ transfer-format ( many-answers | one-answer );<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> |<br>
+     * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfers <em class="replaceable"><code>integer</code></em>;<br>
+ };<br>
+ servfail-ttl <em class="replaceable"><code>ttlval</code></em>;<br>
+ sig-signing-nodes <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-signatures <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-type <em class="replaceable"><code>integer</code></em>;<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em> [ <em class="replaceable"><code>integer</code></em> ];<br>
+ sortlist { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ transfer-format ( many-answers | one-answer );<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ trust-anchor-telemetry <em class="replaceable"><code>boolean</code></em>; // experimental<br>
+ trusted-keys { <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em><br>
+     <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>;<br>
+     ... };<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+ v6-bias <em class="replaceable"><code>integer</code></em>;<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ zone <em class="replaceable"><code>string</code></em> [ <em class="replaceable"><code>class</code></em> ] {<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ also-notify [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { (<br>
+     <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] |<br>
+     <em class="replaceable"><code>ipv6_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ];<br>
+     ... };<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ auto-dnssec ( allow | maintain | off );<br>
+ check-dup-records ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-names ( fail | warn | ignore );<br>
+ check-sibling <em class="replaceable"><code>boolean</code></em>;<br>
+ check-spf ( warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ check-wildcard <em class="replaceable"><code>boolean</code></em>;<br>
+ database <em class="replaceable"><code>string</code></em>;<br>
+ delegation-only <em class="replaceable"><code>boolean</code></em>;<br>
+ dialup ( notify | notify-passive | passive | refresh |<br>
+     <em class="replaceable"><code>boolean</code></em> );<br>
+ dlz <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-loadkeys-interval <em class="replaceable"><code>integer</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-update-mode ( maintain | no-resign );<br>
+ file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ forward ( first | only );<br>
+ forwarders [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { (<br>
+     <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [ port <em class="replaceable"><code>integer</code></em> ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ in-view <em class="replaceable"><code>string</code></em>;<br>
+ inline-signing <em class="replaceable"><code>boolean</code></em>;<br>
+ ixfr-from-differences <em class="replaceable"><code>boolean</code></em>;<br>
+ journal <em class="replaceable"><code>quoted_string</code></em>;<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ masterfile-format ( map | raw | text );<br>
+ masterfile-style ( full | relative );<br>
+ masters [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em><br>
+     | <em class="replaceable"><code>ipv4_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [<br>
+     port <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ]; ... };<br>
+ max-ixfr-log-size ( default | unlimited |<br>
+ max-journal-size ( unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ max-records <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-zone-ttl ( unlimited | <em class="replaceable"><code>ttlval</code></em> );<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+ notify ( explicit | master-only | <em class="replaceable"><code>boolean</code></em> );<br>
+ notify-delay <em class="replaceable"><code>integer</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | *<br>
+     ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em><br>
+     | * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ pubkey <em class="replaceable"><code>integer</code></em><br>
+     <em class="replaceable"><code>integer</code></em><br>
+     <em class="replaceable"><code>integer</code></em><br>
+ request-expire <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ serial-update-method ( date | increment | unixtime );<br>
+ server-addresses { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [<br>
+     port <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ server-names { <em class="replaceable"><code>quoted_string</code></em>; ... };<br>
+ sig-signing-nodes <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-signatures <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-type <em class="replaceable"><code>integer</code></em>;<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em> [ <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> |<br>
+     * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port (<br>
+     <em class="replaceable"><code>integer</code></em> | * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ type ( delegation-only | forward | hint | master | redirect<br>
+     | slave | static-stub | stub );<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ update-policy ( local | { ( deny | grant ) <em class="replaceable"><code>string</code></em> (<br>
+     6to4-self | external | krb5-self | krb5-selfsub |<br>
+     krb5-subdomain | ms-self | ms-selfsub | ms-subdomain |<br>
+     name | self | selfsub | selfwild | subdomain | tcp-self<br>
+     | wildcard | zonesub ) [ <em class="replaceable"><code>string</code></em> ] <em class="replaceable"><code>rrtypelist</code></em>; ... };<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ zone-statistics ( full | terse | none | <em class="replaceable"><code>boolean</code></em> );<br>
+ };<br>
+ zone-statistics ( full | terse | none | <em class="replaceable"><code>boolean</code></em> );<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.22"></a><h2>ZONE</h2>
+
+ <div class="literallayout"><p><br>
+zone <em class="replaceable"><code>string</code></em> [ <em class="replaceable"><code>class</code></em> ] {<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ also-notify [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> |<br>
+     <em class="replaceable"><code>ipv4_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ]; ... };<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> |<br>
+     * ) ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ auto-dnssec ( allow | maintain | off );<br>
+ check-dup-records ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-names ( fail | warn | ignore );<br>
+ check-sibling <em class="replaceable"><code>boolean</code></em>;<br>
+ check-spf ( warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ check-wildcard <em class="replaceable"><code>boolean</code></em>;<br>
+ database <em class="replaceable"><code>string</code></em>;<br>
+ delegation-only <em class="replaceable"><code>boolean</code></em>;<br>
+ dialup ( notify | notify-passive | passive | refresh | <em class="replaceable"><code>boolean</code></em> );<br>
+ dlz <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-loadkeys-interval <em class="replaceable"><code>integer</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-update-mode ( maintain | no-resign );<br>
+ file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ forward ( first | only );<br>
+ forwarders [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>ipv4_address</code></em><br>
+     | <em class="replaceable"><code>ipv6_address</code></em> ) [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ in-view <em class="replaceable"><code>string</code></em>;<br>
+ inline-signing <em class="replaceable"><code>boolean</code></em>;<br>
+ ixfr-from-differences <em class="replaceable"><code>boolean</code></em>;<br>
+ journal <em class="replaceable"><code>quoted_string</code></em>;<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ masterfile-format ( map | raw | text );<br>
+ masterfile-style ( full | relative );<br>
+ masters [ port <em class="replaceable"><code>integer</code></em> ] [ dscp <em class="replaceable"><code>integer</code></em> ] { ( <em class="replaceable"><code>masters</code></em> |<br>
+     <em class="replaceable"><code>ipv4_address</code></em> [ port <em class="replaceable"><code>integer</code></em> ] | <em class="replaceable"><code>ipv6_address</code></em> [ port<br>
+     <em class="replaceable"><code>integer</code></em> ] ) [ key <em class="replaceable"><code>string</code></em> ]; ... };<br>
+ max-journal-size ( unlimited | <em class="replaceable"><code>sizeval</code></em> );<br>
+ max-records <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-zone-ttl ( unlimited | <em class="replaceable"><code>ttlval</code></em> );<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+ notify ( explicit | master-only | <em class="replaceable"><code>boolean</code></em> );<br>
+ notify-delay <em class="replaceable"><code>integer</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ]<br>
+     [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ pubkey <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em><br>
+ request-expire <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ serial-update-method ( date | increment | unixtime );<br>
+ server-addresses { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [ port<br>
+     <em class="replaceable"><code>integer</code></em> ]; ... };<br>
+ server-names { <em class="replaceable"><code>quoted_string</code></em>; ... };<br>
+ sig-signing-nodes <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-signatures <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-type <em class="replaceable"><code>integer</code></em>;<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em> [ <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * ) ] [<br>
+     dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [ port ( <em class="replaceable"><code>integer</code></em> | * )<br>
+     ] [ dscp <em class="replaceable"><code>integer</code></em> ];<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ type ( delegation-only | forward | hint | master | redirect | slave<br>
+     | static-stub | stub );<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ update-policy ( local | { ( deny | grant ) <em class="replaceable"><code>string</code></em> ( 6to4-self |<br>
+     external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self<br>
+     | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild<br>
+     | subdomain | tcp-self | wildcard | zonesub ) [ <em class="replaceable"><code>string</code></em> ]<br>
+     <em class="replaceable"><code>rrtypelist</code></em>; ... };<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ zone-statistics ( full | terse | none | <em class="replaceable"><code>boolean</code></em> );<br>
+};<br>
+</p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.23"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/named.conf</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.24"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">ddns-confgen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named-checkconf</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc-confgen</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/named/named.docbook b/bin/named/named.docbook
new file mode 100644
index 0000000..c869369
--- /dev/null
+++ b/bin/named/named.docbook
@@ -0,0 +1,547 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named">
+ <info>
+ <date>2014-02-19</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>named</application></refname>
+ <refpurpose>Internet domain name server</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2011</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>named</command>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">string</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-E <replaceable class="parameter">engine-name</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-g</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">logfile</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-M <replaceable class="parameter">option</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">#cpus</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S <replaceable class="parameter">#max-socks</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-U <replaceable class="parameter">#listeners</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-u <replaceable class="parameter">user</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-X <replaceable class="parameter">lock-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x <replaceable class="parameter">cache-file</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>named</command>
+ is a Domain Name System (DNS) server,
+ part of the BIND 9 distribution from ISC. For more
+ information on the DNS, see RFCs 1033, 1034, and 1035.
+ </para>
+ <para>
+ When invoked without arguments, <command>named</command>
+ will
+ read the default configuration file
+ <filename>/etc/named.conf</filename>, read any initial
+ data, and listen for queries.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable> as the
+ configuration file instead of the default,
+ <filename>/etc/named.conf</filename>. To
+ ensure that reloading the configuration file continues
+ to work after the server has changed its working
+ directory due to to a possible
+ <option>directory</option> option in the configuration
+ file, <replaceable class="parameter">config-file</replaceable> should be
+ an absolute pathname.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">debug-level</replaceable></term>
+ <listitem>
+ <para>
+ Set the daemon's debug level to <replaceable class="parameter">debug-level</replaceable>.
+ Debugging traces from <command>named</command> become
+ more verbose as the debug level increases.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">string</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a string that is used to identify a instance of
+ <command>named</command> in a process listing. The contents
+ of <replaceable class="parameter">string</replaceable> are
+ not examined.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-E <replaceable class="parameter">engine-name</replaceable></term>
+ <listitem>
+ <para>
+ When applicable, specifies the hardware to use for
+ cryptographic operations, such as a secure key store used
+ for signing.
+ </para>
+ <para>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Run the server in the foreground (i.e. do not daemonize).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Run the server in the foreground and force all logging
+ to <filename>stderr</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">logfile</replaceable></term>
+ <listitem>
+ <para>
+ Log to the file <option>logfile</option> by default
+ instead of the system log.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-M <replaceable class="parameter">option</replaceable></term>
+ <listitem>
+ <para>
+ Sets the default memory context options. Currently
+ the only supported option is
+ <replaceable class="parameter">external</replaceable>,
+ which causes the internal memory manager to be bypassed
+ in favor of system-provided memory allocation functions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Turn on memory usage debugging flags. Possible flags are
+ <replaceable class="parameter">usage</replaceable>,
+ <replaceable class="parameter">trace</replaceable>,
+ <replaceable class="parameter">record</replaceable>,
+ <replaceable class="parameter">size</replaceable>, and
+ <replaceable class="parameter">mctx</replaceable>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <filename>&lt;isc/mem.h&gt;</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">#cpus</replaceable></term>
+ <listitem>
+ <para>
+ Create <replaceable class="parameter">#cpus</replaceable> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <command>named</command> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Listen for queries on port <replaceable class="parameter">port</replaceable>. If not
+ specified, the default is port 53.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Write memory usage statistics to <filename>stdout</filename> on exit.
+ </para>
+ <note>
+ <para>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">#max-socks</replaceable></term>
+ <listitem>
+ <para>
+ Allow <command>named</command> to use up to
+ <replaceable class="parameter">#max-socks</replaceable> sockets.
+ The default value is 4096 on systems built with default
+ configuration options, and 21000 on systems built with
+ "configure --with-tuning=large".
+ </para>
+ <warning>
+ <para>
+ 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 a little
+ fewer than the specified value because
+ <command>named</command> reserves some file descriptors
+ for its internal use.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>Chroot
+ to <replaceable class="parameter">directory</replaceable> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </para>
+ <warning>
+ <para>
+ This option should be used in conjunction with the
+ <option>-u</option> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <function>chroot(2)</function> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-U <replaceable class="parameter">#listeners</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">#listeners</replaceable>
+ worker threads to listen for incoming UDP packets on each
+ address. If not specified, <command>named</command> will
+ calculate 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</option> has been set to a higher value than
+ the number of detected CPUs, then <option>-U</option> may
+ be increased as high as that value, but no higher.
+ On Windows, the number of UDP listeners is hardwired to 1
+ and this option has no effect.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">user</replaceable></term>
+ <listitem>
+ <para>Setuid
+ to <replaceable class="parameter">user</replaceable> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </para>
+ <note>
+ <para>
+ On Linux, <command>named</command> uses the kernel's
+ capability mechanism to drop all root privileges
+ except the ability to <function>bind(2)</function> to
+ a
+ privileged port and set process resource limits.
+ Unfortunately, this means that the <option>-u</option>
+ option only works when <command>named</command> 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 <function>setuid(2)</function>.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Report the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Report the version number and build options, and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-X <replaceable class="parameter">lock-file</replaceable></term>
+ <listitem>
+ <para>
+ Acquire a lock on the specified file at runtime; this
+ helps to prevent duplicate <command>named</command> instances
+ from running simultaneously.
+ Use of this option overrides the <command>lock-file</command>
+ option in <filename>named.conf</filename>.
+ If set to <literal>none</literal>, the lock file check
+ is disabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x <replaceable class="parameter">cache-file</replaceable></term>
+ <listitem>
+ <para>
+ Load data from <replaceable class="parameter">cache-file</replaceable> into the
+ cache of the default view.
+ </para>
+ <warning>
+ <para>
+ This option must not be used. It is only of interest
+ to BIND 9 developers and may be removed or changed in a
+ future release.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>SIGNALS</title></info>
+
+ <para>
+ In routine operation, signals should not be used to control
+ the nameserver; <command>rndc</command> should be used
+ instead.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>SIGHUP</term>
+ <listitem>
+ <para>
+ Force a reload of the server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>SIGINT, SIGTERM</term>
+ <listitem>
+ <para>
+ Shut down the server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+ The result of sending any other signals to the server is undefined.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>CONFIGURATION</title></info>
+
+ <para>
+ The <command>named</command> configuration file is too complex
+ to describe in detail here. A complete description is provided
+ in the
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+
+ <para>
+ <command>named</command> inherits the <function>umask</function>
+ (file creation mode mask) from the parent process. If files
+ created by <command>named</command>, such as journal files,
+ need to have custom permissions, the <function>umask</function>
+ should be set explicitly in the script used to start the
+ <command>named</command> process.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+
+ <variablelist>
+
+ <varlistentry>
+ <term><filename>/etc/named.conf</filename></term>
+ <listitem>
+ <para>
+ The default configuration file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/var/run/named/named.pid</filename></term>
+ <listitem>
+ <para>
+ The default process-id file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citetitle>RFC 1033</citetitle>,
+ <citetitle>RFC 1034</citetitle>,
+ <citetitle>RFC 1035</citetitle>,
+ <citerefentry>
+ <refentrytitle>named-checkconf</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkzone</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwresd</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/named/named.html b/bin/named/named.html
new file mode 100644
index 0000000..b912196
--- /dev/null
+++ b/bin/named/named.html
@@ -0,0 +1,456 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000, 2001, 2003-2009, 2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">named</span>
+ &#8212; Internet domain name server
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named</code>
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>string</code></em></code>]
+ [<code class="option">-E <em class="replaceable"><code>engine-name</code></em></code>]
+ [<code class="option">-f</code>]
+ [<code class="option">-g</code>]
+ [<code class="option">-L <em class="replaceable"><code>logfile</code></em></code>]
+ [<code class="option">-M <em class="replaceable"><code>option</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>]
+ [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>port</code></em></code>]
+ [<code class="option">-s</code>]
+ [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-U <em class="replaceable"><code>#listeners</code></em></code>]
+ [<code class="option">-u <em class="replaceable"><code>user</code></em></code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-X <em class="replaceable"><code>lock-file</code></em></code>]
+ [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>named</strong></span>
+ is a Domain Name System (DNS) server,
+ part of the BIND 9 distribution from ISC. For more
+ information on the DNS, see RFCs 1033, 1034, and 1035.
+ </p>
+ <p>
+ When invoked without arguments, <span class="command"><strong>named</strong></span>
+ will
+ read the default configuration file
+ <code class="filename">/etc/named.conf</code>, read any initial
+ data, and listen for queries.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/named.conf</code>. To
+ ensure that reloading the configuration file continues
+ to work after the server has changed its working
+ directory due to to a possible
+ <code class="option">directory</code> option in the configuration
+ file, <em class="replaceable"><code>config-file</code></em> should be
+ an absolute pathname.
+ </p>
+ </dd>
+<dt><span class="term">-d <em class="replaceable"><code>debug-level</code></em></span></dt>
+<dd>
+ <p>
+ Set the daemon's debug level to <em class="replaceable"><code>debug-level</code></em>.
+ Debugging traces from <span class="command"><strong>named</strong></span> become
+ more verbose as the debug level increases.
+ </p>
+ </dd>
+<dt><span class="term">-D <em class="replaceable"><code>string</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a string that is used to identify a instance of
+ <span class="command"><strong>named</strong></span> in a process listing. The contents
+ of <em class="replaceable"><code>string</code></em> are
+ not examined.
+ </p>
+ </dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine-name</code></em></span></dt>
+<dd>
+ <p>
+ When applicable, specifies the hardware to use for
+ cryptographic operations, such as a secure key store used
+ for signing.
+ </p>
+ <p>
+ When BIND is built with OpenSSL PKCS#11 support, this defaults
+ to the string "pkcs11", which identifies an OpenSSL engine
+ that can drive a cryptographic accelerator or hardware service
+ module. When BIND is built with native PKCS#11 cryptography
+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
+ provider library specified via "--with-pkcs11".
+ </p>
+ </dd>
+<dt><span class="term">-f</span></dt>
+<dd>
+ <p>
+ Run the server in the foreground (i.e. do not daemonize).
+ </p>
+ </dd>
+<dt><span class="term">-g</span></dt>
+<dd>
+ <p>
+ Run the server in the foreground and force all logging
+ to <code class="filename">stderr</code>.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>logfile</code></em></span></dt>
+<dd>
+ <p>
+ Log to the file <code class="option">logfile</code> by default
+ instead of the system log.
+ </p>
+ </dd>
+<dt><span class="term">-M <em class="replaceable"><code>option</code></em></span></dt>
+<dd>
+ <p>
+ Sets the default memory context options. Currently
+ the only supported option is
+ <em class="replaceable"><code>external</code></em>,
+ which causes the internal memory manager to be bypassed
+ in favor of system-provided memory allocation functions.
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd>
+ <p>
+ Turn on memory usage debugging flags. Possible flags are
+ <em class="replaceable"><code>usage</code></em>,
+ <em class="replaceable"><code>trace</code></em>,
+ <em class="replaceable"><code>record</code></em>,
+ <em class="replaceable"><code>size</code></em>, and
+ <em class="replaceable"><code>mctx</code></em>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <code class="filename">&lt;isc/mem.h&gt;</code>.
+ </p>
+ </dd>
+<dt><span class="term">-n <em class="replaceable"><code>#cpus</code></em></span></dt>
+<dd>
+ <p>
+ Create <em class="replaceable"><code>#cpus</code></em> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <span class="command"><strong>named</strong></span> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Listen for queries on port <em class="replaceable"><code>port</code></em>. If not
+ specified, the default is port 53.
+ </p>
+ </dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+ <p>
+ Write memory usage statistics to <code class="filename">stdout</code> on exit.
+ </p>
+ <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ <p>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </p>
+ </div>
+ </dd>
+<dt><span class="term">-S <em class="replaceable"><code>#max-socks</code></em></span></dt>
+<dd>
+ <p>
+ Allow <span class="command"><strong>named</strong></span> to use up to
+ <em class="replaceable"><code>#max-socks</code></em> sockets.
+ The default value is 4096 on systems built with default
+ configuration options, and 21000 on systems built with
+ "configure --with-tuning=large".
+ </p>
+ <div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+ <p>
+ 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 a little
+ fewer than the specified value because
+ <span class="command"><strong>named</strong></span> reserves some file descriptors
+ for its internal use.
+ </p>
+ </div>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>Chroot
+ to <em class="replaceable"><code>directory</code></em> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </p>
+ <div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+ <p>
+ This option should be used in conjunction with the
+ <code class="option">-u</code> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <code class="function">chroot(2)</code> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </p>
+ </div>
+ </dd>
+<dt><span class="term">-U <em class="replaceable"><code>#listeners</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>#listeners</code></em>
+ worker threads to listen for incoming UDP packets on each
+ address. If not specified, <span class="command"><strong>named</strong></span> will
+ calculate 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 <code class="option">-n</code> has been set to a higher value than
+ the number of detected CPUs, then <code class="option">-U</code> may
+ be increased as high as that value, but no higher.
+ On Windows, the number of UDP listeners is hardwired to 1
+ and this option has no effect.
+ </p>
+ </dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd>
+ <p>Setuid
+ to <em class="replaceable"><code>user</code></em> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </p>
+ <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ <p>
+ On Linux, <span class="command"><strong>named</strong></span> uses the kernel's
+ capability mechanism to drop all root privileges
+ except the ability to <code class="function">bind(2)</code> to
+ a
+ privileged port and set process resource limits.
+ Unfortunately, this means that the <code class="option">-u</code>
+ option only works when <span class="command"><strong>named</strong></span> 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 <code class="function">setuid(2)</code>.
+ </p>
+ </div>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Report the version number and exit.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Report the version number and build options, and exit.
+ </p>
+ </dd>
+<dt><span class="term">-X <em class="replaceable"><code>lock-file</code></em></span></dt>
+<dd>
+ <p>
+ Acquire a lock on the specified file at runtime; this
+ helps to prevent duplicate <span class="command"><strong>named</strong></span> instances
+ from running simultaneously.
+ Use of this option overrides the <span class="command"><strong>lock-file</strong></span>
+ option in <code class="filename">named.conf</code>.
+ If set to <code class="literal">none</code>, the lock file check
+ is disabled.
+ </p>
+ </dd>
+<dt><span class="term">-x <em class="replaceable"><code>cache-file</code></em></span></dt>
+<dd>
+ <p>
+ Load data from <em class="replaceable"><code>cache-file</code></em> into the
+ cache of the default view.
+ </p>
+ <div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+ <p>
+ This option must not be used. It is only of interest
+ to BIND 9 developers and may be removed or changed in a
+ future release.
+ </p>
+ </div>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SIGNALS</h2>
+
+ <p>
+ In routine operation, signals should not be used to control
+ the nameserver; <span class="command"><strong>rndc</strong></span> should be used
+ instead.
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">SIGHUP</span></dt>
+<dd>
+ <p>
+ Force a reload of the server.
+ </p>
+ </dd>
+<dt><span class="term">SIGINT, SIGTERM</span></dt>
+<dd>
+ <p>
+ Shut down the server.
+ </p>
+ </dd>
+</dl></div>
+
+ <p>
+ The result of sending any other signals to the server is undefined.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>CONFIGURATION</h2>
+
+ <p>
+ The <span class="command"><strong>named</strong></span> configuration file is too complex
+ to describe in detail here. A complete description is provided
+ in the
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+
+ <p>
+ <span class="command"><strong>named</strong></span> inherits the <code class="function">umask</code>
+ (file creation mode mask) from the parent process. If files
+ created by <span class="command"><strong>named</strong></span>, such as journal files,
+ need to have custom permissions, the <code class="function">umask</code>
+ should be set explicitly in the script used to start the
+ <span class="command"><strong>named</strong></span> process.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>FILES</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="filename">/etc/named.conf</code></span></dt>
+<dd>
+ <p>
+ The default configuration file.
+ </p>
+ </dd>
+<dt><span class="term"><code class="filename">/var/run/named/named.pid</code></span></dt>
+<dd>
+ <p>
+ The default process-id file.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p><em class="citetitle">RFC 1033</em>,
+ <em class="citetitle">RFC 1034</em>,
+ <em class="citetitle">RFC 1035</em>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named-checkconf</span>
+ (8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named-checkzone</span>
+ (8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc</span>
+ (8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">lwresd</span>
+ (8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named.conf</span>
+ (5)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/named/notify.c b/bin/named/notify.c
new file mode 100644
index 0000000..0ad5abc
--- /dev/null
+++ b/bin/named/notify.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: notify.c,v 1.37 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/log.h>
+#include <isc/print.h>
+
+#include <dns/message.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/log.h>
+#include <named/notify.h>
+
+/*! \file
+ * \brief
+ * This module implements notify as in RFC1996.
+ */
+
+static void
+notify_log(ns_client_t *client, int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ ns_client_logv(client, DNS_LOGCATEGORY_NOTIFY, NS_LOGMODULE_NOTIFY,
+ level, fmt, ap);
+ va_end(ap);
+}
+
+static void
+respond(ns_client_t *client, isc_result_t result) {
+ dns_rcode_t rcode;
+ dns_message_t *message;
+ isc_result_t msg_result;
+
+ message = client->message;
+ rcode = dns_result_torcode(result);
+
+ msg_result = dns_message_reply(message, true);
+ if (msg_result != ISC_R_SUCCESS)
+ msg_result = dns_message_reply(message, false);
+ if (msg_result != ISC_R_SUCCESS) {
+ ns_client_next(client, msg_result);
+ return;
+ }
+ message->rcode = rcode;
+ if (rcode == dns_rcode_noerror)
+ message->flags |= DNS_MESSAGEFLAG_AA;
+ else
+ message->flags &= ~DNS_MESSAGEFLAG_AA;
+ ns_client_send(client);
+}
+
+void
+ns_notify_start(ns_client_t *client) {
+ dns_message_t *request = client->message;
+ isc_result_t result;
+ dns_name_t *zonename;
+ dns_rdataset_t *zone_rdataset;
+ dns_zone_t *zone = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char tsigbuf[DNS_NAME_FORMATSIZE * 2 + sizeof(": TSIG '' ()")];
+ dns_tsigkey_t *tsigkey;
+
+ /*
+ * Interpret the question section.
+ */
+ result = dns_message_firstname(request, DNS_SECTION_QUESTION);
+ if (result != ISC_R_SUCCESS) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section empty");
+ result = DNS_R_FORMERR;
+ goto done;
+ }
+
+ /*
+ * The question section must contain exactly one question.
+ */
+ zonename = NULL;
+ dns_message_currentname(request, DNS_SECTION_QUESTION, &zonename);
+ zone_rdataset = ISC_LIST_HEAD(zonename->list);
+ if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section contains multiple RRs");
+ result = DNS_R_FORMERR;
+ goto done;
+ }
+
+ /* The zone section must have exactly one name. */
+ result = dns_message_nextname(request, DNS_SECTION_ZONE);
+ if (result != ISC_R_NOMORE) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section contains multiple RRs");
+ result = DNS_R_FORMERR;
+ goto done;
+ }
+
+ /* The one rdataset must be an SOA. */
+ if (zone_rdataset->type != dns_rdatatype_soa) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section contains no SOA");
+ result = DNS_R_FORMERR;
+ goto done;
+ }
+
+ tsigkey = dns_message_gettsigkey(request);
+ if (tsigkey != NULL) {
+ dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf));
+
+ if (tsigkey->generated) {
+ char cnamebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(tsigkey->creator, cnamebuf,
+ sizeof(cnamebuf));
+ snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)",
+ namebuf, cnamebuf);
+ } else {
+ snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'",
+ namebuf);
+ }
+ } else
+ tsigbuf[0] = '\0';
+
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, &zone);
+ if (result == ISC_R_SUCCESS) {
+ dns_zonetype_t zonetype = dns_zone_gettype(zone);
+
+ if ((zonetype == dns_zone_master) ||
+ (zonetype == dns_zone_slave) ||
+ (zonetype == dns_zone_stub))
+ {
+ isc_sockaddr_t *from = ns_client_getsockaddr(client);
+ isc_sockaddr_t *to = ns_client_getdestaddr(client);
+ notify_log(client, ISC_LOG_INFO,
+ "received notify for zone '%s'%s",
+ namebuf, tsigbuf);
+ result = dns_zone_notifyreceive2(zone, from, to,
+ request);
+ goto done;
+ }
+ }
+
+ notify_log(client, ISC_LOG_NOTICE,
+ "received notify for zone '%s'%s: not authoritative",
+ namebuf, tsigbuf);
+ result = DNS_R_NOTAUTH;
+
+ done:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ respond(client, result);
+}
diff --git a/bin/named/query.c b/bin/named/query.c
new file mode 100644
index 0000000..f8dbef2
--- /dev/null
+++ b/bin/named/query.c
@@ -0,0 +1,9615 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <isc/hex.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/rwlock.h>
+#include <isc/serial.h>
+#include <isc/stats.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/badcache.h>
+#include <dns/byaddr.h>
+#include <dns/cache.h>
+#include <dns/db.h>
+#include <dns/dlz.h>
+#include <dns/dns64.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/keytable.h>
+#include <dns/message.h>
+#include <dns/ncache.h>
+#include <dns/nsec3.h>
+#include <dns/order.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/resolver.h>
+#include <dns/result.h>
+#include <dns/stats.h>
+#include <dns/tkey.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/client.h>
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/sortlist.h>
+#include <named/xfrout.h>
+
+#if 0
+/*
+ * It has been recommended that DNS64 be changed to return excluded
+ * AAAA addresses if DNS64 synthesis does not occur. This minimises
+ * the impact on the lookup results. While most DNS AAAA lookups are
+ * done to send IP packets to a host, not all of them are and filtering
+ * excluded addresses has a negative impact on those uses.
+ */
+#define dns64_bis_return_excluded_addresses 1
+#endif
+
+/*% Partial answer? */
+#define PARTIALANSWER(c) (((c)->query.attributes & \
+ NS_QUERYATTR_PARTIALANSWER) != 0)
+/*% Use Cache? */
+#define USECACHE(c) (((c)->query.attributes & \
+ NS_QUERYATTR_CACHEOK) != 0)
+/*% Recursion OK? */
+#define RECURSIONOK(c) (((c)->query.attributes & \
+ NS_QUERYATTR_RECURSIONOK) != 0)
+/*% Recursing? */
+#define RECURSING(c) (((c)->query.attributes & \
+ NS_QUERYATTR_RECURSING) != 0)
+/*% Cache glue ok? */
+#define CACHEGLUEOK(c) (((c)->query.attributes & \
+ NS_QUERYATTR_CACHEGLUEOK) != 0)
+/*% Want Recursion? */
+#define WANTRECURSION(c) (((c)->query.attributes & \
+ NS_QUERYATTR_WANTRECURSION) != 0)
+/*% Is TCP? */
+#define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
+
+/*% Want DNSSEC? */
+#define WANTDNSSEC(c) (((c)->attributes & \
+ NS_CLIENTATTR_WANTDNSSEC) != 0)
+/*% Want WANTAD? */
+#define WANTAD(c) (((c)->attributes & \
+ NS_CLIENTATTR_WANTAD) != 0)
+/*% Client presented a valid COOKIE. */
+#define HAVECOOKIE(c) (((c)->attributes & \
+ NS_CLIENTATTR_HAVECOOKIE) != 0)
+/*% Client presented a COOKIE. */
+#define WANTCOOKIE(c) (((c)->attributes & \
+ NS_CLIENTATTR_WANTCOOKIE) != 0)
+/*% No authority? */
+#define NOAUTHORITY(c) (((c)->query.attributes & \
+ NS_QUERYATTR_NOAUTHORITY) != 0)
+/*% No additional? */
+#define NOADDITIONAL(c) (((c)->query.attributes & \
+ NS_QUERYATTR_NOADDITIONAL) != 0)
+/*% Secure? */
+#define SECURE(c) (((c)->query.attributes & \
+ NS_QUERYATTR_SECURE) != 0)
+/*% DNS64 A lookup? */
+#define DNS64(c) (((c)->query.attributes & \
+ NS_QUERYATTR_DNS64) != 0)
+
+#define DNS64EXCLUDE(c) (((c)->query.attributes & \
+ NS_QUERYATTR_DNS64EXCLUDE) != 0)
+
+#define REDIRECT(c) (((c)->query.attributes & \
+ NS_QUERYATTR_REDIRECT) != 0)
+
+/*% No QNAME Proof? */
+#define NOQNAME(r) (((r)->attributes & \
+ DNS_RDATASETATTR_NOQNAME) != 0)
+
+#ifdef WANT_QUERYTRACE
+static inline void
+client_trace(ns_client_t *client, int level, const char *message) {
+ if (client != NULL && client->query.qname != NULL) {
+ if (isc_log_wouldlog(ns_g_lctx, level)) {
+ char qbuf[DNS_NAME_FORMATSIZE];
+ char tbuf[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(client->query.qname,
+ qbuf, sizeof(qbuf));
+ dns_rdatatype_format(client->query.qtype,
+ tbuf, sizeof(tbuf));
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY, level,
+ "query client=%p thread=0x%lx "
+ "(%s/%s): %s",
+ client,
+ (unsigned long) isc_thread_self(),
+ qbuf, tbuf, message);
+ }
+ } else {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY, level,
+ "query client=%p thread=0x%lx "
+ "(<unknown-query>): %s",
+ client,
+ (unsigned long) isc_thread_self(),
+ message);
+ }
+}
+#define CTRACE(l,m) client_trace(client, l, m)
+#else
+#define CTRACE(l,m) ((void)m)
+#endif /* WANT_QUERYTRACE */
+
+
+#define DNS_GETDB_NOEXACT 0x01U
+#define DNS_GETDB_NOLOG 0x02U
+#define DNS_GETDB_PARTIAL 0x04U
+#define DNS_GETDB_IGNOREACL 0x08U
+
+#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
+
+#define SFCACHE_CDFLAG 0x1
+
+/*
+ * These have the same semantics as:
+ *
+ * foo_attach(b, a);
+ * foo_detach(&a);
+ *
+ * without the locking and magic testing.
+ *
+ * We use SAVE and RESTORE as that shows the operation being performed.
+ */
+#define SAVE(a, b) do { INSIST(a == NULL); a = b; b = NULL; } while (0)
+#define RESTORE(a, b) SAVE(a, b)
+
+typedef struct client_additionalctx {
+ ns_client_t *client;
+ dns_rdataset_t *rdataset;
+} client_additionalctx_t;
+
+static isc_result_t
+query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
+
+static bool
+validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+
+static void
+query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
+ dns_dbversion_t *version, ns_client_t *client,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_name_t *fname, bool exact,
+ dns_name_t *found);
+
+static inline void
+log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
+
+static void
+rpz_st_clear(ns_client_t *client);
+
+static bool
+rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+
+/*%
+ * Increment query statistics counters.
+ */
+static inline void
+inc_stats(ns_client_t *client, isc_statscounter_t counter) {
+ dns_zone_t *zone = client->query.authzone;
+ dns_rdatatype_t qtype;
+ dns_rdataset_t *rdataset;
+ isc_stats_t *zonestats;
+ dns_stats_t *querystats = NULL;
+
+ isc_stats_increment(ns_g_server->nsstats, counter);
+
+ if (zone == NULL)
+ return;
+
+ /* Do regular response type stats */
+ zonestats = dns_zone_getrequeststats(zone);
+
+ if (zonestats != NULL)
+ isc_stats_increment(zonestats, counter);
+
+ /* Do query type statistics
+ *
+ * We only increment per-type if we're using the authoritative
+ * answer counter, preventing double-counting.
+ */
+ if (counter == dns_nsstatscounter_authans) {
+ querystats = dns_zone_getrcvquerystats(zone);
+ if (querystats != NULL) {
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ if (rdataset != NULL) {
+ qtype = rdataset->type;
+ dns_rdatatypestats_increment(querystats, qtype);
+ }
+ }
+ }
+}
+
+static void
+query_send(ns_client_t *client) {
+ isc_statscounter_t counter;
+
+ if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
+ inc_stats(client, dns_nsstatscounter_nonauthans);
+ else
+ inc_stats(client, dns_nsstatscounter_authans);
+
+ if (client->message->rcode == dns_rcode_noerror) {
+ dns_section_t answer = DNS_SECTION_ANSWER;
+ if (ISC_LIST_EMPTY(client->message->sections[answer])) {
+ if (client->query.isreferral)
+ counter = dns_nsstatscounter_referral;
+ else
+ counter = dns_nsstatscounter_nxrrset;
+ } else
+ counter = dns_nsstatscounter_success;
+ } else if (client->message->rcode == dns_rcode_nxdomain)
+ counter = dns_nsstatscounter_nxdomain;
+ else if (client->message->rcode == dns_rcode_badcookie)
+ counter = dns_nsstatscounter_badcookie;
+ else /* We end up here in case of YXDOMAIN, and maybe others */
+ counter = dns_nsstatscounter_failure;
+
+ inc_stats(client, counter);
+ ns_client_send(client);
+}
+
+static void
+query_error(ns_client_t *client, isc_result_t result, int line) {
+ int loglevel = ISC_LOG_DEBUG(3);
+
+ switch (result) {
+ case DNS_R_SERVFAIL:
+ loglevel = ISC_LOG_DEBUG(1);
+ inc_stats(client, dns_nsstatscounter_servfail);
+ break;
+ case DNS_R_FORMERR:
+ inc_stats(client, dns_nsstatscounter_formerr);
+ break;
+ default:
+ inc_stats(client, dns_nsstatscounter_failure);
+ break;
+ }
+
+ if (ns_g_server->log_queries)
+ loglevel = ISC_LOG_INFO;
+
+ log_queryerror(client, result, line, loglevel);
+
+ ns_client_error(client, result);
+}
+
+static void
+query_next(ns_client_t *client, isc_result_t result) {
+ if (result == DNS_R_DUPLICATE)
+ inc_stats(client, dns_nsstatscounter_duplicate);
+ else if (result == DNS_R_DROP)
+ inc_stats(client, dns_nsstatscounter_dropped);
+ else
+ inc_stats(client, dns_nsstatscounter_failure);
+ ns_client_next(client, result);
+}
+
+static inline void
+query_freefreeversions(ns_client_t *client, bool everything) {
+ ns_dbversion_t *dbversion, *dbversion_next;
+ unsigned int i;
+
+ for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
+ dbversion != NULL;
+ dbversion = dbversion_next, i++)
+ {
+ dbversion_next = ISC_LIST_NEXT(dbversion, link);
+ /*
+ * If we're not freeing everything, we keep the first three
+ * dbversions structures around.
+ */
+ if (i > 3 || everything) {
+ ISC_LIST_UNLINK(client->query.freeversions, dbversion,
+ link);
+ isc_mem_put(client->mctx, dbversion,
+ sizeof(*dbversion));
+ }
+ }
+}
+
+void
+ns_query_cancel(ns_client_t *client) {
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ LOCK(&client->query.fetchlock);
+ if (client->query.fetch != NULL) {
+ dns_resolver_cancelfetch(client->query.fetch);
+
+ client->query.fetch = NULL;
+ }
+ UNLOCK(&client->query.fetchlock);
+}
+
+static inline void
+query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
+ dns_rdataset_t *rdataset = *rdatasetp;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset");
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(client->message, rdatasetp);
+ }
+ CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset: done");
+}
+
+static inline void
+query_reset(ns_client_t *client, bool everything) {
+ isc_buffer_t *dbuf, *dbuf_next;
+ ns_dbversion_t *dbversion, *dbversion_next;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_reset");
+
+ /*%
+ * Reset the query state of a client to its default state.
+ */
+
+ /*
+ * Cancel the fetch if it's running.
+ */
+ ns_query_cancel(client);
+
+ /*
+ * Cleanup any active versions.
+ */
+ for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
+ dbversion != NULL;
+ dbversion = dbversion_next) {
+ dbversion_next = ISC_LIST_NEXT(dbversion, link);
+ dns_db_closeversion(dbversion->db, &dbversion->version,
+ false);
+ dns_db_detach(&dbversion->db);
+ ISC_LIST_INITANDAPPEND(client->query.freeversions,
+ dbversion, link);
+ }
+ ISC_LIST_INIT(client->query.activeversions);
+
+ if (client->query.authdb != NULL)
+ dns_db_detach(&client->query.authdb);
+ if (client->query.authzone != NULL)
+ dns_zone_detach(&client->query.authzone);
+
+ if (client->query.dns64_aaaa != NULL)
+ query_putrdataset(client, &client->query.dns64_aaaa);
+ if (client->query.dns64_sigaaaa != NULL)
+ query_putrdataset(client, &client->query.dns64_sigaaaa);
+ if (client->query.dns64_aaaaok != NULL) {
+ isc_mem_put(client->mctx, client->query.dns64_aaaaok,
+ client->query.dns64_aaaaoklen *
+ sizeof(bool));
+ client->query.dns64_aaaaok = NULL;
+ client->query.dns64_aaaaoklen = 0;
+ }
+
+ query_putrdataset(client, &client->query.redirect.rdataset);
+ query_putrdataset(client, &client->query.redirect.sigrdataset);
+ if (client->query.redirect.db != NULL) {
+ if (client->query.redirect.node != NULL)
+ dns_db_detachnode(client->query.redirect.db,
+ &client->query.redirect.node);
+ dns_db_detach(&client->query.redirect.db);
+ }
+ if (client->query.redirect.zone != NULL)
+ dns_zone_detach(&client->query.redirect.zone);
+
+ query_freefreeversions(client, everything);
+
+ for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
+ dbuf != NULL;
+ dbuf = dbuf_next) {
+ dbuf_next = ISC_LIST_NEXT(dbuf, link);
+ if (dbuf_next != NULL || everything) {
+ ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
+ isc_buffer_free(&dbuf);
+ }
+ }
+
+ if (client->query.restarts > 0) {
+ /*
+ * client->query.qname was dynamically allocated.
+ */
+ dns_message_puttempname(client->message,
+ &client->query.qname);
+ }
+ client->query.qname = NULL;
+ client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
+ NS_QUERYATTR_CACHEOK |
+ NS_QUERYATTR_SECURE);
+ client->query.restarts = 0;
+ client->query.timerset = false;
+ if (client->query.rpz_st != NULL) {
+ rpz_st_clear(client);
+ if (everything) {
+ isc_mem_put(client->mctx, client->query.rpz_st,
+ sizeof(*client->query.rpz_st));
+ client->query.rpz_st = NULL;
+ }
+ }
+ client->query.origqname = NULL;
+ client->query.dboptions = 0;
+ client->query.fetchoptions = 0;
+ client->query.gluedb = NULL;
+ client->query.authdbset = false;
+ client->query.isreferral = false;
+ client->query.dns64_options = 0;
+ client->query.dns64_ttl = UINT32_MAX;
+ client->query.root_key_sentinel_keyid = 0;
+ client->query.root_key_sentinel_is_ta = false;
+ client->query.root_key_sentinel_not_ta = false;
+}
+
+static void
+query_next_callback(ns_client_t *client) {
+ query_reset(client, false);
+}
+
+void
+ns_query_free(ns_client_t *client) {
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ query_reset(client, true);
+}
+
+static inline isc_result_t
+query_newnamebuf(ns_client_t *client) {
+ isc_buffer_t *dbuf;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf");
+ /*%
+ * Allocate a name buffer.
+ */
+
+ dbuf = NULL;
+ result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_newnamebuf: isc_buffer_allocate failed: done");
+ return (result);
+ }
+ ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf: done");
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_buffer_t *
+query_getnamebuf(ns_client_t *client) {
+ isc_buffer_t *dbuf;
+ isc_result_t result;
+ isc_region_t r;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf");
+ /*%
+ * Return a name buffer with space for a maximal name, allocating
+ * a new one if necessary.
+ */
+
+ if (ISC_LIST_EMPTY(client->query.namebufs)) {
+ result = query_newnamebuf(client);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_getnamebuf: query_newnamebuf failed: done");
+ return (NULL);
+ }
+ }
+
+ dbuf = ISC_LIST_TAIL(client->query.namebufs);
+ INSIST(dbuf != NULL);
+ isc_buffer_availableregion(dbuf, &r);
+ if (r.length < DNS_NAME_MAXWIRE) {
+ result = query_newnamebuf(client);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_getnamebuf: query_newnamebuf failed: done");
+ return (NULL);
+
+ }
+ dbuf = ISC_LIST_TAIL(client->query.namebufs);
+ isc_buffer_availableregion(dbuf, &r);
+ INSIST(r.length >= 255);
+ }
+ CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: done");
+ return (dbuf);
+}
+
+static inline void
+query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
+ isc_region_t r;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_keepname");
+ /*%
+ * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
+ * adjusted to take account of that. We do the adjustment.
+ */
+
+ REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
+
+ dns_name_toregion(name, &r);
+ isc_buffer_add(dbuf, r.length);
+ dns_name_setbuffer(name, NULL);
+ client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
+}
+
+static inline void
+query_releasename(ns_client_t *client, dns_name_t **namep) {
+ dns_name_t *name = *namep;
+
+ /*%
+ * 'name' is no longer needed. Return it to our pool of temporary
+ * names. If it is using a name buffer, relinquish its exclusive
+ * rights on the buffer.
+ */
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_releasename");
+ if (dns_name_hasbuffer(name)) {
+ INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
+ != 0);
+ client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
+ }
+ dns_message_puttempname(client->message, namep);
+ CTRACE(ISC_LOG_DEBUG(3), "query_releasename: done");
+}
+
+static inline dns_name_t *
+query_newname(ns_client_t *client, isc_buffer_t *dbuf,
+ isc_buffer_t *nbuf)
+{
+ dns_name_t *name;
+ isc_region_t r;
+ isc_result_t result;
+
+ REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_newname");
+ name = NULL;
+ result = dns_message_gettempname(client->message, &name);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_newname: dns_message_gettempname failed: done");
+ return (NULL);
+ }
+ isc_buffer_availableregion(dbuf, &r);
+ isc_buffer_init(nbuf, r.base, r.length);
+ dns_name_init(name, NULL);
+ dns_name_setbuffer(name, nbuf);
+ client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_newname: done");
+ return (name);
+}
+
+static inline dns_rdataset_t *
+query_newrdataset(ns_client_t *client) {
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset");
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(client->message, &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_newrdataset: "
+ "dns_message_gettemprdataset failed: done");
+ return (NULL);
+ }
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset: done");
+ return (rdataset);
+}
+
+static inline isc_result_t
+query_newdbversion(ns_client_t *client, unsigned int n) {
+ unsigned int i;
+ ns_dbversion_t *dbversion;
+
+ for (i = 0; i < n; i++) {
+ dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
+ if (dbversion != NULL) {
+ dbversion->db = NULL;
+ dbversion->version = NULL;
+ ISC_LIST_INITANDAPPEND(client->query.freeversions,
+ dbversion, link);
+ } else {
+ /*
+ * We only return ISC_R_NOMEMORY if we couldn't
+ * allocate anything.
+ */
+ if (i == 0)
+ return (ISC_R_NOMEMORY);
+ else
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline ns_dbversion_t *
+query_getdbversion(ns_client_t *client) {
+ isc_result_t result;
+ ns_dbversion_t *dbversion;
+
+ if (ISC_LIST_EMPTY(client->query.freeversions)) {
+ result = query_newdbversion(client, 1);
+ if (result != ISC_R_SUCCESS)
+ return (NULL);
+ }
+ dbversion = ISC_LIST_HEAD(client->query.freeversions);
+ INSIST(dbversion != NULL);
+ ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
+
+ return (dbversion);
+}
+
+isc_result_t
+ns_query_init(ns_client_t *client) {
+ isc_result_t result;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ ISC_LIST_INIT(client->query.namebufs);
+ ISC_LIST_INIT(client->query.activeversions);
+ ISC_LIST_INIT(client->query.freeversions);
+ client->query.restarts = 0;
+ client->query.timerset = false;
+ client->query.rpz_st = NULL;
+ client->query.qname = NULL;
+ /*
+ * This mutex is destroyed when the client is destroyed in
+ * exit_check().
+ */
+ result = isc_mutex_init(&client->query.fetchlock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ client->query.fetch = NULL;
+ client->query.prefetch = NULL;
+ client->query.authdb = NULL;
+ client->query.authzone = NULL;
+ client->query.authdbset = false;
+ client->query.isreferral = false;
+ client->query.dns64_aaaa = NULL;
+ client->query.dns64_sigaaaa = NULL;
+ client->query.dns64_aaaaok = NULL;
+ client->query.dns64_aaaaoklen = 0;
+ client->query.redirect.db = NULL;
+ client->query.redirect.node = NULL;
+ client->query.redirect.zone = NULL;
+ client->query.redirect.qtype = dns_rdatatype_none;
+ client->query.redirect.result = ISC_R_SUCCESS;
+ client->query.redirect.rdataset = NULL;
+ client->query.redirect.sigrdataset = NULL;
+ client->query.redirect.authoritative = false;
+ client->query.redirect.is_zone = false;
+ client->query.redirect.fname =
+ dns_fixedname_initname(&client->query.redirect.fixed);
+ query_reset(client, false);
+ result = query_newdbversion(client, 3);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&client->query.fetchlock);
+ return (result);
+ }
+ result = query_newnamebuf(client);
+ if (result != ISC_R_SUCCESS) {
+ query_freefreeversions(client, true);
+ DESTROYLOCK(&client->query.fetchlock);
+ }
+
+ return (result);
+}
+
+static ns_dbversion_t *
+query_findversion(ns_client_t *client, dns_db_t *db) {
+ ns_dbversion_t *dbversion;
+
+ /*%
+ * We may already have done a query related to this
+ * database. If so, we must be sure to make subsequent
+ * queries from the same version.
+ */
+ for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
+ dbversion != NULL;
+ dbversion = ISC_LIST_NEXT(dbversion, link)) {
+ if (dbversion->db == db)
+ break;
+ }
+
+ if (dbversion == NULL) {
+ /*
+ * This is a new zone for this query. Add it to
+ * the active list.
+ */
+ dbversion = query_getdbversion(client);
+ if (dbversion == NULL)
+ return (NULL);
+ dns_db_attach(db, &dbversion->db);
+ dns_db_currentversion(db, &dbversion->version);
+ dbversion->acl_checked = false;
+ dbversion->queryok = false;
+ ISC_LIST_APPEND(client->query.activeversions,
+ dbversion, link);
+ }
+
+ return (dbversion);
+}
+
+static inline isc_result_t
+query_validatezonedb(ns_client_t *client, dns_name_t *name,
+ dns_rdatatype_t qtype, unsigned int options,
+ dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t **versionp)
+{
+ isc_result_t result;
+ dns_acl_t *queryacl, *queryonacl;
+ ns_dbversion_t *dbversion;
+
+ REQUIRE(zone != NULL);
+ REQUIRE(db != NULL);
+
+ /*
+ * This limits our searching to the zone where the first name
+ * (the query target) was looked for. This prevents following
+ * CNAMES or DNAMES into other zones and prevents returning
+ * additional data from other zones.
+ */
+ if (!client->view->additionalfromauth &&
+ client->query.authdbset &&
+ db != client->query.authdb)
+ return (DNS_R_REFUSED);
+
+ /*
+ * Non recursive query to a static-stub zone is prohibited; its
+ * zone content is not public data, but a part of local configuration
+ * and should not be disclosed.
+ */
+ if (dns_zone_gettype(zone) == dns_zone_staticstub &&
+ !RECURSIONOK(client)) {
+ return (DNS_R_REFUSED);
+ }
+
+ /*
+ * If the zone has an ACL, we'll check it, otherwise
+ * we use the view's "allow-query" ACL. Each ACL is only checked
+ * once per query.
+ *
+ * Also, get the database version to use.
+ */
+
+ /*
+ * Get the current version of this database.
+ */
+ dbversion = query_findversion(client, db);
+ if (dbversion == NULL) {
+ CTRACE(ISC_LOG_ERROR, "unable to get db version");
+ return (DNS_R_SERVFAIL);
+ }
+
+ if ((options & DNS_GETDB_IGNOREACL) != 0)
+ goto approved;
+ if (dbversion->acl_checked) {
+ if (!dbversion->queryok)
+ return (DNS_R_REFUSED);
+ goto approved;
+ }
+
+ queryacl = dns_zone_getqueryacl(zone);
+ if (queryacl == NULL) {
+ queryacl = client->view->queryacl;
+ if ((client->query.attributes &
+ NS_QUERYATTR_QUERYOKVALID) != 0) {
+ /*
+ * We've evaluated the view's queryacl already. If
+ * NS_QUERYATTR_QUERYOK is set, then the client is
+ * allowed to make queries, otherwise the query should
+ * be refused.
+ */
+ dbversion->acl_checked = true;
+ if ((client->query.attributes &
+ NS_QUERYATTR_QUERYOK) == 0) {
+ dbversion->queryok = false;
+ return (DNS_R_REFUSED);
+ }
+ dbversion->queryok = true;
+ goto approved;
+ }
+ }
+
+ result = ns_client_checkaclsilent(client, NULL, queryacl, true);
+ if ((options & DNS_GETDB_NOLOG) == 0) {
+ char msg[NS_CLIENT_ACLMSGSIZE("query")];
+ if (result == ISC_R_SUCCESS) {
+ if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) {
+ ns_client_aclmsg("query", name, qtype,
+ client->view->rdclass,
+ msg, sizeof(msg));
+ ns_client_log(client,
+ DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_DEBUG(3),
+ "%s approved", msg);
+ }
+ } else {
+ ns_client_aclmsg("query", name, qtype,
+ client->view->rdclass,
+ msg, sizeof(msg));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "%s denied", msg);
+ }
+ }
+
+ if (queryacl == client->view->queryacl) {
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We were allowed by the default
+ * "allow-query" ACL. Remember this so we
+ * don't have to check again.
+ */
+ client->query.attributes |= NS_QUERYATTR_QUERYOK;
+ }
+ /*
+ * We've now evaluated the view's query ACL, and
+ * the NS_QUERYATTR_QUERYOK attribute is now valid.
+ */
+ client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
+ }
+
+ /* If and only if we've gotten this far, check allow-query-on too */
+ if (result == ISC_R_SUCCESS) {
+ queryonacl = dns_zone_getqueryonacl(zone);
+ if (queryonacl == NULL)
+ queryonacl = client->view->queryonacl;
+
+ result = ns_client_checkaclsilent(client, &client->destaddr,
+ queryonacl, true);
+ if ((options & DNS_GETDB_NOLOG) == 0 &&
+ result != ISC_R_SUCCESS)
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "query-on denied");
+ }
+
+ dbversion->acl_checked = true;
+ if (result != ISC_R_SUCCESS) {
+ dbversion->queryok = false;
+ return (DNS_R_REFUSED);
+ }
+ dbversion->queryok = true;
+
+ approved:
+ /* Transfer ownership, if necessary. */
+ if (versionp != NULL)
+ *versionp = dbversion->version;
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
+ unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp)
+{
+ isc_result_t result;
+ unsigned int ztoptions;
+ dns_zone_t *zone = NULL;
+ dns_db_t *db = NULL;
+ bool partial = false;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /*%
+ * Find a zone database to answer the query.
+ */
+ ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
+ DNS_ZTFIND_NOEXACT : 0;
+
+ result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
+ &zone);
+
+ if (result == DNS_R_PARTIALMATCH)
+ partial = true;
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ result = dns_zone_getdb(zone, &db);
+
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = query_validatezonedb(client, name, qtype, options, zone, db,
+ versionp);
+
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /* Transfer ownership. */
+ *zonep = zone;
+ *dbp = db;
+
+ if (partial && (options & DNS_GETDB_PARTIAL) != 0)
+ return (DNS_R_PARTIALMATCH);
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ return (result);
+}
+
+static void
+rpz_log_rewrite(ns_client_t *client, bool disabled,
+ dns_rpz_policy_t policy, dns_rpz_type_t type,
+ dns_zone_t *p_zone, dns_name_t *p_name,
+ dns_name_t *cname, dns_rpz_num_t rpz_num)
+{
+ isc_stats_t *zonestats;
+ char qname_buf[DNS_NAME_FORMATSIZE];
+ char p_name_buf[DNS_NAME_FORMATSIZE];
+ char cname_buf[DNS_NAME_FORMATSIZE] = { 0 };
+ const char *s1 = cname_buf, *s2 = cname_buf;
+ dns_rpz_st_t *st;
+
+ /*
+ * Count enabled rewrites in the global counter.
+ * Count both enabled and disabled rewrites for each zone.
+ */
+ if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_rpz_rewrites);
+ }
+ if (p_zone != NULL) {
+ zonestats = dns_zone_getrequeststats(p_zone);
+ if (zonestats != NULL)
+ isc_stats_increment(zonestats,
+ dns_nsstatscounter_rpz_rewrites);
+ }
+
+ if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL))
+ return;
+
+ st = client->query.rpz_st;
+ if ((st->popt.no_log & DNS_RPZ_ZBIT(rpz_num)) != 0)
+ return;
+
+ dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
+ dns_name_format(p_name, p_name_buf, sizeof(p_name_buf));
+ if (cname != NULL) {
+ s1 = " (CNAME to: ";
+ dns_name_format(cname, cname_buf, sizeof(cname_buf));
+ s2 = ")";
+ }
+
+ ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY,
+ DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s%s%s%s",
+ disabled ? "disabled " : "",
+ dns_rpz_type2str(type), dns_rpz_policy2str(policy),
+ qname_buf, p_name_buf, s1, cname_buf, s2);
+}
+
+static void
+rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name,
+ dns_rpz_type_t rpz_type1, dns_rpz_type_t rpz_type2,
+ const char *str, isc_result_t result)
+{
+ char qnamebuf[DNS_NAME_FORMATSIZE];
+ char p_namebuf[DNS_NAME_FORMATSIZE];
+ const char *failed;
+ const char *slash;
+ const char *via;
+ const char *str_blank;
+ const char *rpztypestr1;
+ const char *rpztypestr2;
+
+ if (!isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ /*
+ * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems.
+ */
+ if (level <= DNS_RPZ_DEBUG_LEVEL1)
+ failed = "failed: ";
+ else
+ failed = ": ";
+
+ rpztypestr1 = dns_rpz_type2str(rpz_type1);
+ if (rpz_type2 != DNS_RPZ_TYPE_BAD) {
+ slash = "/";
+ rpztypestr2 = dns_rpz_type2str(rpz_type2);
+ } else {
+ slash = "";
+ rpztypestr2 = "";
+ }
+
+ str_blank = (*str != ' ' && *str != '\0') ? " " : "";
+ dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf));
+ if (p_name != NULL) {
+ via = " via ";
+ dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
+ } else {
+ via = "";
+ p_namebuf[0] = '\0';
+ }
+
+ ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS,
+ NS_LOGMODULE_QUERY, level,
+ "rpz %s%s%s rewrite %s%s%s%s%s%s : %s",
+ rpztypestr1, slash, rpztypestr2,
+ qnamebuf, via, p_namebuf, str_blank,
+ str, failed, isc_result_totext(result));
+}
+
+static void
+rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name,
+ dns_rpz_type_t rpz_type, const char *str, isc_result_t result)
+{
+ rpz_log_fail_helper(client, level, p_name,
+ rpz_type, DNS_RPZ_TYPE_BAD, str, result);
+}
+
+/*
+ * Get a policy rewrite zone database.
+ */
+static isc_result_t
+rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type,
+ dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp)
+{
+ char qnamebuf[DNS_NAME_FORMATSIZE];
+ char p_namebuf[DNS_NAME_FORMATSIZE];
+ dns_dbversion_t *rpz_version = NULL;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_getdb");
+
+ result = query_getzonedb(client, p_name, dns_rdatatype_any,
+ DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
+ if (result == ISC_R_SUCCESS) {
+ dns_rpz_st_t *st = client->query.rpz_st;
+
+ /*
+ * It isn't meaningful to log this message when
+ * logging is disabled for some policy zones.
+ */
+ if (st->popt.no_log == 0 &&
+ isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2))
+ {
+ dns_name_format(client->query.qname, qnamebuf,
+ sizeof(qnamebuf));
+ dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
+ ns_client_log(client, DNS_LOGCATEGORY_RPZ,
+ NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
+ "try rpz %s rewrite %s via %s",
+ dns_rpz_type2str(rpz_type),
+ qnamebuf, p_namebuf);
+ }
+ *versionp = rpz_version;
+ return (ISC_R_SUCCESS);
+ }
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
+ " query_getzonedb()", result);
+ return (result);
+}
+
+static inline isc_result_t
+query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
+ dns_db_t **dbp, unsigned int options)
+{
+ isc_result_t result;
+ bool check_acl;
+ dns_db_t *db = NULL;
+
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /*%
+ * Find a cache database to answer the query.
+ * This may fail with DNS_R_REFUSED if the client
+ * is not allowed to use the cache.
+ */
+
+ if (!USECACHE(client))
+ return (DNS_R_REFUSED);
+ dns_db_attach(client->view->cachedb, &db);
+
+ if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) != 0) {
+ /*
+ * We've evaluated the view's cacheacl already. If
+ * NS_QUERYATTR_CACHEACLOK is set, then the client is
+ * allowed to make queries, otherwise the query should
+ * be refused.
+ */
+ check_acl = false;
+ if ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) == 0)
+ goto refuse;
+ } else {
+ /*
+ * We haven't evaluated the view's queryacl yet.
+ */
+ check_acl = true;
+ }
+
+ if (check_acl) {
+ bool log = !(options & DNS_GETDB_NOLOG);
+ char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
+
+ result = ns_client_checkaclsilent(client, NULL,
+ client->view->cacheacl,
+ true);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We were allowed by the "allow-query-cache" ACL.
+ * Remember this so we don't have to check again.
+ */
+ client->query.attributes |=
+ NS_QUERYATTR_CACHEACLOK;
+ if (log && isc_log_wouldlog(ns_g_lctx,
+ ISC_LOG_DEBUG(3)))
+ {
+ ns_client_aclmsg("query (cache)", name, qtype,
+ client->view->rdclass,
+ msg, sizeof(msg));
+ ns_client_log(client,
+ DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_DEBUG(3),
+ "%s approved", msg);
+ }
+ } else if (log) {
+ ns_client_aclmsg("query (cache)", name, qtype,
+ client->view->rdclass, msg,
+ sizeof(msg));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "%s denied", msg);
+ }
+ /*
+ * We've now evaluated the view's query ACL, and
+ * the NS_QUERYATTR_CACHEACLOKVALID attribute is now valid.
+ */
+ client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
+
+ if (result != ISC_R_SUCCESS)
+ goto refuse;
+ }
+
+ /* Approved. */
+
+ /* Transfer ownership. */
+ *dbp = db;
+
+ return (ISC_R_SUCCESS);
+
+ refuse:
+ result = DNS_R_REFUSED;
+
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ return (result);
+}
+
+static inline isc_result_t
+query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
+ unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp, bool *is_zonep)
+{
+ isc_result_t result;
+
+ isc_result_t tresult;
+ unsigned int namelabels;
+ unsigned int zonelabels;
+ dns_zone_t *zone = NULL;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+
+ /* Calculate how many labels are in name. */
+ namelabels = dns_name_countlabels(name);
+ zonelabels = 0;
+
+ /* Try to find name in bind's standard database. */
+ result = query_getzonedb(client, name, qtype, options, &zone,
+ dbp, versionp);
+
+ /* See how many labels are in the zone's name. */
+ if (result == ISC_R_SUCCESS && zone != NULL)
+ zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
+
+ /*
+ * If # zone labels < # name labels, try to find an even better match
+ * Only try if DLZ drivers are loaded for this view
+ */
+ if (ISC_UNLIKELY(zonelabels < namelabels &&
+ !ISC_LIST_EMPTY(client->view->dlz_searched)))
+ {
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ dns_db_t *tdbp;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ tdbp = NULL;
+ tresult = dns_view_searchdlz(client->view, name,
+ zonelabels, &cm, &ci, &tdbp);
+ /* If we successful, we found a better match. */
+ if (tresult == ISC_R_SUCCESS) {
+ ns_dbversion_t *dbversion;
+
+ /*
+ * If the previous search returned a zone, detach it.
+ */
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ /*
+ * If the previous search returned a database,
+ * detach it.
+ */
+ if (*dbp != NULL)
+ dns_db_detach(dbp);
+
+ /*
+ * If the previous search returned a version, clear it.
+ */
+ *versionp = NULL;
+
+ dbversion = query_findversion(client, tdbp);
+ if (dbversion == NULL) {
+ tresult = ISC_R_NOMEMORY;
+ } else {
+ /*
+ * Be sure to return our database.
+ */
+ *dbp = tdbp;
+ *versionp = dbversion->version;
+ }
+
+ /*
+ * We return a null zone, No stats for DLZ zones.
+ */
+ zone = NULL;
+ result = tresult;
+ }
+ }
+
+ /* If successful, Transfer ownership of zone. */
+ if (result == ISC_R_SUCCESS) {
+ *zonep = zone;
+ /*
+ * If neither attempt above succeeded, return the cache instead
+ */
+ *is_zonep = true;
+ } else if (result == ISC_R_NOTFOUND) {
+ result = query_getcachedb(client, name, qtype, dbp, options);
+ *is_zonep = false;
+ }
+ return (result);
+}
+
+static inline bool
+query_isduplicate(ns_client_t *client, dns_name_t *name,
+ dns_rdatatype_t type, dns_name_t **mnamep)
+{
+ dns_section_t section;
+ dns_name_t *mname = NULL;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
+
+ for (section = DNS_SECTION_ANSWER;
+ section <= DNS_SECTION_ADDITIONAL;
+ section++) {
+ result = dns_message_findname(client->message, section,
+ name, type, 0, &mname, NULL);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got this RRset in the response.
+ */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_isduplicate: true: done");
+ return (true);
+ } else if (result == DNS_R_NXRRSET) {
+ /*
+ * The name exists, but the rdataset does not.
+ */
+ if (section == DNS_SECTION_ADDITIONAL)
+ break;
+ } else
+ RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
+ mname = NULL;
+ }
+
+ if (mnamep != NULL)
+ *mnamep = mname;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
+ return (false);
+}
+
+static isc_result_t
+query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
+ ns_client_t *client = arg;
+ isc_result_t result, eresult;
+ dns_dbnode_t *node;
+ dns_db_t *db;
+ dns_name_t *fname, *mname;
+ dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
+ isc_buffer_t *dbuf;
+ isc_buffer_t b;
+ dns_dbversion_t *version;
+ bool added_something, need_addname;
+ dns_zone_t *zone;
+ dns_rdatatype_t type;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ dns_rdatasetadditional_t additionaltype;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(qtype != dns_rdatatype_any);
+
+ if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
+ return (ISC_R_SUCCESS);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional");
+
+ /*
+ * Initialization.
+ */
+ eresult = ISC_R_SUCCESS;
+ fname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ trdataset = NULL;
+ db = NULL;
+ version = NULL;
+ node = NULL;
+ added_something = false;
+ need_addname = false;
+ zone = NULL;
+ additionaltype = dns_rdatasetadditional_fromauth;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * We treat type A additional section processing as if it
+ * were "any address type" additional section processing.
+ * To avoid multiple lookups, we do an 'any' database
+ * lookup and iterate over the node.
+ */
+ if (qtype == dns_rdatatype_a)
+ type = dns_rdatatype_any;
+ else
+ type = qtype;
+
+ /*
+ * Get some resources.
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL)
+ goto cleanup;
+ if (WANTDNSSEC(client)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+ }
+
+ /*
+ * Look for a zone database that might contain authoritative
+ * additional data.
+ */
+ result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
+ &zone, &db, &version);
+ if (result != ISC_R_SUCCESS)
+ goto try_cache;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: db_find");
+
+ /*
+ * Since we are looking for authoritative data, we do not set
+ * the GLUEOK flag. Glue will be looked for later, but not
+ * necessarily in the same database.
+ */
+ result = dns_db_findext(db, name, version, type,
+ client->query.dboptions,
+ client->now, &node, fname, &cm, &ci,
+ rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (sigrdataset != NULL && !dns_db_issecure(db) &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ goto found;
+ }
+
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ version = NULL;
+ dns_db_detach(&db);
+
+ /*
+ * No authoritative data was found. The cache is our next best bet.
+ */
+
+ try_cache:
+ additionaltype = dns_rdatasetadditional_fromcache;
+ result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
+ if (result != ISC_R_SUCCESS)
+ /*
+ * Most likely the client isn't allowed to query the cache.
+ */
+ goto try_glue;
+ /*
+ * Attempt to validate glue.
+ */
+ if (sigrdataset == NULL) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+ }
+ result = dns_db_findext(db, name, version, type,
+ client->query.dboptions |
+ DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
+ client->now, &node, fname, &cm, &ci,
+ rdataset, sigrdataset);
+
+ dns_cache_updatestats(client->view->cache, result);
+ if (!WANTDNSSEC(client))
+ query_putrdataset(client, &sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto found;
+
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+
+ try_glue:
+ /*
+ * No cached data was found. Glue is our last chance.
+ * RFC1035 sayeth:
+ *
+ * NS records cause both the usual additional section
+ * processing to locate a type A record, and, when used
+ * in a referral, a special search of the zone in which
+ * they reside for glue information.
+ *
+ * This is the "special search". Note that we must search
+ * the zone where the NS record resides, not the zone it
+ * points to, and that we only do the search in the delegation
+ * case (identified by client->query.gluedb being set).
+ */
+
+ if (client->query.gluedb == NULL)
+ goto cleanup;
+
+ /*
+ * Don't poison caches using the bailiwick protection model.
+ */
+ if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
+ goto cleanup;
+
+ dns_db_attach(client->query.gluedb, &db);
+
+ additionaltype = dns_rdatasetadditional_fromglue;
+ result = dns_db_findext(db, name, version, type,
+ client->query.dboptions | DNS_DBFIND_GLUEOK,
+ client->now, &node, fname, &cm, &ci,
+ rdataset, sigrdataset);
+ if (!(result == ISC_R_SUCCESS ||
+ result == DNS_R_ZONECUT ||
+ result == DNS_R_GLUE))
+ goto cleanup;
+
+ found:
+ /*
+ * We have found a potential additional data rdataset, or
+ * at least a node to iterate over.
+ */
+ query_keepname(client, fname, dbuf);
+
+ /*
+ * If we have an rdataset, add it to the additional data
+ * section.
+ */
+ mname = NULL;
+ if (dns_rdataset_isassociated(rdataset) &&
+ !query_isduplicate(client, fname, type, &mname)) {
+ if (mname != NULL) {
+ INSIST(mname != fname);
+ query_releasename(client, &fname);
+ fname = mname;
+ } else
+ need_addname = true;
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ trdataset = rdataset;
+ rdataset = NULL;
+ added_something = true;
+ /*
+ * Note: we only add SIGs if we've added the type they cover,
+ * so we do not need to check if the SIG rdataset is already
+ * in the response.
+ */
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ {
+ ISC_LIST_APPEND(fname->list, sigrdataset, link);
+ sigrdataset = NULL;
+ }
+ }
+
+ if (qtype == dns_rdatatype_a) {
+#ifdef ALLOW_FILTER_AAAA
+ bool have_a = false;
+#endif
+
+ /*
+ * We now go looking for A and AAAA records, along with
+ * their signatures.
+ *
+ * XXXRTH This code could be more efficient.
+ */
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ } else {
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ goto addname;
+ }
+ if (sigrdataset != NULL) {
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ } else if (WANTDNSSEC(client)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto addname;
+ }
+ if (query_isduplicate(client, fname, dns_rdatatype_a, NULL))
+ goto aaaa_lookup;
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_a, 0,
+ client->now,
+ rdataset, sigrdataset);
+ if (result == DNS_R_NCACHENXDOMAIN)
+ goto addname;
+ if (result == DNS_R_NCACHENXRRSET) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ if (result == ISC_R_SUCCESS) {
+ bool invalid = false;
+ mname = NULL;
+#ifdef ALLOW_FILTER_AAAA
+ have_a = true;
+#endif
+ if (additionaltype ==
+ dns_rdatasetadditional_fromcache &&
+ (DNS_TRUST_PENDING(rdataset->trust) ||
+ DNS_TRUST_GLUE(rdataset->trust)))
+ {
+ /* validate() may change rdataset->trust */
+ invalid = !validate(client, db, fname,
+ rdataset, sigrdataset);
+ }
+ if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ } else if (!query_isduplicate(client, fname,
+ dns_rdatatype_a, &mname))
+ {
+ if (mname != fname) {
+ if (mname != NULL) {
+ query_releasename(client,
+ &fname);
+ fname = mname;
+ } else
+ need_addname = true;
+ }
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ added_something = true;
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ {
+ ISC_LIST_APPEND(fname->list,
+ sigrdataset, link);
+ sigrdataset =
+ query_newrdataset(client);
+ }
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ goto addname;
+ if (WANTDNSSEC(client) && sigrdataset == NULL)
+ goto addname;
+ } else {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ }
+ aaaa_lookup:
+ if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
+ goto addname;
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_aaaa, 0,
+ client->now,
+ rdataset, sigrdataset);
+ if (result == DNS_R_NCACHENXDOMAIN)
+ goto addname;
+ if (result == DNS_R_NCACHENXRRSET) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ if (result == ISC_R_SUCCESS) {
+ bool invalid = false;
+ mname = NULL;
+ /*
+ * There's an A; check whether we're filtering AAAA
+ */
+#ifdef ALLOW_FILTER_AAAA
+ if (have_a &&
+ (client->filter_aaaa == dns_aaaa_break_dnssec ||
+ (client->filter_aaaa == dns_aaaa_filter &&
+ (!WANTDNSSEC(client) || sigrdataset == NULL ||
+ !dns_rdataset_isassociated(sigrdataset)))))
+ goto addname;
+#endif
+ if (additionaltype ==
+ dns_rdatasetadditional_fromcache &&
+ (DNS_TRUST_PENDING(rdataset->trust) ||
+ DNS_TRUST_GLUE(rdataset->trust)))
+ {
+ /* validate() may change rdataset->trust */
+ invalid = !validate(client, db, fname,
+ rdataset, sigrdataset);
+ }
+ if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ } else if (!query_isduplicate(client, fname,
+ dns_rdatatype_aaaa, &mname))
+ {
+ if (mname != fname) {
+ if (mname != NULL) {
+ query_releasename(client,
+ &fname);
+ fname = mname;
+ } else
+ need_addname = true;
+ }
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ added_something = true;
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ {
+ ISC_LIST_APPEND(fname->list,
+ sigrdataset, link);
+ sigrdataset = NULL;
+ }
+ rdataset = NULL;
+ }
+ }
+ }
+
+ addname:
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: addname");
+ /*
+ * If we haven't added anything, then we're done.
+ */
+ if (!added_something)
+ goto cleanup;
+
+ /*
+ * We may have added our rdatasets to an existing name, if so, then
+ * need_addname will be false. Whether we used an existing name
+ * or a new one, we must set fname to NULL to prevent cleanup.
+ */
+ if (need_addname)
+ dns_message_addname(client->message, fname,
+ DNS_SECTION_ADDITIONAL);
+ fname = NULL;
+
+ /*
+ * In a few cases, we want to add additional data for additional
+ * data. It's simpler to just deal with special cases here than
+ * to try to create a general purpose mechanism and allow the
+ * rdata implementations to do it themselves.
+ *
+ * This involves recursion, but the depth is limited. The
+ * most complex case is adding a SRV rdataset, which involves
+ * recursing to add address records, which in turn can cause
+ * recursion to add KEYs.
+ */
+ if (type == dns_rdatatype_srv && trdataset != NULL) {
+ /*
+ * If we're adding SRV records to the additional data
+ * section, it's helpful if we add the SRV additional data
+ * as well.
+ */
+ eresult = dns_rdataset_additionaldata(trdataset,
+ query_addadditional,
+ client);
+ }
+
+ cleanup:
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: cleanup");
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: done");
+ return (eresult);
+}
+
+static inline void
+query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
+ dns_rdatasetadditional_t additionaltype,
+ dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp, dns_dbnode_t **nodep,
+ dns_name_t *fname)
+{
+ dns_rdataset_t *rdataset;
+
+ while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
+ ISC_LIST_UNLINK(fname->list, rdataset, link);
+ query_putrdataset(client, &rdataset);
+ }
+ if (*versionp != NULL)
+ dns_db_closeversion(*dbp, versionp, false);
+ if (*nodep != NULL)
+ dns_db_detachnode(*dbp, nodep);
+ if (*dbp != NULL)
+ dns_db_detach(dbp);
+ if (*zonep != NULL)
+ dns_zone_detach(zonep);
+ (void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
+ additionaltype, type);
+}
+
+static inline isc_result_t
+query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
+ dns_dbversion_t *version)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_dbversion_t *version_current = NULL;
+ dns_db_t *db_current = db0;
+
+ if (db_current == NULL) {
+ result = dns_zone_getdb(zone, &db_current);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ dns_db_currentversion(db_current, &version_current);
+ if (db_current != db || version_current != version) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ cleanup:
+ dns_db_closeversion(db_current, &version_current, false);
+ if (db0 == NULL && db_current != NULL)
+ dns_db_detach(&db_current);
+
+ return (result);
+}
+
+static isc_result_t
+query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
+ client_additionalctx_t *additionalctx = arg;
+ dns_rdataset_t *rdataset_base;
+ ns_client_t *client;
+ isc_result_t result, eresult;
+ dns_dbnode_t *node, *cnode;
+ dns_db_t *db, *cdb;
+ dns_name_t *fname, *mname0, cfname;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ dns_rdataset_t *crdataset, *crdataset_next;
+ isc_buffer_t *dbuf;
+ isc_buffer_t b;
+ dns_dbversion_t *version, *cversion;
+ bool added_something, need_addname, needadditionalcache;
+ bool need_sigrrset;
+ dns_zone_t *zone;
+ dns_rdatatype_t type;
+ dns_rdatasetadditional_t additionaltype;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ bool invalid;
+
+ /*
+ * If we don't have an additional cache call query_addadditional.
+ */
+ client = additionalctx->client;
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ if (qtype != dns_rdatatype_a || client->view->acache == NULL) {
+ /*
+ * This function is optimized for "address" types. For other
+ * types, use a generic routine.
+ * XXX: ideally, this function should be generic enough.
+ */
+ return (query_addadditional(additionalctx->client,
+ name, qtype));
+ }
+
+ /*
+ * Initialization.
+ */
+ rdataset_base = additionalctx->rdataset;
+ eresult = ISC_R_SUCCESS;
+ fname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ db = NULL;
+ cdb = NULL;
+ version = NULL;
+ cversion = NULL;
+ node = NULL;
+ cnode = NULL;
+ added_something = false;
+ need_addname = false;
+ zone = NULL;
+ needadditionalcache = false;
+ POST(needadditionalcache);
+ additionaltype = dns_rdatasetadditional_fromauth;
+ dns_name_init(&cfname, NULL);
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2");
+
+ /*
+ * We treat type A additional section processing as if it
+ * were "any address type" additional section processing.
+ * To avoid multiple lookups, we do an 'any' database
+ * lookup and iterate over the node.
+ * XXXJT: this approach can cause a suboptimal result when the cache
+ * DB only has partial address types and the glue DB has remaining
+ * ones.
+ */
+ type = dns_rdatatype_any;
+
+ /*
+ * Get some resources.
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL)
+ goto cleanup;
+ dns_name_setbuffer(&cfname, &b); /* share the buffer */
+
+ /* Check additional cache */
+ result = dns_rdataset_getadditional(rdataset_base, additionaltype,
+ type, client->view->acache, &zone,
+ &cdb, &cversion, &cnode, &cfname,
+ client->message, client->now);
+ if (result != ISC_R_SUCCESS)
+ goto findauthdb;
+ if (zone == NULL) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addadditional2: auth zone not found");
+ goto try_cache;
+ }
+
+ /* Is the cached DB up-to-date? */
+ result = query_iscachevalid(zone, cdb, NULL, cversion);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addadditional2: old auth additional cache");
+ query_discardcache(client, rdataset_base, additionaltype,
+ type, &zone, &cdb, &cversion, &cnode,
+ &cfname);
+ goto findauthdb;
+ }
+
+ if (cnode == NULL) {
+ /*
+ * We have a negative cache. We don't have to check the zone
+ * ACL, since the result (not using this zone) would be same
+ * regardless of the result.
+ */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addadditional2: negative auth additional cache");
+ dns_db_closeversion(cdb, &cversion, false);
+ dns_db_detach(&cdb);
+ dns_zone_detach(&zone);
+ goto try_cache;
+ }
+
+ result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
+ zone, cdb, NULL);
+ if (result != ISC_R_SUCCESS) {
+ query_discardcache(client, rdataset_base, additionaltype,
+ type, &zone, &cdb, &cversion, &cnode,
+ &cfname);
+ goto try_cache;
+ }
+
+ /* We've got an active cache. */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addadditional2: auth additional cache");
+ dns_db_closeversion(cdb, &cversion, false);
+ db = cdb;
+ node = cnode;
+ dns_name_clone(&cfname, fname);
+ query_keepname(client, fname, dbuf);
+ goto foundcache;
+
+ /*
+ * Look for a zone database that might contain authoritative
+ * additional data.
+ */
+ findauthdb:
+ result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
+ &zone, &db, &version);
+ if (result != ISC_R_SUCCESS) {
+ /* Cache the negative result */
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ goto try_cache;
+ }
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: db_find");
+
+ /*
+ * Since we are looking for authoritative data, we do not set
+ * the GLUEOK flag. Glue will be looked for later, but not
+ * necessarily in the same database.
+ */
+ node = NULL;
+ result = dns_db_findext(db, name, version, type,
+ client->query.dboptions,
+ client->now, &node, fname, &cm, &ci,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ goto found;
+
+ /* Cache the negative result */
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache, zone, db,
+ version, NULL, fname);
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ version = NULL;
+ dns_db_detach(&db);
+
+ /*
+ * No authoritative data was found. The cache is our next best bet.
+ */
+
+ try_cache:
+ additionaltype = dns_rdatasetadditional_fromcache;
+ result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
+ if (result != ISC_R_SUCCESS)
+ /*
+ * Most likely the client isn't allowed to query the cache.
+ */
+ goto try_glue;
+
+ result = dns_db_findext(db, name, version, type,
+ client->query.dboptions |
+ DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
+ client->now, &node, fname, &cm, &ci,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ goto found;
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+
+ try_glue:
+ /*
+ * No cached data was found. Glue is our last chance.
+ * RFC1035 sayeth:
+ *
+ * NS records cause both the usual additional section
+ * processing to locate a type A record, and, when used
+ * in a referral, a special search of the zone in which
+ * they reside for glue information.
+ *
+ * This is the "special search". Note that we must search
+ * the zone where the NS record resides, not the zone it
+ * points to, and that we only do the search in the delegation
+ * case (identified by client->query.gluedb being set).
+ */
+ if (client->query.gluedb == NULL)
+ goto cleanup;
+
+ /*
+ * Don't poison caches using the bailiwick protection model.
+ */
+ if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
+ goto cleanup;
+
+ /* Check additional cache */
+ additionaltype = dns_rdatasetadditional_fromglue;
+ result = dns_rdataset_getadditional(rdataset_base, additionaltype,
+ type, client->view->acache, NULL,
+ &cdb, &cversion, &cnode, &cfname,
+ client->message, client->now);
+ if (result != ISC_R_SUCCESS)
+ goto findglue;
+
+ result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addadditional2: old glue additional cache");
+ query_discardcache(client, rdataset_base, additionaltype,
+ type, &zone, &cdb, &cversion, &cnode,
+ &cfname);
+ goto findglue;
+ }
+
+ if (cnode == NULL) {
+ /* We have a negative cache. */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addadditional2: negative glue additional cache");
+ dns_db_closeversion(cdb, &cversion, false);
+ dns_db_detach(&cdb);
+ goto cleanup;
+ }
+
+ /* Cache hit. */
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: glue additional cache");
+ dns_db_closeversion(cdb, &cversion, false);
+ db = cdb;
+ node = cnode;
+ dns_name_clone(&cfname, fname);
+ query_keepname(client, fname, dbuf);
+ goto foundcache;
+
+ findglue:
+ dns_db_attach(client->query.gluedb, &db);
+ result = dns_db_findext(db, name, version, type,
+ client->query.dboptions | DNS_DBFIND_GLUEOK,
+ client->now, &node, fname, &cm, &ci,
+ NULL, NULL);
+ if (!(result == ISC_R_SUCCESS ||
+ result == DNS_R_ZONECUT ||
+ result == DNS_R_GLUE)) {
+ /* cache the negative result */
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache,
+ NULL, db, version, NULL,
+ fname);
+ goto cleanup;
+ }
+
+ found:
+ /*
+ * We have found a DB node to iterate over from a DB.
+ * We are going to look for address RRsets (i.e., A and AAAA) in the DB
+ * node we've just found. We'll then store the complete information
+ * in the additional data cache.
+ */
+ dns_name_clone(fname, &cfname);
+ query_keepname(client, fname, dbuf);
+ needadditionalcache = true;
+
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ goto cleanup;
+
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+
+ if (additionaltype == dns_rdatasetadditional_fromcache &&
+ query_isduplicate(client, fname, dns_rdatatype_a, NULL))
+ goto aaaa_lookup;
+ /*
+ * Find A RRset with sig RRset. Even if we don't find a sig RRset
+ * for a client using DNSSEC, we'll continue the process to make a
+ * complete list to be cached. However, we need to cancel the
+ * caching when something unexpected happens, in order to avoid
+ * caching incomplete information.
+ */
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0,
+ client->now, rdataset, sigrdataset);
+
+ /*
+ * Try to promote pending/glue from the cache to secure.
+ * If unable to do so, drop it from the response unless
+ * it's glue, in which case it may still be needed.
+ */
+ invalid = false;
+ if (result == ISC_R_SUCCESS &&
+ additionaltype == dns_rdatasetadditional_fromcache &&
+ (DNS_TRUST_PENDING(rdataset->trust) ||
+ DNS_TRUST_GLUE(rdataset->trust)))
+ {
+ invalid = !validate(client, db, fname,
+ rdataset, sigrdataset);
+ }
+ if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ result = ISC_R_NOTFOUND;
+ }
+ if (result == DNS_R_NCACHENXDOMAIN)
+ goto setcache;
+ if (result == DNS_R_NCACHENXRRSET) {
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ if (result == ISC_R_SUCCESS) {
+ /* Remember the result as a cache */
+ ISC_LIST_APPEND(cfname.list, rdataset, link);
+ if (dns_rdataset_isassociated(sigrdataset)) {
+ ISC_LIST_APPEND(cfname.list, sigrdataset, link);
+ sigrdataset = query_newrdataset(client);
+ }
+ rdataset = query_newrdataset(client);
+ if (sigrdataset == NULL || rdataset == NULL) {
+ /* do not cache incomplete information */
+ goto foundcache;
+ }
+ }
+
+ aaaa_lookup:
+ if (additionaltype == dns_rdatasetadditional_fromcache &&
+ query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
+ goto foundcache;
+ /* Find AAAA RRset with sig RRset */
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa,
+ 0, client->now, rdataset, sigrdataset);
+ /*
+ * Try to promote pending/glue from the cache to secure.
+ * If unable to do so, drop it from the response unless
+ * it's glue, in which case it may still be needed.
+ */
+ invalid = false;
+ if (result == ISC_R_SUCCESS &&
+ additionaltype == dns_rdatasetadditional_fromcache &&
+ (DNS_TRUST_PENDING(rdataset->trust) ||
+ DNS_TRUST_GLUE(rdataset->trust)))
+ {
+ invalid = !validate(client, db, fname,
+ rdataset, sigrdataset);
+ }
+ if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ result = ISC_R_NOTFOUND;
+ }
+ if (result == ISC_R_SUCCESS) {
+ ISC_LIST_APPEND(cfname.list, rdataset, link);
+ rdataset = NULL;
+ if (dns_rdataset_isassociated(sigrdataset)) {
+ ISC_LIST_APPEND(cfname.list, sigrdataset, link);
+ sigrdataset = NULL;
+ }
+ }
+
+ setcache:
+ /*
+ * Set the new result in the cache if required. We do not support
+ * caching additional data from a cache DB.
+ */
+ if (needadditionalcache == true &&
+ (additionaltype == dns_rdatasetadditional_fromauth ||
+ additionaltype == dns_rdatasetadditional_fromglue)) {
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache,
+ zone, db, version, node,
+ &cfname);
+ }
+
+ foundcache:
+ need_sigrrset = false;
+ mname0 = NULL;
+ for (crdataset = ISC_LIST_HEAD(cfname.list);
+ crdataset != NULL;
+ crdataset = crdataset_next) {
+ dns_name_t *mname;
+
+ crdataset_next = ISC_LIST_NEXT(crdataset, link);
+
+ mname = NULL;
+ if (crdataset->type == dns_rdatatype_a ||
+ crdataset->type == dns_rdatatype_aaaa) {
+ if (!query_isduplicate(client, fname, crdataset->type,
+ &mname)) {
+ if (mname != fname) {
+ if (mname != NULL) {
+ /*
+ * A different type of this name is
+ * already stored in the additional
+ * section. We'll reuse the name.
+ * Note that this should happen at most
+ * once. Otherwise, fname->link could
+ * leak below.
+ */
+ INSIST(mname0 == NULL);
+
+ query_releasename(client, &fname);
+ fname = mname;
+ mname0 = mname;
+ } else
+ need_addname = true;
+ }
+ ISC_LIST_UNLINK(cfname.list, crdataset, link);
+ ISC_LIST_APPEND(fname->list, crdataset, link);
+ added_something = true;
+ need_sigrrset = true;
+ } else
+ need_sigrrset = false;
+ } else if (crdataset->type == dns_rdatatype_rrsig &&
+ need_sigrrset && WANTDNSSEC(client)) {
+ ISC_LIST_UNLINK(cfname.list, crdataset, link);
+ ISC_LIST_APPEND(fname->list, crdataset, link);
+ added_something = true; /* just in case */
+ need_sigrrset = false;
+ }
+ }
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: addname");
+
+ /*
+ * If we haven't added anything, then we're done.
+ */
+ if (!added_something)
+ goto cleanup;
+
+ /*
+ * We may have added our rdatasets to an existing name, if so, then
+ * need_addname will be false. Whether we used an existing name
+ * or a new one, we must set fname to NULL to prevent cleanup.
+ */
+ if (need_addname)
+ dns_message_addname(client->message, fname,
+ DNS_SECTION_ADDITIONAL);
+ fname = NULL;
+
+ cleanup:
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: cleanup");
+
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ while ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) {
+ ISC_LIST_UNLINK(cfname.list, crdataset, link);
+ query_putrdataset(client, &crdataset);
+ }
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: done");
+ return (eresult);
+}
+
+static inline void
+query_addrdataset(ns_client_t *client, dns_name_t *fname,
+ dns_rdataset_t *rdataset)
+{
+ client_additionalctx_t additionalctx;
+
+ /*
+ * Add 'rdataset' and any pertinent additional data to
+ * 'fname', a name in the response message for 'client'.
+ */
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset");
+
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+
+ if (client->view->order != NULL)
+ rdataset->attributes |= dns_order_find(client->view->order,
+ fname, rdataset->type,
+ rdataset->rdclass);
+ rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
+
+ if (NOADDITIONAL(client))
+ return;
+
+ /*
+ * Add additional data.
+ *
+ * We don't care if dns_rdataset_additionaldata() fails.
+ */
+ additionalctx.client = client;
+ additionalctx.rdataset = rdataset;
+ (void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
+ &additionalctx);
+ CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset: done");
+}
+
+static isc_result_t
+query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf,
+ dns_section_t section)
+{
+ dns_name_t *name, *mname;
+ dns_rdata_t *dns64_rdata;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t *dns64_rdatalist;
+ dns_rdataset_t *dns64_rdataset;
+ dns_rdataset_t *mrdataset;
+ isc_buffer_t *buffer;
+ isc_region_t r;
+ isc_result_t result;
+ dns_view_t *view = client->view;
+ isc_netaddr_t netaddr;
+ dns_dns64_t *dns64;
+ unsigned int flags = 0;
+
+ /*%
+ * To the current response for 'client', add the answer RRset
+ * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
+ * owner name '*namep', to section 'section', unless they are
+ * already there. Also add any pertinent additional data.
+ *
+ * If 'dbuf' is not NULL, then '*namep' is the name whose data is
+ * stored in 'dbuf'. In this case, query_addrrset() guarantees that
+ * when it returns the name will either have been kept or released.
+ */
+ CTRACE(ISC_LOG_DEBUG(3), "query_dns64");
+ name = *namep;
+ mname = NULL;
+ mrdataset = NULL;
+ buffer = NULL;
+ dns64_rdata = NULL;
+ dns64_rdataset = NULL;
+ dns64_rdatalist = NULL;
+ result = dns_message_findname(client->message, section,
+ name, dns_rdatatype_aaaa,
+ rdataset->covers,
+ &mname, &mrdataset);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got an RRset of the given name and type.
+ * There's nothing else to do;
+ */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_dns64: dns_message_findname succeeded: done");
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ return (ISC_R_SUCCESS);
+ } else if (result == DNS_R_NXDOMAIN) {
+ /*
+ * The name doesn't exist.
+ */
+ if (dbuf != NULL)
+ query_keepname(client, name, dbuf);
+ dns_message_addname(client->message, name, section);
+ *namep = NULL;
+ mname = name;
+ } else {
+ RUNTIME_CHECK(result == DNS_R_NXRRSET);
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ }
+
+ if (rdataset->trust != dns_trust_secure &&
+ (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY))
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+ result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt *
+ 16 * dns_rdataset_count(rdataset));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdataset(client->message, &dns64_rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdatalist(client->message,
+ &dns64_rdatalist);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_rdatalist_init(dns64_rdatalist);
+ dns64_rdatalist->rdclass = dns_rdataclass_in;
+ dns64_rdatalist->type = dns_rdatatype_aaaa;
+ if (client->query.dns64_ttl != UINT32_MAX)
+ dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl,
+ client->query.dns64_ttl);
+ else
+ dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600);
+
+ if (RECURSIONOK(client))
+ flags |= DNS_DNS64_RECURSIVE;
+
+ /*
+ * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
+ * as this provides a easy way to see if the answer was signed.
+ */
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ flags |= DNS_DNS64_DNSSEC;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ for (dns64 = ISC_LIST_HEAD(client->view->dns64);
+ dns64 != NULL; dns64 = dns_dns64_next(dns64)) {
+
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_availableregion(buffer, &r);
+ INSIST(r.length >= 16);
+ result = dns_dns64_aaaafroma(dns64, &netaddr,
+ client->signer,
+ &ns_g_server->aclenv,
+ flags, rdata.data, r.base);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+ isc_buffer_add(buffer, 16);
+ isc_buffer_remainingregion(buffer, &r);
+ isc_buffer_forward(buffer, 16);
+ result = dns_message_gettemprdata(client->message,
+ &dns64_rdata);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdata_init(dns64_rdata);
+ dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
+ dns_rdatatype_aaaa, &r);
+ ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
+ link);
+ dns64_rdata = NULL;
+ dns_rdata_reset(&rdata);
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup;
+
+ if (ISC_LIST_EMPTY(dns64_rdatalist->rdata))
+ goto cleanup;
+
+ result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdataset_setownercase(dns64_rdataset, mname);
+ client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
+ dns64_rdataset->trust = rdataset->trust;
+ query_addrdataset(client, mname, dns64_rdataset);
+ dns64_rdataset = NULL;
+ dns64_rdatalist = NULL;
+ dns_message_takebuffer(client->message, &buffer);
+ inc_stats(client, dns_nsstatscounter_dns64);
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (buffer != NULL)
+ isc_buffer_free(&buffer);
+
+ if (dns64_rdata != NULL)
+ dns_message_puttemprdata(client->message, &dns64_rdata);
+
+ if (dns64_rdataset != NULL)
+ dns_message_puttemprdataset(client->message, &dns64_rdataset);
+
+ if (dns64_rdatalist != NULL) {
+ for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
+ dns64_rdata != NULL;
+ dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
+ {
+ ISC_LIST_UNLINK(dns64_rdatalist->rdata,
+ dns64_rdata, link);
+ dns_message_puttemprdata(client->message, &dns64_rdata);
+ }
+ dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
+ }
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done");
+ return (result);
+}
+
+static void
+query_filter64(ns_client_t *client, dns_name_t **namep,
+ dns_rdataset_t *rdataset, isc_buffer_t *dbuf,
+ dns_section_t section)
+{
+ dns_name_t *name, *mname;
+ dns_rdata_t *myrdata;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t *myrdatalist;
+ dns_rdataset_t *myrdataset;
+ isc_buffer_t *buffer;
+ isc_region_t r;
+ isc_result_t result;
+ unsigned int i;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_filter64");
+
+ INSIST(client->query.dns64_aaaaok != NULL);
+ INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
+
+ name = *namep;
+ mname = NULL;
+ buffer = NULL;
+ myrdata = NULL;
+ myrdataset = NULL;
+ myrdatalist = NULL;
+ result = dns_message_findname(client->message, section,
+ name, dns_rdatatype_aaaa,
+ rdataset->covers,
+ &mname, &myrdataset);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got an RRset of the given name and type.
+ * There's nothing else to do;
+ */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_filter64: dns_message_findname succeeded: done");
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ return;
+ } else if (result == DNS_R_NXDOMAIN) {
+ mname = name;
+ *namep = NULL;
+ } else {
+ RUNTIME_CHECK(result == DNS_R_NXRRSET);
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ dbuf = NULL;
+ }
+
+ if (rdataset->trust != dns_trust_secure &&
+ (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY))
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+
+ result = isc_buffer_allocate(client->mctx, &buffer,
+ 16 * dns_rdataset_count(rdataset));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdataset(client->message, &myrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdatalist(client->message, &myrdatalist);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_rdatalist_init(myrdatalist);
+ myrdatalist->rdclass = dns_rdataclass_in;
+ myrdatalist->type = dns_rdatatype_aaaa;
+ myrdatalist->ttl = rdataset->ttl;
+
+ i = 0;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ if (!client->query.dns64_aaaaok[i++])
+ continue;
+ dns_rdataset_current(rdataset, &rdata);
+ INSIST(rdata.length == 16);
+ isc_buffer_putmem(buffer, rdata.data, rdata.length);
+ isc_buffer_remainingregion(buffer, &r);
+ isc_buffer_forward(buffer, rdata.length);
+ result = dns_message_gettemprdata(client->message, &myrdata);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdata_init(myrdata);
+ dns_rdata_fromregion(myrdata, dns_rdataclass_in,
+ dns_rdatatype_aaaa, &r);
+ ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
+ myrdata = NULL;
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup;
+
+ result = dns_rdatalist_tordataset(myrdatalist, myrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdataset_setownercase(myrdataset, name);
+ client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
+ if (mname == name) {
+ if (dbuf != NULL)
+ query_keepname(client, name, dbuf);
+ dns_message_addname(client->message, name, section);
+ dbuf = NULL;
+ }
+ myrdataset->trust = rdataset->trust;
+ query_addrdataset(client, mname, myrdataset);
+ myrdataset = NULL;
+ myrdatalist = NULL;
+ dns_message_takebuffer(client->message, &buffer);
+
+ cleanup:
+ if (buffer != NULL)
+ isc_buffer_free(&buffer);
+
+ if (myrdata != NULL)
+ dns_message_puttemprdata(client->message, &myrdata);
+
+ if (myrdataset != NULL)
+ dns_message_puttemprdataset(client->message, &myrdataset);
+
+ if (myrdatalist != NULL) {
+ for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
+ myrdata != NULL;
+ myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
+ {
+ ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
+ dns_message_puttemprdata(client->message, &myrdata);
+ }
+ dns_message_puttemprdatalist(client->message, &myrdatalist);
+ }
+ if (dbuf != NULL)
+ query_releasename(client, &name);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done");
+}
+
+static void
+query_addrrset(ns_client_t *client, dns_name_t **namep,
+ dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
+ isc_buffer_t *dbuf, dns_section_t section)
+{
+ dns_name_t *name, *mname;
+ dns_rdataset_t *rdataset, *mrdataset, *sigrdataset;
+ isc_result_t result;
+
+ /*%
+ * To the current response for 'client', add the answer RRset
+ * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
+ * owner name '*namep', to section 'section', unless they are
+ * already there. Also add any pertinent additional data.
+ *
+ * If 'dbuf' is not NULL, then '*namep' is the name whose data is
+ * stored in 'dbuf'. In this case, query_addrrset() guarantees that
+ * when it returns the name will either have been kept or released.
+ */
+ CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
+ name = *namep;
+ rdataset = *rdatasetp;
+ if (sigrdatasetp != NULL)
+ sigrdataset = *sigrdatasetp;
+ else
+ sigrdataset = NULL;
+ mname = NULL;
+ mrdataset = NULL;
+ result = dns_message_findname(client->message, section,
+ name, rdataset->type, rdataset->covers,
+ &mname, &mrdataset);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got an RRset of the given name and type.
+ */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addrrset: dns_message_findname succeeded: done");
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
+ mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
+ return;
+ } else if (result == DNS_R_NXDOMAIN) {
+ /*
+ * The name doesn't exist.
+ */
+ if (dbuf != NULL)
+ query_keepname(client, name, dbuf);
+ dns_message_addname(client->message, name, section);
+ *namep = NULL;
+ mname = name;
+ } else {
+ RUNTIME_CHECK(result == DNS_R_NXRRSET);
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ }
+
+ if (rdataset->trust != dns_trust_secure &&
+ (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY))
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+ /*
+ * Note: we only add SIGs if we've added the type they cover, so
+ * we do not need to check if the SIG rdataset is already in the
+ * response.
+ */
+ query_addrdataset(client, mname, rdataset);
+ *rdatasetp = NULL;
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
+ /*
+ * We have a signature. Add it to the response.
+ */
+ ISC_LIST_APPEND(mname->list, sigrdataset, link);
+ *sigrdatasetp = NULL;
+ }
+ CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
+}
+
+static inline isc_result_t
+query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
+ unsigned int override_ttl, bool isassociated,
+ dns_section_t section)
+{
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ isc_result_t result, eresult;
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+ dns_rdataset_t **sigrdatasetp = NULL;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addsoa");
+ /*
+ * Initialization.
+ */
+ eresult = ISC_R_SUCCESS;
+ name = NULL;
+ rdataset = NULL;
+ node = NULL;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Don't add the SOA record for test which set "-T nosoa".
+ */
+ if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated))
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Get resources and make 'name' be the database origin.
+ */
+ result = dns_message_gettempname(client->message, &name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_init(name, NULL);
+ dns_name_clone(dns_db_origin(db), name);
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL) {
+ CTRACE(ISC_LOG_ERROR, "unable to allocate rdataset");
+ eresult = DNS_R_SERVFAIL;
+ goto cleanup;
+ }
+ if (WANTDNSSEC(client) && dns_db_issecure(db)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ CTRACE(ISC_LOG_ERROR, "unable to allocate sigrdataset");
+ eresult = DNS_R_SERVFAIL;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Find the SOA.
+ */
+ result = dns_db_getoriginnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_soa, 0, client->now,
+ rdataset, sigrdataset);
+ } else {
+ dns_fixedname_t foundname;
+ dns_name_t *fname;
+
+ fname = dns_fixedname_initname(&foundname);
+
+ result = dns_db_findext(db, name, version, dns_rdatatype_soa,
+ client->query.dboptions, 0, &node,
+ fname, &cm, &ci, rdataset, sigrdataset);
+ }
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * This is bad. We tried to get the SOA RR at the zone top
+ * and it didn't work!
+ */
+ CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex");
+ eresult = DNS_R_SERVFAIL;
+ } else {
+ /*
+ * Extract the SOA MINIMUM.
+ */
+ dns_rdata_soa_t soa;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ result = dns_rdataset_first(rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (override_ttl != UINT32_MAX &&
+ override_ttl < rdataset->ttl) {
+ rdataset->ttl = override_ttl;
+ if (sigrdataset != NULL)
+ sigrdataset->ttl = override_ttl;
+ }
+
+ /*
+ * Add the SOA and its SIG to the response, with the
+ * TTLs adjusted per RFC2308 section 3.
+ */
+ if (rdataset->ttl > soa.minimum)
+ rdataset->ttl = soa.minimum;
+ if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
+ sigrdataset->ttl = soa.minimum;
+
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+
+ if (section == DNS_SECTION_ADDITIONAL)
+ rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
+ query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
+ section);
+ }
+
+ cleanup:
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (name != NULL)
+ query_releasename(client, &name);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ return (eresult);
+}
+
+static inline isc_result_t
+query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
+ dns_name_t *name, *fname;
+ dns_dbnode_t *node;
+ isc_result_t result, eresult;
+ dns_fixedname_t foundname;
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+ dns_rdataset_t **sigrdatasetp = NULL;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addns");
+ /*
+ * Initialization.
+ */
+ eresult = ISC_R_SUCCESS;
+ name = NULL;
+ rdataset = NULL;
+ node = NULL;
+ fname = dns_fixedname_initname(&foundname);
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Get resources and make 'name' be the database origin.
+ */
+ result = dns_message_gettempname(client->message, &name);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "query_addns: dns_message_gettempname failed: done");
+ return (result);
+ }
+ dns_name_init(name, NULL);
+ dns_name_clone(dns_db_origin(db), name);
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_addns: query_newrdataset failed");
+ eresult = DNS_R_SERVFAIL;
+ goto cleanup;
+ }
+ if (WANTDNSSEC(client) && dns_db_issecure(db)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_addns: query_newrdataset failed");
+ eresult = DNS_R_SERVFAIL;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Find the NS rdataset.
+ */
+ result = dns_db_getoriginnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_ns, 0, client->now,
+ rdataset, sigrdataset);
+ } else {
+ CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find");
+ result = dns_db_findext(db, name, NULL, dns_rdatatype_ns,
+ client->query.dboptions, 0, &node,
+ fname, &cm, &ci, rdataset, sigrdataset);
+ CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete");
+ }
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_addns: "
+ "dns_db_findrdataset or dns_db_find failed");
+ /*
+ * This is bad. We tried to get the NS rdataset at the zone
+ * top and it didn't work!
+ */
+ eresult = DNS_R_SERVFAIL;
+ } else {
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
+ DNS_SECTION_AUTHORITY);
+ }
+
+ cleanup:
+ CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup");
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (name != NULL)
+ query_releasename(client, &name);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
+ return (eresult);
+}
+static isc_result_t
+query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
+ dns_trust_t trust, dns_ttl_t ttl)
+{
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ isc_region_t r;
+ dns_name_t *aname;
+ isc_result_t result;
+
+ /*
+ * We assume the name data referred to by tname won't go away.
+ */
+
+ aname = NULL;
+ result = dns_message_gettempname(client->message, &aname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_name_dup(qname, client->mctx, aname);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
+ return (result);
+ }
+
+ rdatalist = NULL;
+ result = dns_message_gettemprdatalist(client->message, &rdatalist);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
+ return (result);
+ }
+ rdata = NULL;
+ result = dns_message_gettemprdata(client->message, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
+ dns_message_puttemprdatalist(client->message, &rdatalist);
+ return (result);
+ }
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(client->message, &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
+ dns_message_puttemprdatalist(client->message, &rdatalist);
+ dns_message_puttemprdata(client->message, &rdata);
+ return (result);
+ }
+ rdatalist->type = dns_rdatatype_cname;
+ rdatalist->rdclass = client->message->rdclass;
+ rdatalist->ttl = ttl;
+
+ dns_name_toregion(tname, &r);
+ rdata->data = r.base;
+ rdata->length = r.length;
+ rdata->rdclass = client->message->rdclass;
+ rdata->type = dns_rdatatype_cname;
+
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
+ == ISC_R_SUCCESS);
+ rdataset->trust = trust;
+ dns_rdataset_setownercase(rdataset, aname);
+
+ query_addrrset(client, &aname, &rdataset, NULL, NULL,
+ DNS_SECTION_ANSWER);
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(client->message, &rdataset);
+ }
+ if (aname != NULL)
+ dns_message_puttempname(client->message, &aname);
+
+ return (ISC_R_SUCCESS);
+}
+
+static bool
+get_root_key_sentinel_id(ns_client_t *client, const char *ndata) {
+ unsigned int v = 0;
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ if (ndata[i] < '0' || ndata[i] > '9') {
+ return (false);
+ }
+ v *= 10;
+ v += ndata[i] - '0';
+ }
+ if (v > 65535U) {
+ return (false);
+ }
+ client->query.root_key_sentinel_keyid = v;
+ return (true);
+}
+
+/*%
+ * Find out if the query is for a root key sentinel and if so, record the type
+ * of root key sentinel query and the key id that is being checked for.
+ *
+ * The code is assuming a zero padded decimal field of width 5.
+ */
+static void
+root_key_sentinel_detect(ns_client_t *client) {
+ const char *ndata = (const char *)client->query.qname->ndata;
+
+ if (client->query.qname->length > 30 && ndata[0] == 29 &&
+ strncasecmp(ndata + 1, "root-key-sentinel-is-ta-", 24) == 0)
+ {
+ if (!get_root_key_sentinel_id(client, ndata + 25)) {
+ return;
+ }
+ client->query.root_key_sentinel_is_ta = true;
+ ns_client_log(client, NS_LOGCATEGORY_TAT,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "root-key-sentinel-is-ta query label found");
+ } else if (client->query.qname->length > 31 && ndata[0] == 30 &&
+ strncasecmp(ndata + 1, "root-key-sentinel-not-ta-", 25) == 0)
+ {
+ if (!get_root_key_sentinel_id(client, ndata + 26)) {
+ return;
+ }
+ client->query.root_key_sentinel_not_ta = true;
+ ns_client_log(client, NS_LOGCATEGORY_TAT,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "root-key-sentinel-not-ta query label found");
+ }
+}
+
+/*
+ * Mark the RRsets as secure. Update the cache (db) to reflect the
+ * change in trust level.
+ */
+static void
+mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
+ dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ isc_stdtime_t now;
+
+ rdataset->trust = dns_trust_secure;
+ sigrdataset->trust = dns_trust_secure;
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Save the updated secure state. Ignore failures.
+ */
+ result = dns_db_findnodeext(db, name, true, &cm, &ci, &node);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ isc_stdtime_get(&now);
+ dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
+ client->view->acceptexpired);
+
+ (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
+ 0, NULL);
+ (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,
+ 0, NULL);
+ dns_db_detachnode(db, &node);
+}
+
+/*
+ * Find the secure key that corresponds to rrsig.
+ * Note: 'keyrdataset' maintains state between successive calls,
+ * there may be multiple keys with the same keyid.
+ * Return false if we have exhausted all the possible keys.
+ */
+static bool
+get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
+ dns_rdataset_t *keyrdataset, dst_key_t **keyp)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ bool secure = false;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ if (!dns_rdataset_isassociated(keyrdataset)) {
+ result = dns_db_findnodeext(db, &rrsig->signer, false,
+ &cm, &ci, &node);
+ if (result != ISC_R_SUCCESS)
+ return (false);
+
+ result = dns_db_findrdataset(db, node, NULL,
+ dns_rdatatype_dnskey, 0,
+ client->now, keyrdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (false);
+
+ if (keyrdataset->trust != dns_trust_secure)
+ return (false);
+
+ result = dns_rdataset_first(keyrdataset);
+ } else
+ result = dns_rdataset_next(keyrdataset);
+
+ for ( ; result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(keyrdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+
+ dns_rdataset_current(keyrdataset, &rdata);
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+ result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
+ client->mctx, keyp);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
+ rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
+ dst_key_iszonekey(*keyp)) {
+ secure = true;
+ break;
+ }
+ dst_key_free(keyp);
+ }
+ return (secure);
+}
+
+static bool
+verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdata_t *rdata, ns_client_t *client)
+{
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ bool ignore = false;
+
+ dns_fixedname_init(&fixed);
+
+again:
+ result = dns_dnssec_verify3(name, rdataset, key, ignore,
+ client->view->maxbits, client->mctx,
+ rdata, NULL);
+ if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) {
+ ignore = true;
+ goto again;
+ }
+ if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)
+ return (true);
+ return (false);
+}
+
+/*
+ * Validate the rdataset if possible with available records.
+ */
+static bool
+validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+ dst_key_t *key = NULL;
+ dns_rdataset_t keyrdataset;
+
+ if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
+ return (false);
+
+ for (result = dns_rdataset_first(sigrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(sigrdataset)) {
+
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(sigrdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (false);
+ if (!dns_resolver_algorithm_supported(client->view->resolver,
+ name, rrsig.algorithm))
+ continue;
+ if (!dns_name_issubdomain(name, &rrsig.signer))
+ continue;
+ dns_rdataset_init(&keyrdataset);
+ do {
+ if (!get_key(client, db, &rrsig, &keyrdataset, &key))
+ break;
+ if (verify(key, name, rdataset, &rdata, client)) {
+ dst_key_free(&key);
+ dns_rdataset_disassociate(&keyrdataset);
+ mark_secure(client, db, name, &rrsig,
+ rdataset, sigrdataset);
+ return (true);
+ }
+ dst_key_free(&key);
+ } while (1);
+ if (dns_rdataset_isassociated(&keyrdataset))
+ dns_rdataset_disassociate(&keyrdataset);
+ }
+ return (false);
+}
+
+static void
+query_addbestns(ns_client_t *client) {
+ dns_db_t *db, *zdb;
+ dns_dbnode_t *node;
+ dns_name_t *fname, *zfname;
+ dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
+ bool is_zone, use_zone;
+ isc_buffer_t *dbuf;
+ isc_result_t result;
+ dns_dbversion_t *version;
+ dns_zone_t *zone;
+ isc_buffer_t b;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
+ fname = NULL;
+ zfname = NULL;
+ rdataset = NULL;
+ zrdataset = NULL;
+ sigrdataset = NULL;
+ zsigrdataset = NULL;
+ node = NULL;
+ db = NULL;
+ zdb = NULL;
+ version = NULL;
+ zone = NULL;
+ is_zone = false;
+ use_zone = false;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Find the right database.
+ */
+ result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
+ &zone, &db, &version, &is_zone);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ db_find:
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL)
+ goto cleanup;
+ /*
+ * Get the RRSIGs if the client requested them or if we may
+ * need to validate answers from the cache.
+ */
+ if (WANTDNSSEC(client) || !is_zone) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+ }
+
+ /*
+ * Now look for the zonecut.
+ */
+ if (is_zone) {
+ result = dns_db_findext(db, client->query.qname, version,
+ dns_rdatatype_ns,
+ client->query.dboptions,
+ client->now, &node, fname,
+ &cm, &ci, rdataset, sigrdataset);
+ if (result != DNS_R_DELEGATION)
+ goto cleanup;
+ if (USECACHE(client)) {
+ query_keepname(client, fname, dbuf);
+ dns_db_detachnode(db, &node);
+ SAVE(zdb, db);
+ SAVE(zfname, fname);
+ SAVE(zrdataset, rdataset);
+ SAVE(zsigrdataset, sigrdataset);
+ version = NULL;
+ dns_db_attach(client->view->cachedb, &db);
+ is_zone = false;
+ goto db_find;
+ }
+ } else {
+ result = dns_db_findzonecut(db, client->query.qname,
+ client->query.dboptions,
+ client->now, &node, fname,
+ rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (zfname != NULL &&
+ !dns_name_issubdomain(fname, zfname)) {
+ /*
+ * We found a zonecut in the cache, but our
+ * zone delegation is better.
+ */
+ use_zone = true;
+ }
+ } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
+ /*
+ * We didn't find anything in the cache, but we
+ * have a zone delegation, so use it.
+ */
+ use_zone = true;
+ } else
+ goto cleanup;
+ }
+
+ if (use_zone) {
+ query_releasename(client, &fname);
+ /*
+ * We've already done query_keepname() on
+ * zfname, so we must set dbuf to NULL to
+ * prevent query_addrrset() from trying to
+ * call query_keepname() again.
+ */
+ dbuf = NULL;
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+
+ RESTORE(db, zdb);
+ RESTORE(fname, zfname);
+ RESTORE(rdataset, zrdataset);
+ RESTORE(sigrdataset, zsigrdataset);
+ }
+
+ /*
+ * Attempt to validate RRsets that are pending or that are glue.
+ */
+ if ((DNS_TRUST_PENDING(rdataset->trust) ||
+ (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust)))
+ && !validate(client, db, fname, rdataset, sigrdataset) &&
+ !PENDINGOK(client->query.dboptions))
+ goto cleanup;
+
+ if ((DNS_TRUST_GLUE(rdataset->trust) ||
+ (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
+ !validate(client, db, fname, rdataset, sigrdataset) &&
+ SECURE(client) && WANTDNSSEC(client))
+ goto cleanup;
+
+ /*
+ * If the answer is secure only add NS records if they are secure
+ * when the client may be looking for AD in the response.
+ */
+ if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) &&
+ ((rdataset->trust != dns_trust_secure) ||
+ (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure)))
+ goto cleanup;
+
+ /*
+ * If the client doesn't want DNSSEC we can discard the sigrdataset
+ * now.
+ */
+ if (!WANTDNSSEC(client))
+ query_putrdataset(client, &sigrdataset);
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ cleanup:
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (zdb != NULL) {
+ query_putrdataset(client, &zrdataset);
+ if (zsigrdataset != NULL)
+ query_putrdataset(client, &zsigrdataset);
+ if (zfname != NULL)
+ query_releasename(client, &zfname);
+ dns_db_detach(&zdb);
+ }
+}
+
+static void
+fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
+ if (*rdataset == NULL)
+ *rdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(*rdataset))
+ dns_rdataset_disassociate(*rdataset);
+}
+
+static void
+fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
+ isc_buffer_t *nbuf)
+{
+ if (*fname == NULL) {
+ *dbuf = query_getnamebuf(client);
+ if (*dbuf == NULL)
+ return;
+ *fname = query_newname(client, *dbuf, nbuf);
+ }
+}
+
+static void
+query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version, dns_name_t *name)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *fname = NULL;
+ dns_name_t *rname;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ isc_buffer_t *dbuf, b;
+ isc_result_t result;
+ unsigned int count;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addds");
+ rname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+
+ /*
+ * We'll need some resources...
+ */
+ rdataset = query_newrdataset(client);
+ sigrdataset = query_newrdataset(client);
+ if (rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+
+ /*
+ * Look for the DS record, which may or may not be present.
+ */
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0,
+ client->now, rdataset, sigrdataset);
+ /*
+ * If we didn't find it, look for an NSEC.
+ */
+ if (result == ISC_R_NOTFOUND)
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec, 0, client->now,
+ rdataset, sigrdataset);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto addnsec3;
+ if (!dns_rdataset_isassociated(rdataset) ||
+ !dns_rdataset_isassociated(sigrdataset))
+ goto addnsec3;
+
+ /*
+ * We've already added the NS record, so if the name's not there,
+ * we have other problems. Use this name rather than calling
+ * query_addrrset().
+ */
+ result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ rname = NULL;
+ dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
+ &rname);
+ result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ISC_LIST_APPEND(rname->list, rdataset, link);
+ ISC_LIST_APPEND(rname->list, sigrdataset, link);
+ rdataset = NULL;
+ sigrdataset = NULL;
+ return;
+
+ addnsec3:
+ if (!dns_db_iszone(db))
+ goto cleanup;
+ /*
+ * Add the NSEC3 which proves the DS does not exist.
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ dns_fixedname_init(&fixed);
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ query_findclosestnsec3(name, db, version, client, rdataset,
+ sigrdataset, fname, true,
+ dns_fixedname_name(&fixed));
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+ DNS_SECTION_AUTHORITY);
+ /*
+ * Did we find the closest provable encloser instead?
+ * If so add the nearest to the closest provable encloser.
+ */
+ if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
+ count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
+ dns_name_getlabelsequence(name,
+ dns_name_countlabels(name) - count,
+ count, dns_fixedname_name(&fixed));
+ fixfname(client, &fname, &dbuf, &b);
+ fixrdataset(client, &rdataset);
+ fixrdataset(client, &sigrdataset);
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+ query_findclosestnsec3(dns_fixedname_name(&fixed), db, version,
+ client, rdataset, sigrdataset, fname,
+ false, NULL);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+ DNS_SECTION_AUTHORITY);
+ }
+
+ cleanup:
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+}
+
+static void
+query_addwildcardproof(ns_client_t *client, dns_db_t *db,
+ dns_dbversion_t *version, dns_name_t *name,
+ bool ispositive, bool nodata)
+{
+ isc_buffer_t *dbuf, b;
+ dns_name_t *fname;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ dns_fixedname_t wfixed;
+ dns_name_t *wname;
+ dns_dbnode_t *node;
+ unsigned int options;
+ unsigned int olabels, nlabels, labels;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec_t nsec;
+ bool have_wname;
+ int order;
+ dns_fixedname_t cfixed;
+ dns_name_t *cname;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
+ fname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ node = NULL;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Get the NOQNAME proof then if !ispositive
+ * get the NOWILDCARD proof.
+ *
+ * DNS_DBFIND_NOWILD finds the NSEC records that covers the
+ * name ignoring any wildcard. From the owner and next names
+ * of this record you can compute which wildcard (if it exists)
+ * will match by finding the longest common suffix of the
+ * owner name and next names with the qname and prefixing that
+ * with the wildcard label.
+ *
+ * e.g.
+ * Given:
+ * example SOA
+ * example NSEC b.example
+ * b.example A
+ * b.example NSEC a.d.example
+ * a.d.example A
+ * a.d.example NSEC g.f.example
+ * g.f.example A
+ * g.f.example NSEC z.i.example
+ * z.i.example A
+ * z.i.example NSEC example
+ *
+ * QNAME:
+ * a.example -> example NSEC b.example
+ * owner common example
+ * next common example
+ * wild *.example
+ * d.b.example -> b.example NSEC a.d.example
+ * owner common b.example
+ * next common example
+ * wild *.b.example
+ * a.f.example -> a.d.example NSEC g.f.example
+ * owner common example
+ * next common f.example
+ * wild *.f.example
+ * j.example -> z.i.example NSEC example
+ * owner common example
+ * next common example
+ * wild *.example
+ */
+ options = client->query.dboptions | DNS_DBFIND_NOWILD;
+ wname = dns_fixedname_initname(&wfixed);
+ again:
+ have_wname = false;
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ sigrdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+
+ result = dns_db_findext(db, name, version, dns_rdatatype_nsec,
+ options, 0, &node, fname, &cm, &ci,
+ rdataset, sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ if (!dns_rdataset_isassociated(rdataset)) {
+ /*
+ * No NSEC proof available, return NSEC3 proofs instead.
+ */
+ cname = dns_fixedname_initname(&cfixed);
+ /*
+ * Find the closest encloser.
+ */
+ dns_name_copy(name, cname, NULL);
+ while (result == DNS_R_NXDOMAIN) {
+ labels = dns_name_countlabels(cname) - 1;
+ /*
+ * Sanity check.
+ */
+ if (labels == 0U)
+ goto cleanup;
+ dns_name_split(cname, labels, NULL, cname);
+ result = dns_db_findext(db, cname, version,
+ dns_rdatatype_nsec,
+ options, 0, NULL, fname,
+ &cm, &ci, NULL, NULL);
+ }
+ /*
+ * Add closest (provable) encloser NSEC3.
+ */
+ query_findclosestnsec3(cname, db, version, client, rdataset,
+ sigrdataset, fname, true, cname);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ if (!ispositive)
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+
+ /*
+ * Replace resources which were consumed by query_addrrset.
+ */
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ }
+
+ if (rdataset == NULL)
+ rdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ if (sigrdataset == NULL)
+ sigrdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+ /*
+ * Add no qname proof.
+ */
+ labels = dns_name_countlabels(cname) + 1;
+ if (dns_name_countlabels(name) == labels)
+ dns_name_copy(name, wname, NULL);
+ else
+ dns_name_split(name, labels, NULL, wname);
+
+ query_findclosestnsec3(wname, db, version, client, rdataset,
+ sigrdataset, fname, false, NULL);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+
+ if (ispositive)
+ goto cleanup;
+
+ /*
+ * Replace resources which were consumed by query_addrrset.
+ */
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ }
+
+ if (rdataset == NULL)
+ rdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ if (sigrdataset == NULL)
+ sigrdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+ /*
+ * Add the no wildcard proof.
+ */
+ result = dns_name_concatenate(dns_wildcardname,
+ cname, wname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ query_findclosestnsec3(wname, db, version, client, rdataset,
+ sigrdataset, fname, nodata, NULL);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+
+ goto cleanup;
+ } else if (result == DNS_R_NXDOMAIN) {
+ if (!ispositive)
+ result = dns_rdataset_first(rdataset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ }
+ if (result == ISC_R_SUCCESS) {
+ (void)dns_name_fullcompare(name, fname, &order,
+ &olabels);
+ (void)dns_name_fullcompare(name, &nsec.next, &order,
+ &nlabels);
+ /*
+ * Check for a pathological condition created when
+ * serving some malformed signed zones and bail out.
+ */
+ if (dns_name_countlabels(name) == nlabels)
+ goto cleanup;
+
+ if (olabels > nlabels)
+ dns_name_split(name, olabels, NULL, wname);
+ else
+ dns_name_split(name, nlabels, NULL, wname);
+ result = dns_name_concatenate(dns_wildcardname,
+ wname, wname, NULL);
+ if (result == ISC_R_SUCCESS)
+ have_wname = true;
+ dns_rdata_freestruct(&nsec);
+ }
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+ }
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (have_wname) {
+ ispositive = true; /* prevent loop */
+ if (!dns_name_equal(name, wname)) {
+ name = wname;
+ goto again;
+ }
+ }
+ cleanup:
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+}
+
+static void
+query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
+ dns_dbversion_t *version, dns_name_t **namep,
+ dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
+{
+ dns_name_t *name;
+ dns_rdataset_t *sigrdataset;
+ dns_rdata_t sigrdata;
+ dns_rdata_rrsig_t sig;
+ unsigned int labels;
+ isc_buffer_t *dbuf, b;
+ dns_name_t *fname;
+ isc_result_t result;
+
+ name = *namep;
+ if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
+ query_addrrset(client, namep, rdatasetp, sigrdatasetp,
+ NULL, DNS_SECTION_AUTHORITY);
+ return;
+ }
+
+ if (sigrdatasetp == NULL)
+ return;
+
+ sigrdataset = *sigrdatasetp;
+ if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
+ return;
+ result = dns_rdataset_first(sigrdataset);
+ if (result != ISC_R_SUCCESS)
+ return;
+ dns_rdata_init(&sigrdata);
+ dns_rdataset_current(sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ labels = dns_name_countlabels(name);
+ if ((unsigned int)sig.labels + 1 >= labels)
+ return;
+
+ /* XXX */
+ query_addwildcardproof(client, db, version, client->query.qname,
+ true, false);
+
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ return;
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL)
+ return;
+ dns_name_split(name, sig.labels + 1, NULL, fname);
+ /* This will succeed, since we've stripped labels. */
+ RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
+ NULL) == ISC_R_SUCCESS);
+ query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
+ dbuf, DNS_SECTION_AUTHORITY);
+}
+
+static void
+free_devent(ns_client_t *client, isc_event_t **eventp,
+ dns_fetchevent_t **deventp)
+{
+ dns_fetchevent_t *devent = *deventp;
+
+ REQUIRE((void*)(*eventp) == (void *)(*deventp));
+
+ if (devent->fetch != NULL)
+ dns_resolver_destroyfetch(&devent->fetch);
+ if (devent->node != NULL)
+ dns_db_detachnode(devent->db, &devent->node);
+ if (devent->db != NULL)
+ dns_db_detach(&devent->db);
+ if (devent->rdataset != NULL)
+ query_putrdataset(client, &devent->rdataset);
+ if (devent->sigrdataset != NULL)
+ query_putrdataset(client, &devent->sigrdataset);
+ /*
+ * If the two pointers are the same then leave the setting of
+ * (*deventp) to NULL to isc_event_free.
+ */
+ if ((void *)eventp != (void *)deventp)
+ (*deventp) = NULL;
+ isc_event_free(eventp);
+}
+
+/*%
+ * Check the configured trust anchors for a root zone trust anchor
+ * with a key id that matches client->query.root_key_sentinel_keyid.
+ *
+ * Return true when found, otherwise return false.
+ */
+static bool
+has_ta(ns_client_t *client) {
+ dns_keytable_t *keytable = NULL;
+ dns_keynode_t *keynode = NULL;
+ isc_result_t result;
+
+ result = dns_view_getsecroots(client->view, &keytable);
+ if (result != ISC_R_SUCCESS) {
+ return (false);
+ }
+
+ result = dns_keytable_find(keytable, dns_rootname, &keynode);
+ while (result == ISC_R_SUCCESS) {
+ dns_keynode_t *nextnode = NULL;
+ dns_keytag_t keyid = dst_key_id(dns_keynode_key(keynode));
+ if (keyid == client->query.root_key_sentinel_keyid) {
+ dns_keytable_detachkeynode(keytable, &keynode);
+ dns_keytable_detach(&keytable);
+ return (true);
+ }
+ result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
+ dns_keytable_detachkeynode(keytable, &keynode);
+ keynode = nextnode;
+ }
+ dns_keytable_detach(&keytable);
+
+ return (false);
+}
+
+/*%
+ * Check if a root key sentinel SERVFAIL should be returned.
+ */
+static bool
+root_key_sentinel_return_servfail(ns_client_t *client, bool is_zone,
+ dns_rdataset_t *rdataset, isc_result_t result)
+{
+ /*
+ * Are we looking at a "root-key-sentinel" query?
+ */
+ if (!client->query.root_key_sentinel_is_ta &&
+ !client->query.root_key_sentinel_not_ta)
+ {
+ return (false);
+ }
+
+ /*
+ * We only care about the query if 'result' indicates we have a cached
+ * answer.
+ */
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ break;
+ default:
+ return (false);
+ }
+
+ /*
+ * Do we meet the specified conditions to return SERVFAIL?
+ */
+ if (!is_zone && rdataset->trust == dns_trust_secure &&
+ ((client->query.root_key_sentinel_is_ta && !has_ta(client)) ||
+ (client->query.root_key_sentinel_not_ta && has_ta(client))))
+ {
+ return (true);
+ }
+
+ /*
+ * As special processing may only be triggered by the original QNAME,
+ * disable it after following a CNAME/DNAME.
+ */
+ client->query.root_key_sentinel_is_ta = false;
+ client->query.root_key_sentinel_not_ta = false;
+
+ return (false);
+}
+
+static void
+query_resume(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
+ dns_fetch_t *fetch = NULL;
+ ns_client_t *client;
+ bool fetch_canceled, client_shuttingdown;
+ isc_result_t result;
+ isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_ERRORS;
+ int errorloglevel;
+
+ /*
+ * Resume a query after recursion.
+ */
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ client = devent->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(RECURSING(client));
+
+ LOCK(&client->query.fetchlock);
+ if (client->query.fetch != NULL) {
+ /*
+ * This is the fetch we've been waiting for.
+ */
+ INSIST(devent->fetch == client->query.fetch);
+ client->query.fetch = NULL;
+ fetch_canceled = false;
+ /*
+ * Update client->now.
+ */
+ isc_stdtime_get(&client->now);
+ } else {
+ /*
+ * This is a fetch completion event for a canceled fetch.
+ * Clean up and don't resume the find.
+ */
+ fetch_canceled = true;
+ }
+ UNLOCK(&client->query.fetchlock);
+ INSIST(client->query.fetch == NULL);
+
+ client->query.attributes &= ~NS_QUERYATTR_RECURSING;
+ SAVE(fetch, devent->fetch);
+
+ /*
+ * If this client is shutting down, or this transaction
+ * has timed out, do not resume the find.
+ */
+ client_shuttingdown = ns_client_shuttingdown(client);
+ if (fetch_canceled || client_shuttingdown) {
+ free_devent(client, &event, &devent);
+ if (fetch_canceled) {
+ CTRACE(ISC_LOG_ERROR, "fetch cancelled");
+ query_error(client, DNS_R_SERVFAIL, __LINE__);
+ } else
+ query_next(client, ISC_R_CANCELED);
+ /*
+ * This may destroy the client.
+ */
+ ns_client_detach(&client);
+ } else {
+ result = query_find(client, devent, 0);
+ if (result != ISC_R_SUCCESS) {
+ if (result == DNS_R_SERVFAIL)
+ errorloglevel = ISC_LOG_DEBUG(2);
+ else
+ errorloglevel = ISC_LOG_DEBUG(4);
+ if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) {
+ dns_resolver_logfetch(fetch, ns_g_lctx,
+ logcategory,
+ NS_LOGMODULE_QUERY,
+ errorloglevel, false);
+ }
+ }
+ }
+
+ dns_resolver_destroyfetch(&fetch);
+}
+
+static void
+prefetch_done(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
+ ns_client_t *client;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ client = devent->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+
+ LOCK(&client->query.fetchlock);
+ if (client->query.prefetch != NULL) {
+ INSIST(devent->fetch == client->query.prefetch);
+ client->query.prefetch = NULL;
+ }
+ UNLOCK(&client->query.fetchlock);
+ free_devent(client, &event, &devent);
+ ns_client_detach(&client);
+}
+
+static void
+query_prefetch(ns_client_t *client, dns_name_t *qname,
+ dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ isc_sockaddr_t *peeraddr;
+ dns_rdataset_t *tmprdataset;
+ ns_client_t *dummy = NULL;
+ unsigned int options;
+
+ if (client->query.prefetch != NULL ||
+ client->view->prefetch_trigger == 0U ||
+ rdataset->ttl > client->view->prefetch_trigger ||
+ (rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0)
+ return;
+
+ if (client->recursionquota == NULL) {
+ result = isc_quota_attach(&ns_g_server->recursionquota,
+ &client->recursionquota);
+ if (result == ISC_R_SUCCESS && !client->mortal && !TCP(client))
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS)
+ return;
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_recursclients);
+ }
+
+ tmprdataset = query_newrdataset(client);
+ if (tmprdataset == NULL)
+ return;
+ if (!TCP(client))
+ peeraddr = &client->peeraddr;
+ else
+ peeraddr = NULL;
+ ns_client_attach(client, &dummy);
+ options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
+ result = dns_resolver_createfetch3(client->view->resolver,
+ qname, rdataset->type, NULL, NULL,
+ NULL, peeraddr, client->message->id,
+ options, 0, NULL, client->task,
+ prefetch_done, client,
+ tmprdataset, NULL,
+ &client->query.prefetch);
+ if (result != ISC_R_SUCCESS) {
+ query_putrdataset(client, &tmprdataset);
+ ns_client_detach(&dummy);
+ }
+ dns_rdataset_clearprefetch(rdataset);
+}
+
+static isc_result_t
+query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
+ dns_name_t *qdomain, dns_rdataset_t *nameservers,
+ bool resuming)
+{
+ isc_result_t result;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ isc_sockaddr_t *peeraddr;
+
+ if (!resuming)
+ inc_stats(client, dns_nsstatscounter_recursion);
+
+ /*
+ * We are about to recurse, which means that this client will
+ * be unavailable for serving new requests for an indeterminate
+ * amount of time. If this client is currently responsible
+ * for handling incoming queries, set up a new client
+ * object to handle them while we are waiting for a
+ * response. There is no need to replace TCP clients
+ * because those have already been replaced when the
+ * connection was accepted (if allowed by the TCP quota).
+ */
+ if (client->recursionquota == NULL) {
+ result = isc_quota_attach(&ns_g_server->recursionquota,
+ &client->recursionquota);
+
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_recursclients);
+
+ if (result == ISC_R_SOFTQUOTA) {
+ static isc_stdtime_t last = 0;
+ isc_stdtime_t now;
+ isc_stdtime_get(&now);
+ if (now != last) {
+ last = now;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "recursive-clients soft limit "
+ "exceeded (%d/%d/%d), "
+ "aborting oldest query",
+ client->recursionquota->used,
+ client->recursionquota->soft,
+ client->recursionquota->max);
+ }
+ ns_client_killoldestquery(client);
+ result = ISC_R_SUCCESS;
+ } else if (result == ISC_R_QUOTA) {
+ static isc_stdtime_t last = 0;
+ isc_stdtime_t now;
+ isc_stdtime_get(&now);
+ if (now != last) {
+ last = now;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "no more recursive clients "
+ "(%d/%d/%d): %s",
+ ns_g_server->recursionquota.used,
+ ns_g_server->recursionquota.soft,
+ ns_g_server->recursionquota.max,
+ isc_result_totext(result));
+ }
+ ns_client_killoldestquery(client);
+ }
+ if (result == ISC_R_SUCCESS && !client->mortal &&
+ !TCP(client)) {
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "ns_client_replace() failed: %s",
+ isc_result_totext(result));
+ isc_quota_detach(&client->recursionquota);
+ isc_stats_decrement(ns_g_server->nsstats,
+ dns_nsstatscounter_recursclients);
+ }
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ ns_client_recursing(client);
+ }
+
+ /*
+ * Invoke the resolver.
+ */
+ REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
+ REQUIRE(client->query.fetch == NULL);
+
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ return (ISC_R_NOMEMORY);
+ if (WANTDNSSEC(client)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ query_putrdataset(client, &rdataset);
+ return (ISC_R_NOMEMORY);
+ }
+ } else
+ sigrdataset = NULL;
+
+ if (client->query.timerset == false)
+ ns_client_settimeout(client, 60);
+ if (!TCP(client))
+ peeraddr = &client->peeraddr;
+ else
+ peeraddr = NULL;
+ result = dns_resolver_createfetch3(client->view->resolver,
+ qname, qtype, qdomain, nameservers,
+ NULL, peeraddr, client->message->id,
+ client->query.fetchoptions, 0, NULL,
+ client->task, query_resume, client,
+ rdataset, sigrdataset,
+ &client->query.fetch);
+
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Record that we're waiting for an event. A client which
+ * is shutting down will not be destroyed until all the
+ * events have been received.
+ */
+ } else {
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ }
+
+ return (result);
+}
+
+static inline void
+rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
+ dns_rdataset_t **rdatasetp)
+{
+ if (nodep != NULL && *nodep != NULL) {
+ REQUIRE(dbp != NULL && *dbp != NULL);
+ dns_db_detachnode(*dbp, nodep);
+ }
+ if (dbp != NULL && *dbp != NULL)
+ dns_db_detach(dbp);
+ if (zonep != NULL && *zonep != NULL)
+ dns_zone_detach(zonep);
+ if (rdatasetp != NULL && *rdatasetp != NULL &&
+ dns_rdataset_isassociated(*rdatasetp))
+ dns_rdataset_disassociate(*rdatasetp);
+}
+
+static inline void
+rpz_match_clear(dns_rpz_st_t *st) {
+ rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
+ st->m.version = NULL;
+}
+
+static inline isc_result_t
+rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) {
+ REQUIRE(rdatasetp != NULL);
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_ready");
+
+ if (*rdatasetp == NULL) {
+ *rdatasetp = query_newrdataset(client);
+ if (*rdatasetp == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_ready: query_newrdataset failed");
+ return (DNS_R_SERVFAIL);
+ }
+ } else if (dns_rdataset_isassociated(*rdatasetp)) {
+ dns_rdataset_disassociate(*rdatasetp);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rpz_st_clear(ns_client_t *client) {
+ dns_rpz_st_t *st = client->query.rpz_st;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear");
+
+ if (st->m.rdataset != NULL)
+ query_putrdataset(client, &st->m.rdataset);
+ rpz_match_clear(st);
+
+ rpz_clean(NULL, &st->r.db, NULL, NULL);
+ if (st->r.ns_rdataset != NULL)
+ query_putrdataset(client, &st->r.ns_rdataset);
+ if (st->r.r_rdataset != NULL)
+ query_putrdataset(client, &st->r.r_rdataset);
+
+ rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
+ if (st->q.rdataset != NULL)
+ query_putrdataset(client, &st->q.rdataset);
+ if (st->q.sigrdataset != NULL)
+ query_putrdataset(client, &st->q.sigrdataset);
+ st->state = 0;
+ st->m.type = DNS_RPZ_TYPE_BAD;
+ st->m.policy = DNS_RPZ_POLICY_MISS;
+}
+
+static dns_rpz_zbits_t
+rpz_get_zbits(ns_client_t *client,
+ dns_rdatatype_t ip_type, dns_rpz_type_t rpz_type)
+{
+ dns_rpz_st_t *st;
+ dns_rpz_zbits_t zbits;
+
+ REQUIRE(client != NULL);
+ REQUIRE(client->query.rpz_st != NULL);
+
+ st = client->query.rpz_st;
+
+ switch (rpz_type) {
+ case DNS_RPZ_TYPE_CLIENT_IP:
+ zbits = st->have.client_ip;
+ break;
+ case DNS_RPZ_TYPE_QNAME:
+ zbits = st->have.qname;
+ break;
+ case DNS_RPZ_TYPE_IP:
+ if (ip_type == dns_rdatatype_a) {
+ zbits = st->have.ipv4;
+ } else if (ip_type == dns_rdatatype_aaaa) {
+ zbits = st->have.ipv6;
+ } else {
+ zbits = st->have.ip;
+ }
+ break;
+ case DNS_RPZ_TYPE_NSDNAME:
+ zbits = st->have.nsdname;
+ break;
+ case DNS_RPZ_TYPE_NSIP:
+ if (ip_type == dns_rdatatype_a) {
+ zbits = st->have.nsipv4;
+ } else if (ip_type == dns_rdatatype_aaaa) {
+ zbits = st->have.nsipv6;
+ } else {
+ zbits = st->have.nsip;
+ }
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+
+ /*
+ * Choose
+ * the earliest configured policy zone (rpz->num)
+ * QNAME over IP over NSDNAME over NSIP (rpz_type)
+ * the smallest name,
+ * the longest IP address prefix,
+ * the lexically smallest address.
+ */
+ if (st->m.policy != DNS_RPZ_POLICY_MISS) {
+ if (st->m.type >= rpz_type) {
+ zbits &= DNS_RPZ_ZMASK(st->m.rpz->num);
+ } else{
+ zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1;
+ }
+ }
+
+ /*
+ * If the client wants recursion, allow only compatible policies.
+ */
+ if (!RECURSIONOK(client))
+ zbits &= st->popt.no_rd_ok;
+
+ return (zbits);
+}
+
+static void
+query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
+ isc_result_t result;
+ isc_sockaddr_t *peeraddr;
+ dns_rdataset_t *tmprdataset;
+ ns_client_t *dummy = NULL;
+ unsigned int options;
+
+ if (client->query.prefetch != NULL)
+ return;
+
+ if (client->recursionquota == NULL) {
+ result = isc_quota_attach(&ns_g_server->recursionquota,
+ &client->recursionquota);
+ if (result == ISC_R_SUCCESS && !client->mortal && !TCP(client))
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS)
+ return;
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_recursclients);
+ }
+
+ tmprdataset = query_newrdataset(client);
+ if (tmprdataset == NULL)
+ return;
+ if (!TCP(client))
+ peeraddr = &client->peeraddr;
+ else
+ peeraddr = NULL;
+ ns_client_attach(client, &dummy);
+ options = client->query.fetchoptions;
+ result = dns_resolver_createfetch3(client->view->resolver, qname, type,
+ NULL, NULL, NULL, peeraddr,
+ client->message->id, options, 0,
+ NULL, client->task, prefetch_done,
+ client, tmprdataset, NULL,
+ &client->query.prefetch);
+ if (result != ISC_R_SUCCESS) {
+ query_putrdataset(client, &tmprdataset);
+ ns_client_detach(&dummy);
+ }
+}
+
+/*
+ * Get an NS, A, or AAAA rrset related to the response for the client
+ * to check the contents of that rrset for hits by eligible policy zones.
+ */
+static isc_result_t
+rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
+ dns_rpz_type_t rpz_type, dns_db_t **dbp,
+ dns_dbversion_t *version, dns_rdataset_t **rdatasetp,
+ bool resuming)
+{
+ dns_rpz_st_t *st;
+ bool is_zone;
+ dns_dbnode_t *node;
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ isc_result_t result;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rrset_find");
+
+ st = client->query.rpz_st;
+ if ((st->state & DNS_RPZ_RECURSING) != 0) {
+ INSIST(st->r.r_type == type);
+ INSIST(dns_name_equal(name, st->r_name));
+ INSIST(*rdatasetp == NULL ||
+ !dns_rdataset_isassociated(*rdatasetp));
+ st->state &= ~DNS_RPZ_RECURSING;
+ RESTORE(*dbp, st->r.db);
+ if (*rdatasetp != NULL)
+ query_putrdataset(client, rdatasetp);
+ RESTORE(*rdatasetp, st->r.r_rdataset);
+ result = st->r.r_result;
+ if (result == DNS_R_DELEGATION) {
+ CTRACE(ISC_LOG_ERROR, "RPZ recursing");
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
+ rpz_type, " rpz_rrset_find(1)", result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ result = DNS_R_SERVFAIL;
+ }
+ return (result);
+ }
+
+ result = rpz_ready(client, rdatasetp);
+ if (result != ISC_R_SUCCESS) {
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ return (result);
+ }
+ if (*dbp != NULL) {
+ is_zone = false;
+ } else {
+ dns_zone_t *zone;
+
+ version = NULL;
+ zone = NULL;
+ result = query_getdb(client, name, type, 0, &zone, dbp,
+ &version, &is_zone);
+ if (result != ISC_R_SUCCESS) {
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
+ rpz_type, " rpz_rrset_find(2)", result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ return (result);
+ }
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ }
+
+ node = NULL;
+ found = dns_fixedname_initname(&fixed);
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+ result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
+ client->now, &node, found,
+ &cm, &ci, *rdatasetp, NULL);
+ if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
+ /*
+ * Try the cache if we're authoritative for an
+ * ancestor but not the domain itself.
+ */
+ rpz_clean(NULL, dbp, &node, rdatasetp);
+ version = NULL;
+ dns_db_attach(client->view->cachedb, dbp);
+ result = dns_db_findext(*dbp, name, version, type,
+ 0, client->now, &node, found,
+ &cm, &ci, *rdatasetp, NULL);
+ }
+ rpz_clean(NULL, dbp, &node, NULL);
+ if (result == DNS_R_DELEGATION) {
+ rpz_clean(NULL, NULL, NULL, rdatasetp);
+ /*
+ * Recurse for NS rrset or A or AAAA rrset for an NS.
+ * Do not recurse for addresses for the query name.
+ */
+ if (rpz_type == DNS_RPZ_TYPE_IP) {
+ result = DNS_R_NXRRSET;
+ } else if (!client->view->rpzs->p.nsip_wait_recurse) {
+ query_rpzfetch(client, name, type);
+ result = DNS_R_NXRRSET;
+ } else {
+ dns_name_copy(name, st->r_name, NULL);
+ result = query_recurse(client, type, st->r_name,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS) {
+ st->state |= DNS_RPZ_RECURSING;
+ result = DNS_R_DELEGATION;
+ }
+ }
+ }
+ return (result);
+}
+
+/*
+ * Compute a policy owner name, p_name, in a policy zone given the needed
+ * policy type and the trigger name.
+ */
+static isc_result_t
+rpz_get_p_name(ns_client_t *client, dns_name_t *p_name,
+ dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_name_t *trig_name)
+{
+ dns_offsets_t prefix_offsets;
+ dns_name_t prefix, *suffix;
+ unsigned int first, labels;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_get_p_name");
+
+ /*
+ * The policy owner name consists of a suffix depending on the type
+ * and policy zone and a prefix that is the longest possible string
+ * from the trigger name that keesp the resulting policy owner name
+ * from being too long.
+ */
+ switch (rpz_type) {
+ case DNS_RPZ_TYPE_CLIENT_IP:
+ suffix = &rpz->client_ip;
+ break;
+ case DNS_RPZ_TYPE_QNAME:
+ suffix = &rpz->origin;
+ break;
+ case DNS_RPZ_TYPE_IP:
+ suffix = &rpz->ip;
+ break;
+ case DNS_RPZ_TYPE_NSDNAME:
+ suffix = &rpz->nsdname;
+ break;
+ case DNS_RPZ_TYPE_NSIP:
+ suffix = &rpz->nsip;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ /*
+ * Start with relative version of the full trigger name,
+ * and trim enough allow the addition of the suffix.
+ */
+ dns_name_init(&prefix, prefix_offsets);
+ labels = dns_name_countlabels(trig_name);
+ first = 0;
+ for (;;) {
+ dns_name_getlabelsequence(trig_name, first, labels-first-1,
+ &prefix);
+ result = dns_name_concatenate(&prefix, suffix, p_name, NULL);
+ if (result == ISC_R_SUCCESS)
+ break;
+ INSIST(result == DNS_R_NAMETOOLONG);
+ /*
+ * Trim the trigger name until the combination is not too long.
+ */
+ if (labels-first < 2) {
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix,
+ rpz_type, " concatentate()", result);
+ return (ISC_R_FAILURE);
+ }
+ /*
+ * Complain once about trimming the trigger name.
+ */
+ if (first == 0) {
+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix,
+ rpz_type, " concatentate()", result);
+ }
+ ++first;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Look in policy zone rpz for a policy of rpz_type by p_name.
+ * The self-name (usually the client qname or an NS name) is compared with
+ * the target of a CNAME policy for the old style passthru encoding.
+ * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep,
+ * *rdatasetp, and *policyp.
+ * The target DNS type, qtype, chooses the best rdataset for *rdatasetp.
+ * The caller must decide if the found policy is most suitable, including
+ * better than a previously found policy.
+ * If it is best, the caller records it in client->query.rpz_st->m.
+ */
+static isc_result_t
+rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
+ dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
+ dns_rpz_policy_t *policyp)
+{
+ dns_fixedname_t foundf;
+ dns_name_t *found;
+ isc_result_t result;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ REQUIRE(nodep != NULL);
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p");
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Try to find either a CNAME or the type of record demanded by the
+ * request from the policy zone.
+ */
+ rpz_clean(zonep, dbp, nodep, rdatasetp);
+ result = rpz_ready(client, rdatasetp);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_ERROR, "rpz_ready() failed");
+ return (DNS_R_SERVFAIL);
+ }
+ *versionp = NULL;
+ result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp);
+ if (result != ISC_R_SUCCESS)
+ return (DNS_R_NXDOMAIN);
+ found = dns_fixedname_initname(&foundf);
+
+ result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0,
+ client->now, nodep, found, &cm, &ci,
+ *rdatasetp, NULL);
+ /*
+ * Choose the best rdataset if we found something.
+ */
+ if (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_t *rdsiter;
+
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0,
+ &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name,
+ rpz_type, " allrdatasets()", result);
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_find_p: allrdatasets failed");
+ return (DNS_R_SERVFAIL);
+ }
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, *rdatasetp);
+ if ((*rdatasetp)->type == dns_rdatatype_cname ||
+ (*rdatasetp)->type == qtype)
+ break;
+ dns_rdataset_disassociate(*rdatasetp);
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_NOMORE) {
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
+ p_name, rpz_type,
+ " rdatasetiter", result);
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_find_p: rdatasetiter failed");
+ return (DNS_R_SERVFAIL);
+ }
+ /*
+ * Ask again to get the right DNS_R_DNAME/NXRRSET/...
+ * result if there is neither a CNAME nor target type.
+ */
+ if (dns_rdataset_isassociated(*rdatasetp))
+ dns_rdataset_disassociate(*rdatasetp);
+ dns_db_detachnode(*dbp, nodep);
+
+ if (qtype == dns_rdatatype_rrsig ||
+ qtype == dns_rdatatype_sig)
+ result = DNS_R_NXRRSET;
+ else
+ result = dns_db_findext(*dbp, p_name, *versionp,
+ qtype, 0, client->now,
+ nodep, found, &cm, &ci,
+ *rdatasetp, NULL);
+ }
+ }
+ switch (result) {
+ case ISC_R_SUCCESS:
+ if ((*rdatasetp)->type != dns_rdatatype_cname) {
+ *policyp = DNS_RPZ_POLICY_RECORD;
+ } else {
+ *policyp = dns_rpz_decode_cname(rpz, *rdatasetp,
+ self_name);
+ if ((*policyp == DNS_RPZ_POLICY_RECORD ||
+ *policyp == DNS_RPZ_POLICY_WILDCNAME) &&
+ qtype != dns_rdatatype_cname &&
+ qtype != dns_rdatatype_any)
+ return (DNS_R_CNAME);
+ }
+ return (ISC_R_SUCCESS);
+ case DNS_R_NXRRSET:
+ *policyp = DNS_RPZ_POLICY_NODATA;
+ return (result);
+ case DNS_R_DNAME:
+ /*
+ * DNAME policy RRs have very few if any uses that are not
+ * better served with simple wildcards. Making them work would
+ * require complications to get the number of labels matched
+ * in the name or the found name to the main DNS_R_DNAME case
+ * in query_find(). The domain also does not appear in the
+ * summary database at the right level, so this happens only
+ * with a single policy zone when we have no summary database.
+ * Treat it as a miss.
+ */
+ case DNS_R_NXDOMAIN:
+ case DNS_R_EMPTYNAME:
+ return (DNS_R_NXDOMAIN);
+ default:
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
+ "", result);
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_find_p: unexpected result");
+ return (DNS_R_SERVFAIL);
+ }
+}
+
+static void
+rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix,
+ isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
+ dns_dbversion_t *version)
+{
+ dns_rdataset_t *trdataset = NULL;
+
+ rpz_match_clear(st);
+ st->m.rpz = rpz;
+ st->m.type = rpz_type;
+ st->m.policy = policy;
+ dns_name_copy(p_name, st->p_name, NULL);
+ st->m.prefix = prefix;
+ st->m.result = result;
+ SAVE(st->m.zone, *zonep);
+ SAVE(st->m.db, *dbp);
+ SAVE(st->m.node, *nodep);
+ if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) {
+ /*
+ * Save the replacement rdataset from the policy
+ * and make the previous replacement rdataset scratch.
+ */
+ SAVE(trdataset, st->m.rdataset);
+ SAVE(st->m.rdataset, *rdatasetp);
+ SAVE(*rdatasetp, trdataset);
+ st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl);
+ } else {
+ st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl);
+ }
+ SAVE(st->m.version, version);
+}
+
+/*
+ * Check this address in every eligible policy zone.
+ */
+static isc_result_t
+rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
+ dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
+ dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp)
+{
+ dns_rpz_zones_t *rpzs;
+ dns_rpz_st_t *st;
+ dns_rpz_zone_t *rpz;
+ dns_rpz_prefix_t prefix;
+ dns_rpz_num_t rpz_num;
+ dns_fixedname_t ip_namef, p_namef;
+ dns_name_t *ip_name, *p_name;
+ dns_zone_t *p_zone;
+ dns_db_t *p_db;
+ dns_dbversion_t *p_version;
+ dns_dbnode_t *p_node;
+ dns_rpz_policy_t policy;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip");
+
+ ip_name = dns_fixedname_initname(&ip_namef);
+
+ p_zone = NULL;
+ p_db = NULL;
+ p_node = NULL;
+
+ rpzs = client->view->rpzs;
+ st = client->query.rpz_st;
+ while (zbits != 0) {
+ rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr,
+ ip_name, &prefix);
+ if (rpz_num == DNS_RPZ_INVALID_NUM)
+ break;
+ zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1);
+
+ /*
+ * Do not try applying policy zones that cannot replace a
+ * previously found policy zone.
+ * Stop looking if the next best choice cannot
+ * replace what we already have.
+ */
+ rpz = rpzs->zones[rpz_num];
+ if (st->m.policy != DNS_RPZ_POLICY_MISS) {
+ if (st->m.rpz->num < rpz->num)
+ break;
+ if (st->m.rpz->num == rpz->num &&
+ (st->m.type < rpz_type ||
+ st->m.prefix > prefix))
+ break;
+ }
+
+ /*
+ * Get the policy for a prefix at least as long
+ * as the prefix of the entry we had before.
+ */
+ p_name = dns_fixedname_initname(&p_namef);
+ result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = rpz_find_p(client, ip_name, qtype,
+ p_name, rpz, rpz_type,
+ &p_zone, &p_db, &p_version, &p_node,
+ p_rdatasetp, &policy);
+ switch (result) {
+ case DNS_R_NXDOMAIN:
+ /*
+ * Continue after a policy record that is missing
+ * contrary to the summary data. The summary
+ * data can out of date during races with and among
+ * policy zone updates.
+ */
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_rewrite_ip: mismatched summary data; "
+ "continuing");
+ continue;
+ case DNS_R_SERVFAIL:
+ rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ return (DNS_R_SERVFAIL);
+ default:
+ /*
+ * Forget this policy if it is not preferable
+ * to the previously found policy.
+ * If this policy is not good, then stop looking
+ * because none of the later policy zones would work.
+ *
+ * With more than one applicable policy, prefer
+ * the earliest configured policy,
+ * client-IP over QNAME over IP over NSDNAME over NSIP,
+ * the longest prefix
+ * the lexically smallest address.
+ * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num.
+ * We can compare new and current p_name because
+ * both are of the same type and in the same zone.
+ * The tests above eliminate other reasons to
+ * reject this policy. If this policy can't work,
+ * then neither can later zones.
+ */
+ if (st->m.policy != DNS_RPZ_POLICY_MISS &&
+ rpz->num == st->m.rpz->num &&
+ (st->m.type == rpz_type &&
+ st->m.prefix == prefix &&
+ 0 > dns_name_rdatacompare(st->p_name, p_name)))
+ break;
+
+ /*
+ * Stop checking after saving an enabled hit in this
+ * policy zone. The radix tree in the policy zone
+ * ensures that we found the longest match.
+ */
+ if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "rpz_rewrite_ip: rpz_save_p");
+ rpz_save_p(st, rpz, rpz_type,
+ policy, p_name, prefix, result,
+ &p_zone, &p_db, &p_node,
+ p_rdatasetp, p_version);
+ break;
+ }
+
+ /*
+ * Log DNS_RPZ_POLICY_DISABLED zones
+ * and try the next eligible policy zone.
+ */
+ rpz_log_rewrite(client, true, policy, rpz_type,
+ p_zone, p_name, NULL, rpz_num);
+ }
+ }
+
+ rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Check the IP addresses in the A or AAAA rrsets for name against
+ * all eligible rpz_type (IP or NSIP) response policy rewrite rules.
+ */
+static isc_result_t
+rpz_rewrite_ip_rrset(ns_client_t *client,
+ dns_name_t *name, dns_rdatatype_t qtype,
+ dns_rpz_type_t rpz_type, dns_rdatatype_t ip_type,
+ dns_db_t **ip_dbp, dns_dbversion_t *ip_version,
+ dns_rdataset_t **ip_rdatasetp,
+ dns_rdataset_t **p_rdatasetp, bool resuming)
+{
+ dns_rpz_zbits_t zbits;
+ isc_netaddr_t netaddr;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset");
+
+ zbits = rpz_get_zbits(client, ip_type, rpz_type);
+ if (zbits == 0)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Get the A or AAAA rdataset.
+ */
+ result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp,
+ ip_version, ip_rdatasetp, resuming);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_GLUE:
+ case DNS_R_ZONECUT:
+ break;
+ case DNS_R_EMPTYNAME:
+ case DNS_R_EMPTYWILD:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NXRRSET:
+ case DNS_R_NCACHENXRRSET:
+ case ISC_R_NOTFOUND:
+ return (ISC_R_SUCCESS);
+ case DNS_R_DELEGATION:
+ case DNS_R_DUPLICATE:
+ case DNS_R_DROP:
+ return (result);
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type,
+ " NS address rewrite rrset", result);
+ return (ISC_R_SUCCESS);
+ default:
+ if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
+ client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
+ rpz_type, " NS address rewrite rrset",
+ result);
+ }
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_rewrite_ip_rrset: unexpected result");
+ return (DNS_R_SERVFAIL);
+ }
+
+ /*
+ * Check all of the IP addresses in the rdataset.
+ */
+ for (result = dns_rdataset_first(*ip_rdatasetp);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(*ip_rdatasetp)) {
+
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(*ip_rdatasetp, &rdata);
+ switch (rdata.type) {
+ case dns_rdatatype_a:
+ INSIST(rdata.length == 4);
+ memmove(&ina.s_addr, rdata.data, 4);
+ isc_netaddr_fromin(&netaddr, &ina);
+ break;
+ case dns_rdatatype_aaaa:
+ INSIST(rdata.length == 16);
+ memmove(in6a.s6_addr, rdata.data, 16);
+ isc_netaddr_fromin6(&netaddr, &in6a);
+ break;
+ default:
+ continue;
+ }
+
+ result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type,
+ zbits, p_rdatasetp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Look for IP addresses in A and AAAA rdatasets
+ * that trigger all eligible IP or NSIP policy rules.
+ */
+static isc_result_t
+rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name,
+ dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
+ dns_rdataset_t **ip_rdatasetp, bool resuming)
+{
+ dns_rpz_st_t *st;
+ dns_dbversion_t *ip_version;
+ dns_db_t *ip_db;
+ dns_rdataset_t *p_rdataset;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrsets");
+
+ st = client->query.rpz_st;
+ ip_version = NULL;
+ ip_db = NULL;
+ p_rdataset = NULL;
+ if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
+ (qtype == dns_rdatatype_a ||
+ qtype == dns_rdatatype_any ||
+ rpz_type == DNS_RPZ_TYPE_NSIP)) {
+ /*
+ * Rewrite based on an IPv4 address that will appear
+ * in the ANSWER section or if we are checking IP addresses.
+ */
+ result = rpz_rewrite_ip_rrset(client, name, qtype,
+ rpz_type, dns_rdatatype_a,
+ &ip_db, ip_version, ip_rdatasetp,
+ &p_rdataset, resuming);
+ if (result == ISC_R_SUCCESS)
+ st->state |= DNS_RPZ_DONE_IPv4;
+ } else {
+ result = ISC_R_SUCCESS;
+ }
+ if (result == ISC_R_SUCCESS &&
+ (qtype == dns_rdatatype_aaaa ||
+ qtype == dns_rdatatype_any ||
+ rpz_type == DNS_RPZ_TYPE_NSIP)) {
+ /*
+ * Rewrite based on IPv6 addresses that will appear
+ * in the ANSWER section or if we are checking IP addresses.
+ */
+ result = rpz_rewrite_ip_rrset(client, name, qtype,
+ rpz_type, dns_rdatatype_aaaa,
+ &ip_db, ip_version, ip_rdatasetp,
+ &p_rdataset, resuming);
+ }
+ if (ip_db != NULL)
+ dns_db_detach(&ip_db);
+ query_putrdataset(client, &p_rdataset);
+ return (result);
+}
+
+/*
+ * Try to rewrite a request for a qtype rdataset based on the trigger name
+ * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME).
+ * Record the results including the replacement rdataset if any
+ * in client->query.rpz_st.
+ * *rdatasetp is a scratch rdataset.
+ */
+static isc_result_t
+rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
+ dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
+ dns_rpz_zbits_t allowed_zbits, dns_rdataset_t **rdatasetp)
+{
+ dns_rpz_zones_t *rpzs;
+ dns_rpz_zone_t *rpz;
+ dns_rpz_st_t *st;
+ dns_fixedname_t p_namef;
+ dns_name_t *p_name;
+ dns_rpz_zbits_t zbits;
+ dns_rpz_num_t rpz_num;
+ dns_zone_t *p_zone;
+ dns_db_t *p_db;
+ dns_dbversion_t *p_version;
+ dns_dbnode_t *p_node;
+ dns_rpz_policy_t policy;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name");
+
+ zbits = rpz_get_zbits(client, qtype, rpz_type);
+ zbits &= allowed_zbits;
+ if (zbits == 0)
+ return (ISC_R_SUCCESS);
+
+ rpzs = client->view->rpzs;
+
+ /*
+ * Use the summary database to find the bit mask of policy zones
+ * with policies for this trigger name. We do this even if there
+ * is only one eligible policy zone so that wildcard triggers
+ * are matched correctly, and not into their parent.
+ */
+ zbits = dns_rpz_find_name(rpzs, rpz_type, zbits, trig_name);
+ if (zbits == 0)
+ return (ISC_R_SUCCESS);
+
+ p_name = dns_fixedname_initname(&p_namef);
+
+ p_zone = NULL;
+ p_db = NULL;
+ p_node = NULL;
+
+ st = client->query.rpz_st;
+
+ /*
+ * Check the trigger name in every policy zone that the summary data
+ * says has a hit for the trigger name.
+ * Most of the time there are no eligible zones and the summary data
+ * keeps us from getting this far.
+ * We check the most eligible zone first and so usually check only
+ * one policy zone.
+ */
+ for (rpz_num = 0; zbits != 0; ++rpz_num, zbits >>= 1) {
+ if ((zbits & 1) == 0)
+ continue;
+
+ /*
+ * Do not check policy zones that cannot replace a previously
+ * found policy.
+ */
+ rpz = rpzs->zones[rpz_num];
+ if (st->m.policy != DNS_RPZ_POLICY_MISS) {
+ if (st->m.rpz->num < rpz->num)
+ break;
+ if (st->m.rpz->num == rpz->num &&
+ st->m.type < rpz_type)
+ break;
+ }
+
+ /*
+ * Get the next policy zone's record for this trigger name.
+ */
+ result = rpz_get_p_name(client, p_name, rpz, rpz_type,
+ trig_name);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = rpz_find_p(client, trig_name, qtype, p_name,
+ rpz, rpz_type,
+ &p_zone, &p_db, &p_version, &p_node,
+ rdatasetp, &policy);
+ switch (result) {
+ case DNS_R_NXDOMAIN:
+ /*
+ * Continue after a missing policy record
+ * contrary to the summary data. The summary
+ * data can out of date during races with and among
+ * policy zone updates.
+ */
+ CTRACE(ISC_LOG_ERROR,
+ "rpz_rewrite_name: mismatched summary data; "
+ "continuing");
+ continue;
+ case DNS_R_SERVFAIL:
+ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ return (DNS_R_SERVFAIL);
+ default:
+ /*
+ * With more than one applicable policy, prefer
+ * the earliest configured policy,
+ * client-IP over QNAME over IP over NSDNAME over NSIP,
+ * and the smallest name.
+ * We known st->m.rpz->num >= rpz->num and either
+ * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
+ */
+ if (st->m.policy != DNS_RPZ_POLICY_MISS &&
+ rpz->num == st->m.rpz->num &&
+ (st->m.type < rpz_type ||
+ (st->m.type == rpz_type &&
+ 0 >= dns_name_compare(p_name, st->p_name))))
+ continue;
+#if 0
+ /*
+ * This code would block a customer reported information
+ * leak of rpz rules by rewriting requests in the
+ * rpz-ip, rpz-nsip, rpz-nsdname,and rpz-passthru TLDs.
+ * Without this code, a bad guy could request
+ * 24.0.3.2.10.rpz-ip. to find the policy rule for
+ * 10.2.3.0/14. It is an insignificant leak and this
+ * code is not worth its cost, because the bad guy
+ * could publish "evil.com A 10.2.3.4" and request
+ * evil.com to get the same information.
+ * Keep code with "#if 0" in case customer demand
+ * is irresistible.
+ *
+ * We have the less frequent case of a triggered
+ * policy. Check that we have not trigger on one
+ * of the pretend RPZ TLDs.
+ * This test would make it impossible to rewrite
+ * names in TLDs that start with "rpz-" should
+ * ICANN ever allow such TLDs.
+ */
+ unsigned int labels;
+ labels = dns_name_countlabels(trig_name);
+ if (labels >= 2) {
+ dns_label_t label;
+
+ dns_name_getlabel(trig_name, labels-2, &label);
+ if (label.length >= sizeof(DNS_RPZ_PREFIX)-1 &&
+ strncasecmp((const char *)label.base+1,
+ DNS_RPZ_PREFIX,
+ sizeof(DNS_RPZ_PREFIX)-1) == 0)
+ continue;
+ }
+#endif
+ if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "rpz_rewrite_name: rpz_save_p");
+ rpz_save_p(st, rpz, rpz_type,
+ policy, p_name, 0, result,
+ &p_zone, &p_db, &p_node,
+ rdatasetp, p_version);
+ /*
+ * After a hit, higher numbered policy zones
+ * are irrelevant
+ */
+ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
+ return (ISC_R_SUCCESS);
+ }
+ /*
+ * Log DNS_RPZ_POLICY_DISABLED zones
+ * and try the next eligible policy zone.
+ */
+ rpz_log_rewrite(client, true, policy, rpz_type,
+ p_zone, p_name, NULL, rpz_num);
+ break;
+ }
+ }
+
+ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
+ isc_result_t result, int level, const char *str)
+{
+ dns_rpz_st_t *st;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ns_skip");
+
+ st = client->query.rpz_st;
+
+ if (str != NULL)
+ rpz_log_fail_helper(client, level, nsname,
+ DNS_RPZ_TYPE_NSIP, DNS_RPZ_TYPE_NSDNAME,
+ str, result);
+ if (st->r.ns_rdataset != NULL &&
+ dns_rdataset_isassociated(st->r.ns_rdataset))
+ dns_rdataset_disassociate(st->r.ns_rdataset);
+
+ st->r.label--;
+}
+
+/*
+ * RPZ query result types
+ */
+typedef enum {
+ RPZ_QRESULT_TYPE_DONE,
+ RPZ_QRESULT_TYPE_RESTART,
+ RPZ_QRESULT_TYPE_RECURSE,
+} rpz_qresult_type_t;
+
+/*
+ * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
+ */
+static isc_result_t
+rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
+ isc_result_t qresult, bool resuming,
+ dns_rdataset_t *ordataset, dns_rdataset_t *osigset)
+{
+ dns_rpz_zones_t *rpzs;
+ dns_rpz_st_t *st;
+ dns_rdataset_t *rdataset;
+ dns_fixedname_t nsnamef;
+ dns_name_t *nsname;
+ rpz_qresult_type_t qresult_type;
+ dns_rpz_zbits_t zbits;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rpz_have_t have;
+ dns_rpz_popt_t popt;
+ int rpz_ver;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite");
+
+ rpzs = client->view->rpzs;
+ st = client->query.rpz_st;
+
+ if (rpzs == NULL ||
+ (st != NULL && (st->state & DNS_RPZ_REWRITTEN) != 0))
+ return (DNS_R_DISALLOWED);
+
+ RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
+ if (rpzs->p.num_zones == 0 ||
+ (!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) ||
+ !rpz_ck_dnssec(client, qresult, ordataset, osigset))
+ {
+ RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
+ return (DNS_R_DISALLOWED);
+ }
+ have = rpzs->have;
+ popt = rpzs->p;
+ rpz_ver = rpzs->rpz_ver;
+ RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
+
+ if (st == NULL) {
+ st = isc_mem_get(client->mctx, sizeof(*st));
+ if (st == NULL)
+ return (ISC_R_NOMEMORY);
+ st->state = 0;
+ }
+ if (st->state == 0) {
+ st->state |= DNS_RPZ_ACTIVE;
+ memset(&st->m, 0, sizeof(st->m));
+ st->m.type = DNS_RPZ_TYPE_BAD;
+ st->m.policy = DNS_RPZ_POLICY_MISS;
+ st->m.ttl = ~0;
+ memset(&st->r, 0, sizeof(st->r));
+ memset(&st->q, 0, sizeof(st->q));
+ st->p_name = dns_fixedname_initname(&st->_p_namef);
+ st->r_name = dns_fixedname_initname(&st->_r_namef);
+ st->fname = dns_fixedname_initname(&st->_fnamef);
+ st->have = have;
+ st->popt = popt;
+ st->rpz_ver = rpz_ver;
+ client->query.rpz_st = st;
+ }
+
+ /*
+ * There is nothing to rewrite if the main query failed.
+ */
+ switch (qresult) {
+ case ISC_R_SUCCESS:
+ case DNS_R_GLUE:
+ case DNS_R_ZONECUT:
+ qresult_type = RPZ_QRESULT_TYPE_DONE;
+ break;
+ case DNS_R_EMPTYNAME:
+ case DNS_R_NXRRSET:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_EMPTYWILD:
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ qresult_type = RPZ_QRESULT_TYPE_RESTART;
+ break;
+ case DNS_R_DELEGATION:
+ case ISC_R_NOTFOUND:
+ /*
+ * If recursion is on, do only tentative rewriting.
+ * If recursion is off, this the normal and only time we
+ * can rewrite.
+ */
+ if (RECURSIONOK(client))
+ qresult_type = RPZ_QRESULT_TYPE_RECURSE;
+ else
+ qresult_type = RPZ_QRESULT_TYPE_RESTART;
+ break;
+ case ISC_R_FAILURE:
+ case ISC_R_TIMEDOUT:
+ case DNS_R_BROKENCHAIN:
+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, client->query.qname,
+ DNS_RPZ_TYPE_QNAME,
+ " stop on qresult in rpz_rewrite()", qresult);
+ return (ISC_R_SUCCESS);
+ default:
+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, client->query.qname,
+ DNS_RPZ_TYPE_QNAME,
+ " stop on unrecognized qresult in rpz_rewrite()",
+ qresult);
+ return (ISC_R_SUCCESS);
+ }
+
+ rdataset = NULL;
+
+ if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) !=
+ (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) {
+ isc_netaddr_t netaddr;
+ dns_rpz_zbits_t allowed;
+
+ if (qresult_type == RPZ_QRESULT_TYPE_RECURSE) {
+ /*
+ * This request needs recursion that has not been done.
+ * Get bits for the policy zones that do not need
+ * to wait for the results of recursion.
+ */
+ allowed = st->have.qname_skip_recurse;
+ if (allowed == 0)
+ return (ISC_R_SUCCESS);
+ } else {
+ allowed = DNS_RPZ_ALL_ZBITS;
+ }
+
+ /*
+ * Check once for triggers for the client IP address.
+ */
+ if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) {
+ zbits = rpz_get_zbits(client, dns_rdatatype_none,
+ DNS_RPZ_TYPE_CLIENT_IP);
+ zbits &= allowed;
+ if (zbits != 0) {
+ isc_netaddr_fromsockaddr(&netaddr,
+ &client->peeraddr);
+ result = rpz_rewrite_ip(client, &netaddr, qtype,
+ DNS_RPZ_TYPE_CLIENT_IP,
+ zbits, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Check triggers for the query name if this is the first time
+ * for the current qname.
+ * There is a first time for each name in a CNAME chain
+ */
+ if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
+ result = rpz_rewrite_name(client, client->query.qname,
+ qtype, DNS_RPZ_TYPE_QNAME,
+ allowed, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Check IPv4 addresses in A RRs next.
+ * Reset to the start of the NS names.
+ */
+ st->r.label = dns_name_countlabels(client->query.qname);
+ st->state &= ~(DNS_RPZ_DONE_QNAME_IP |
+ DNS_RPZ_DONE_IPv4);
+
+ }
+
+ /*
+ * Quit if this was an attempt to find a qname or
+ * client-IP trigger before recursion.
+ * We will be back if no pre-recursion triggers hit.
+ * For example, consider 2 policy zones, both with qname and
+ * IP address triggers. If the qname misses the 1st zone,
+ * then we cannot know whether a hit for the qname in the
+ * 2nd zone matters until after recursing to get the A RRs and
+ * testing them in the first zone.
+ * Do not bother saving the work from this attempt,
+ * because recusion is so slow.
+ */
+ if (qresult_type == RPZ_QRESULT_TYPE_RECURSE)
+ goto cleanup;
+
+ /*
+ * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP
+ * is reset at the end of dealing with each CNAME.
+ */
+ st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME);
+ }
+
+ /*
+ * Check known IP addresses for the query name if the database
+ * lookup resulted in some addresses (qresult_type ==
+ * RPZ_QRESULT_TYPE_DONE) and if we have not already checked them.
+ * Any recursion required for the query has already happened.
+ * Do not check addresses that will not be in the ANSWER section.
+ */
+ if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
+ qresult_type == RPZ_QRESULT_TYPE_DONE &&
+ rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0) {
+ result = rpz_rewrite_ip_rrsets(client,
+ client->query.qname, qtype,
+ DNS_RPZ_TYPE_IP,
+ &rdataset, resuming);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ /*
+ * We are finished checking the IP addresses for the qname.
+ * Start with IPv4 if we will check NS IP addesses.
+ */
+ st->state |= DNS_RPZ_DONE_QNAME_IP;
+ st->state &= ~DNS_RPZ_DONE_IPv4;
+ }
+
+ /*
+ * Stop looking for rules if there are none of the other kinds
+ * that could override what we already have.
+ */
+ if (rpz_get_zbits(client, dns_rdatatype_any,
+ DNS_RPZ_TYPE_NSDNAME) == 0 &&
+ rpz_get_zbits(client, dns_rdatatype_any,
+ DNS_RPZ_TYPE_NSIP) == 0) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ dns_fixedname_init(&nsnamef);
+ dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
+ while (st->r.label > st->popt.min_ns_labels) {
+ /*
+ * Get NS rrset for each domain in the current qname.
+ */
+ if (st->r.label == dns_name_countlabels(client->query.qname)) {
+ nsname = client->query.qname;
+ } else {
+ nsname = dns_fixedname_name(&nsnamef);
+ dns_name_split(client->query.qname, st->r.label,
+ NULL, nsname);
+ }
+ if (st->r.ns_rdataset == NULL ||
+ !dns_rdataset_isassociated(st->r.ns_rdataset))
+ {
+ dns_db_t *db = NULL;
+ result = rpz_rrset_find(client, nsname,
+ dns_rdatatype_ns,
+ DNS_RPZ_TYPE_NSDNAME,
+ &db, NULL, &st->r.ns_rdataset,
+ resuming);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (st->m.policy == DNS_RPZ_POLICY_ERROR)
+ goto cleanup;
+ switch (result) {
+ case ISC_R_SUCCESS:
+ result = dns_rdataset_first(st->r.ns_rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ st->state &= ~(DNS_RPZ_DONE_NSDNAME |
+ DNS_RPZ_DONE_IPv4);
+ break;
+ case DNS_R_DELEGATION:
+ case DNS_R_DUPLICATE:
+ case DNS_R_DROP:
+ goto cleanup;
+ case DNS_R_EMPTYNAME:
+ case DNS_R_NXRRSET:
+ case DNS_R_EMPTYWILD:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ case ISC_R_NOTFOUND:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ rpz_rewrite_ns_skip(client, nsname, result,
+ 0, NULL);
+ continue;
+ case ISC_R_TIMEDOUT:
+ case DNS_R_BROKENCHAIN:
+ case ISC_R_FAILURE:
+ rpz_rewrite_ns_skip(client, nsname, result,
+ DNS_RPZ_DEBUG_LEVEL3,
+ " NS rpz_rrset_find()");
+ continue;
+ default:
+ rpz_rewrite_ns_skip(client, nsname, result,
+ DNS_RPZ_INFO_LEVEL,
+ " unrecognized NS"
+ " rpz_rrset_find()");
+ continue;
+ }
+ }
+ /*
+ * Check all NS names.
+ */
+ do {
+ dns_rdata_ns_t ns;
+ dns_rdata_t nsrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
+ result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
+ dns_rdata_reset(&nsrdata);
+ if (result != ISC_R_SUCCESS) {
+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
+ nsname, DNS_RPZ_TYPE_NSIP,
+ " rdata_tostruct()", result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ goto cleanup;
+ }
+ /*
+ * Do nothing about "NS ."
+ */
+ if (dns_name_equal(&ns.name, dns_rootname)) {
+ dns_rdata_freestruct(&ns);
+ result = dns_rdataset_next(st->r.ns_rdataset);
+ continue;
+ }
+ /*
+ * Check this NS name if we did not handle it
+ * during a previous recursion.
+ */
+ if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) {
+ result = rpz_rewrite_name(client, &ns.name,
+ qtype,
+ DNS_RPZ_TYPE_NSDNAME,
+ DNS_RPZ_ALL_ZBITS,
+ &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_freestruct(&ns);
+ goto cleanup;
+ }
+ st->state |= DNS_RPZ_DONE_NSDNAME;
+ }
+ /*
+ * Check all IP addresses for this NS name.
+ */
+ result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype,
+ DNS_RPZ_TYPE_NSIP,
+ &rdataset, resuming);
+ dns_rdata_freestruct(&ns);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ st->state &= ~(DNS_RPZ_DONE_NSDNAME |
+ DNS_RPZ_DONE_IPv4);
+ result = dns_rdataset_next(st->r.ns_rdataset);
+ } while (result == ISC_R_SUCCESS);
+ dns_rdataset_disassociate(st->r.ns_rdataset);
+ st->r.label--;
+
+ if (rpz_get_zbits(client, dns_rdatatype_any,
+ DNS_RPZ_TYPE_NSDNAME) == 0 &&
+ rpz_get_zbits(client, dns_rdatatype_any,
+ DNS_RPZ_TYPE_NSIP) == 0)
+ break;
+ }
+
+ /*
+ * Use the best hit, if any.
+ */
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (st->m.policy != DNS_RPZ_POLICY_MISS &&
+ st->m.policy != DNS_RPZ_POLICY_ERROR &&
+ st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
+ st->m.policy = st->m.rpz->policy;
+ if (st->m.policy == DNS_RPZ_POLICY_MISS ||
+ st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
+ st->m.policy == DNS_RPZ_POLICY_ERROR) {
+ if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
+ result != DNS_R_DELEGATION)
+ rpz_log_rewrite(client, false, st->m.policy,
+ st->m.type, st->m.zone, st->p_name,
+ NULL, st->m.rpz->num);
+ rpz_match_clear(st);
+ }
+ if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
+ CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
+ st->m.type = DNS_RPZ_TYPE_BAD;
+ result = DNS_R_SERVFAIL;
+ }
+ query_putrdataset(client, &rdataset);
+ if ((st->state & DNS_RPZ_RECURSING) == 0)
+ rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
+
+ return (result);
+}
+
+/*
+ * See if response policy zone rewriting is allowed by a lack of interest
+ * by the client in DNSSEC or a lack of signatures.
+ */
+static bool
+rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ dns_rdataset_t trdataset;
+ dns_rdatatype_t type;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_ck_dnssec");
+
+ if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client))
+ return (true);
+
+ /*
+ * We do not know if there are signatures if we have not recursed
+ * for them.
+ */
+ if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND)
+ return (false);
+
+ if (sigrdataset == NULL)
+ return (true);
+ if (dns_rdataset_isassociated(sigrdataset))
+ return (false);
+
+ /*
+ * We are happy to rewrite nothing.
+ */
+ if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
+ return (true);
+ /*
+ * Do not rewrite if there is any sign of signatures.
+ */
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->type == dns_rdatatype_rrsig)
+ return (false);
+
+ /*
+ * Look for a signature in a negative cache rdataset.
+ */
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
+ return (true);
+ found = dns_fixedname_initname(&fixed);
+ dns_rdataset_init(&trdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_ncache_current(rdataset, found, &trdataset);
+ type = trdataset.type;
+ dns_rdataset_disassociate(&trdataset);
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
+ type == dns_rdatatype_rrsig)
+ return (false);
+ }
+ return (true);
+}
+
+/*
+ * Add a CNAME to the query response, including translating foo.evil.com and
+ * *.evil.com CNAME *.example.com
+ * to
+ * foo.evil.com CNAME foo.evil.com.example.com
+ */
+static isc_result_t
+rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st,
+ dns_name_t *cname, dns_name_t *fname, isc_buffer_t *dbuf)
+{
+ dns_fixedname_t prefix, suffix;
+ unsigned int labels;
+ isc_result_t result;
+
+ CTRACE(ISC_LOG_DEBUG(3), "rpz_add_cname");
+
+ labels = dns_name_countlabels(cname);
+ if (labels > 2 && dns_name_iswildcard(cname)) {
+ dns_fixedname_init(&prefix);
+ dns_name_split(client->query.qname, 1,
+ dns_fixedname_name(&prefix), NULL);
+ dns_fixedname_init(&suffix);
+ dns_name_split(cname, labels-1,
+ NULL, dns_fixedname_name(&suffix));
+ result = dns_name_concatenate(dns_fixedname_name(&prefix),
+ dns_fixedname_name(&suffix),
+ fname, NULL);
+ if (result == DNS_R_NAMETOOLONG)
+ client->message->rcode = dns_rcode_yxdomain;
+ } else {
+ result = dns_name_copy(cname, fname, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ query_keepname(client, fname, dbuf);
+ result = query_add_cname(client, client->query.qname,
+ fname, dns_trust_authanswer, st->m.ttl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rpz_log_rewrite(client, false, st->m.policy,
+ st->m.type, st->m.zone, st->p_name, fname,
+ st->m.rpz->num);
+ ns_client_qnamereplace(client, fname);
+ /*
+ * Turn off DNSSEC because the results of a
+ * response policy zone cannot verify.
+ */
+ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
+ NS_CLIENTATTR_WANTAD);
+ return (ISC_R_SUCCESS);
+}
+
+#define MAX_RESTARTS 16
+
+#define QUERY_ERROR(r) \
+do { \
+ eresult = r; \
+ want_restart = false; \
+ line = __LINE__; \
+} while (0)
+
+#define RECURSE_ERROR(r) \
+do { \
+ if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \
+ QUERY_ERROR(r); \
+ else \
+ QUERY_ERROR(DNS_R_SERVFAIL); \
+} while (0)
+
+/*
+ * Extract a network address from the RDATA of an A or AAAA
+ * record.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
+ */
+static isc_result_t
+rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
+ struct in_addr ina;
+ struct in6_addr in6a;
+
+ switch (rdata->type) {
+ case dns_rdatatype_a:
+ INSIST(rdata->length == 4);
+ memmove(&ina.s_addr, rdata->data, 4);
+ isc_netaddr_fromin(netaddr, &ina);
+ return (ISC_R_SUCCESS);
+ case dns_rdatatype_aaaa:
+ INSIST(rdata->length == 16);
+ memmove(in6a.s6_addr, rdata->data, 16);
+ isc_netaddr_fromin6(netaddr, &in6a);
+ return (ISC_R_SUCCESS);
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+}
+
+/*
+ * Find the sort order of 'rdata' in the topology-like
+ * ACL forming the second element in a 2-element top-level
+ * sortlist statement.
+ */
+static int
+query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
+ isc_netaddr_t netaddr;
+
+ if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
+ return (INT_MAX);
+ return (ns_sortlist_addrorder2(&netaddr, arg));
+}
+
+/*
+ * Find the sort order of 'rdata' in the matching element
+ * of a 1-element top-level sortlist statement.
+ */
+static int
+query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
+ isc_netaddr_t netaddr;
+
+ if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
+ return (INT_MAX);
+ return (ns_sortlist_addrorder1(&netaddr, arg));
+}
+
+/*
+ * Find the sortlist statement that applies to 'client' and set up
+ * the sortlist info in in client->message appropriately.
+ */
+static void
+setup_query_sortlist(ns_client_t *client) {
+ isc_netaddr_t netaddr;
+ dns_rdatasetorderfunc_t order = NULL;
+ const void *order_arg = NULL;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (ns_sortlist_setup(client->view->sortlist,
+ &netaddr, &order_arg)) {
+ case NS_SORTLISTTYPE_1ELEMENT:
+ order = query_sortlist_order_1element;
+ break;
+ case NS_SORTLISTTYPE_2ELEMENT:
+ order = query_sortlist_order_2element;
+ break;
+ case NS_SORTLISTTYPE_NONE:
+ order = NULL;
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+ dns_message_setsortorder(client->message, order, order_arg);
+}
+
+static void
+query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
+ isc_buffer_t *dbuf, b;
+ dns_name_t *fname;
+ dns_rdataset_t *neg, *negsig;
+ isc_result_t result = ISC_R_NOMEMORY;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof");
+
+ fname = NULL;
+ neg = NULL;
+ negsig = NULL;
+
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ neg = query_newrdataset(client);
+ negsig = query_newrdataset(client);
+ if (fname == NULL || neg == NULL || negsig == NULL)
+ goto cleanup;
+
+ result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ query_addrrset(client, &fname, &neg, &negsig, dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
+ goto cleanup;
+
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ }
+ if (neg == NULL)
+ neg = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(neg))
+ dns_rdataset_disassociate(neg);
+ if (negsig == NULL)
+ negsig = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(negsig))
+ dns_rdataset_disassociate(negsig);
+ if (fname == NULL || neg == NULL || negsig == NULL)
+ goto cleanup;
+ result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ query_addrrset(client, &fname, &neg, &negsig, dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ cleanup:
+ if (neg != NULL)
+ query_putrdataset(client, &neg);
+ if (negsig != NULL)
+ query_putrdataset(client, &negsig);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+}
+
+static inline void
+answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
+ dns_name_t *name;
+ dns_message_t *msg;
+ dns_section_t section = DNS_SECTION_ADDITIONAL;
+ dns_rdataset_t *rdataset = NULL;
+
+ msg = client->message;
+ for (name = ISC_LIST_HEAD(msg->sections[section]);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link))
+ if (dns_name_equal(name, client->query.qname)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ if (rdataset->type == qtype)
+ break;
+ break;
+ }
+ if (rdataset != NULL) {
+ ISC_LIST_UNLINK(msg->sections[section], name, link);
+ ISC_LIST_PREPEND(msg->sections[section], name, link);
+ ISC_LIST_UNLINK(name->list, rdataset, link);
+ ISC_LIST_PREPEND(name->list, rdataset, link);
+ rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
+ }
+}
+
+static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
+static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
+static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
+
+static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
+
+static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
+
+static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
+
+static dns_name_t rfc1918names[] = {
+ DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
+ DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
+};
+
+
+static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
+static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
+
+static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
+static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
+
+static dns_name_t prisoner =
+ DNS_NAME_INITABSOLUTE(prisoner_data, prisoner_offsets);
+static dns_name_t hostmaster =
+ DNS_NAME_INITABSOLUTE(hostmaster_data, hostmaster_offsets);
+
+static void
+warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
+ unsigned int i;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ dns_rdataset_t found;
+ isc_result_t result;
+
+ for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
+ if (dns_name_issubdomain(fname, &rfc1918names[i])) {
+ dns_rdataset_init(&found);
+ result = dns_ncache_getrdataset(rdataset,
+ &rfc1918names[i],
+ dns_rdatatype_soa,
+ &found);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ result = dns_rdataset_first(&found);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(&found, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (dns_name_equal(&soa.origin, &prisoner) &&
+ dns_name_equal(&soa.contact, &hostmaster)) {
+ char buf[DNS_NAME_FORMATSIZE];
+ dns_name_format(fname, buf, sizeof(buf));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "RFC 1918 response from "
+ "Internet for %s", buf);
+ }
+ dns_rdataset_disassociate(&found);
+ return;
+ }
+ }
+}
+
+static void
+query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
+ dns_dbversion_t *version, ns_client_t *client,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_name_t *fname, bool exact,
+ dns_name_t *found)
+{
+ unsigned char salt[256];
+ size_t salt_length;
+ uint16_t iterations;
+ isc_result_t result;
+ unsigned int dboptions;
+ dns_fixedname_t fixed;
+ dns_hash_t hash;
+ dns_name_t name;
+ unsigned int skip = 0, labels;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ bool optout;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ salt_length = sizeof(salt);
+ result = dns_db_getnsec3parameters(db, version, &hash, NULL,
+ &iterations, salt, &salt_length);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ dns_name_init(&name, NULL);
+ dns_name_clone(qname, &name);
+ labels = dns_name_countlabels(&name);
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ /*
+ * Map unknown algorithm to known value.
+ */
+ if (hash == DNS_NSEC3_UNKNOWNALG)
+ hash = 1;
+
+ again:
+ dns_fixedname_init(&fixed);
+ result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
+ dns_db_origin(db), hash,
+ iterations, salt, salt_length);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
+ result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
+ dns_rdatatype_nsec3, dboptions, client->now,
+ NULL, fname, &cm, &ci, rdataset, sigrdataset);
+
+ if (result == DNS_R_NXDOMAIN) {
+ if (!dns_rdataset_isassociated(rdataset)) {
+ return;
+ }
+ result = dns_rdataset_first(rdataset);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ dns_rdata_reset(&rdata);
+ optout = (nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
+ if (found != NULL && optout &&
+ dns_name_issubdomain(&name, dns_db_origin(db)))
+ {
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ skip++;
+ dns_name_getlabelsequence(qname, skip, labels - skip,
+ &name);
+ ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
+ NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
+ "looking for closest provable encloser");
+ goto again;
+ }
+ if (exact)
+ ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
+ NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
+ "expected a exact match NSEC3, got "
+ "a covering record");
+
+ } else if (result != ISC_R_SUCCESS) {
+ return;
+ } else if (!exact)
+ ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
+ NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
+ "expected covering NSEC3, got an exact match");
+ if (found == qname) {
+ if (skip != 0U)
+ dns_name_getlabelsequence(qname, skip, labels - skip,
+ found);
+ } else if (found != NULL)
+ dns_name_copy(&name, found, NULL);
+ return;
+}
+
+#ifdef ALLOW_FILTER_AAAA
+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);
+}
+
+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);
+}
+#endif
+
+static uint32_t
+dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_soa_t soa;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ uint32_t ttl = UINT32_MAX;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataset_first(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ ttl = ISC_MIN(rdataset.ttl, soa.minimum);
+
+cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (ttl);
+}
+
+static bool
+dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ isc_netaddr_t netaddr;
+ dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
+ unsigned int flags = 0;
+ unsigned int i, count;
+ bool *aaaaok;
+
+ INSIST(client->query.dns64_aaaaok == NULL);
+ INSIST(client->query.dns64_aaaaoklen == 0);
+ INSIST(client->query.dns64_aaaa == NULL);
+ INSIST(client->query.dns64_sigaaaa == NULL);
+
+ if (dns64 == NULL)
+ return (true);
+
+ if (RECURSIONOK(client))
+ flags |= DNS_DNS64_RECURSIVE;
+
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ flags |= DNS_DNS64_DNSSEC;
+
+ count = dns_rdataset_count(rdataset);
+ aaaaok = isc_mem_get(client->mctx, sizeof(bool) * count);
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
+ &ns_g_server->aclenv, flags, rdataset,
+ aaaaok, count)) {
+ for (i = 0; i < count; i++) {
+ if (aaaaok != NULL && !aaaaok[i]) {
+ SAVE(client->query.dns64_aaaaok, aaaaok);
+ client->query.dns64_aaaaoklen = count;
+ break;
+ }
+ }
+ if (aaaaok != NULL)
+ isc_mem_put(client->mctx, aaaaok,
+ sizeof(bool) * count);
+ return (true);
+ }
+ if (aaaaok != NULL)
+ isc_mem_put(client->mctx, aaaaok,
+ sizeof(bool) * count);
+ return (false);
+}
+
+/*
+ * Look for the name and type in the redirection zone. If found update
+ * the arguments as appropriate. Return true if a update was
+ * performed.
+ *
+ * Only perform the update if the client is in the allow query acl and
+ * returning the update would not cause a DNSSEC validation failure.
+ */
+static isc_result_t
+redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_rdatatype_t qtype)
+{
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ dns_rdataset_t trdataset;
+ isc_result_t result;
+ dns_rdatatype_t type;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ ns_dbversion_t *dbversion;
+
+ CTRACE(ISC_LOG_DEBUG(3), "redirect");
+
+ if (client->view->redirect == NULL)
+ return (ISC_R_NOTFOUND);
+
+ found = dns_fixedname_initname(&fixed);
+ dns_rdataset_init(&trdataset);
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
+ return (ISC_R_NOTFOUND);
+
+ if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
+ if (rdataset->trust == dns_trust_secure)
+ return (ISC_R_NOTFOUND);
+ if (rdataset->trust == dns_trust_ultimate &&
+ (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3))
+ return (ISC_R_NOTFOUND);
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_ncache_current(rdataset, found, &trdataset);
+ type = trdataset.type;
+ dns_rdataset_disassociate(&trdataset);
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
+ type == dns_rdatatype_rrsig)
+ return (ISC_R_NOTFOUND);
+ }
+ }
+ }
+
+ result = ns_client_checkaclsilent(client, NULL,
+ dns_zone_getqueryacl(client->view->redirect),
+ true);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ result = dns_zone_getdb(client->view->redirect, &db);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ dbversion = query_findversion(client, db);
+ if (dbversion == NULL) {
+ dns_db_detach(&db);
+ return (ISC_R_NOTFOUND);
+ }
+
+ /*
+ * Lookup the requested data in the redirect zone.
+ */
+ result = dns_db_findext(db, client->query.qname, dbversion->version,
+ qtype, DNS_DBFIND_NOZONECUT, client->now,
+ &node, found, &cm, &ci, &trdataset, NULL);
+ if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ goto nxrrset;
+ } else if (result != ISC_R_SUCCESS) {
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (ISC_R_NOTFOUND);
+ }
+
+ CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
+ dns_name_copy(found, name, NULL);
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(&trdataset)) {
+ dns_rdataset_clone(&trdataset, rdataset);
+ dns_rdataset_disassociate(&trdataset);
+ }
+ nxrrset:
+ if (*nodep != NULL)
+ dns_db_detachnode(*dbp, nodep);
+ dns_db_detach(dbp);
+ dns_db_attachnode(db, node, nodep);
+ dns_db_attach(db, dbp);
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ *versionp = dbversion->version;
+
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+
+ return (result);
+}
+
+static isc_result_t
+redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_rdatatype_t qtype, bool *is_zonep)
+{
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fixed;
+ dns_fixedname_t fixedredirect;
+ dns_name_t *found, *redirectname;
+ dns_rdataset_t trdataset;
+ isc_result_t result;
+ dns_rdatatype_t type;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ dns_dbversion_t *version = NULL;
+ dns_zone_t *zone = NULL;
+ bool is_zone;
+ unsigned int options;
+
+ CTRACE(ISC_LOG_DEBUG(3), "redirect2");
+
+ if (client->view->redirectzone == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (dns_name_issubdomain(name, client->view->redirectzone))
+ return (ISC_R_NOTFOUND);
+
+ found = dns_fixedname_initname(&fixed);
+ dns_rdataset_init(&trdataset);
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+ if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
+ return (ISC_R_NOTFOUND);
+
+ if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
+ if (rdataset->trust == dns_trust_secure)
+ return (ISC_R_NOTFOUND);
+ if (rdataset->trust == dns_trust_ultimate &&
+ (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3))
+ return (ISC_R_NOTFOUND);
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_ncache_current(rdataset, found, &trdataset);
+ type = trdataset.type;
+ dns_rdataset_disassociate(&trdataset);
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
+ type == dns_rdatatype_rrsig)
+ return (ISC_R_NOTFOUND);
+ }
+ }
+ }
+
+ redirectname = dns_fixedname_initname(&fixedredirect);
+ if (dns_name_countlabels(name) > 1U) {
+ dns_name_t prefix;
+ unsigned int labels = dns_name_countlabels(name) - 1;
+
+ dns_name_init(&prefix, NULL);
+ dns_name_getlabelsequence(name, 0, labels, &prefix);
+ result = dns_name_concatenate(&prefix,
+ client->view->redirectzone,
+ redirectname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+ } else
+ dns_name_copy(redirectname, client->view->redirectzone, NULL);
+
+ options = 0;
+ result = query_getdb(client, redirectname, qtype, options, &zone,
+ &db, &version, &is_zone);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ /*
+ * Lookup the requested data in the redirect zone.
+ */
+ result = dns_db_findext(db, redirectname, version,
+ qtype, 0, client->now,
+ &node, found, &cm, &ci, &trdataset, NULL);
+ if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ goto nxrrset;
+ } else if (result == ISC_R_NOTFOUND || result == DNS_R_DELEGATION) {
+ /*
+ * Cleanup.
+ */
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ /*
+ * Don't loop forever if the lookup failed last time.
+ */
+ if (!REDIRECT(client)) {
+ result = query_recurse(client, qtype, redirectname,
+ NULL, NULL, true);
+ if (result == ISC_R_SUCCESS) {
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ client->query.attributes |=
+ NS_QUERYATTR_REDIRECT;
+ return (DNS_R_CONTINUE);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+ } else if (result != ISC_R_SUCCESS) {
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (ISC_R_NOTFOUND);
+ }
+
+ CTRACE(ISC_LOG_DEBUG(3), "redirect2: found data: done");
+ /*
+ * Adjust the found name to not include the redirectzone suffix.
+ */
+ dns_name_split(found, dns_name_countlabels(client->view->redirectzone),
+ found, NULL);
+ /*
+ * Make the name absolute.
+ */
+ result = dns_name_concatenate(found, dns_rootname, found, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_name_copy(found, name, NULL);
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(&trdataset)) {
+ dns_rdataset_clone(&trdataset, rdataset);
+ dns_rdataset_disassociate(&trdataset);
+ }
+ nxrrset:
+ if (*nodep != NULL)
+ dns_db_detachnode(*dbp, nodep);
+ dns_db_detach(dbp);
+ dns_db_attachnode(db, node, nodep);
+ dns_db_attach(db, dbp);
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ *is_zonep = is_zone;
+ *versionp = version;
+
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+
+ return (result);
+}
+
+/*
+ * Do the bulk of query processing for the current query of 'client'.
+ * If 'event' is non-NULL, we are returning from recursion and 'qtype'
+ * is ignored. Otherwise, 'qtype' is the query type.
+ */
+static isc_result_t
+query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
+{
+ dns_db_t *db, *zdb;
+ dns_dbnode_t *node;
+ dns_rdatatype_t type = qtype;
+ dns_name_t *fname, *zfname, *tname, *prefix;
+ dns_rdataset_t *rdataset, *trdataset;
+ dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
+ dns_rdataset_t **sigrdatasetp;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatasetiter_t *rdsiter;
+ bool want_restart, is_zone, need_wildcardproof;
+ bool is_staticstub_zone;
+ bool authoritative = false;
+ bool answer_has_ns = false;
+ unsigned int n, nlabels;
+ dns_namereln_t namereln;
+ int order;
+ isc_buffer_t *dbuf;
+ isc_buffer_t b;
+ isc_result_t result, eresult, tresult;
+ dns_fixedname_t fixed;
+ dns_fixedname_t wildcardname;
+ dns_dbversion_t *version, *zversion;
+ dns_zone_t *zone;
+ dns_rdata_cname_t cname;
+ dns_rdata_dname_t dname;
+ unsigned int options;
+ bool empty_wild;
+ dns_rdataset_t *noqname;
+ dns_rpz_st_t *rpz_st;
+ bool resuming;
+ int line = -1;
+ bool dns64_exclude, dns64, rpz;
+ bool nxrewrite = false;
+ bool redirected = false;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ char errmsg[256];
+ bool associated;
+ dns_section_t section;
+ dns_ttl_t ttl;
+ bool failcache;
+ uint32_t flags;
+#ifdef WANT_QUERYTRACE
+ char mbuf[BUFSIZ];
+ char qbuf[DNS_NAME_FORMATSIZE];
+ char tbuf[DNS_RDATATYPE_FORMATSIZE];
+#endif
+ dns_name_t *rpzqname;
+
+ CTRACE(ISC_LOG_DEBUG(3), "query_find");
+
+ /*
+ * One-time initialization.
+ *
+ * It's especially important to initialize anything that the cleanup
+ * code might cleanup.
+ */
+
+ eresult = ISC_R_SUCCESS;
+ fname = NULL;
+ zfname = NULL;
+ rdataset = NULL;
+ zrdataset = NULL;
+ sigrdataset = NULL;
+ zsigrdataset = NULL;
+ zversion = NULL;
+ node = NULL;
+ db = NULL;
+ zdb = NULL;
+ version = NULL;
+ zone = NULL;
+ need_wildcardproof = false;
+ empty_wild = false;
+ dns64_exclude = dns64 = rpz = false;
+ options = 0;
+ resuming = false;
+ is_zone = false;
+ is_staticstub_zone = false;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client, NULL);
+
+#ifdef WANT_QUERYTRACE
+ if (client->query.origqname != NULL)
+ dns_name_format(client->query.origqname, qbuf,
+ sizeof(qbuf));
+ else
+ snprintf(qbuf, sizeof(qbuf), "<unset>");
+
+ snprintf(mbuf, sizeof(mbuf) - 1,
+ "client attr:0x%x, query attr:0x%X, restarts:%d, "
+ "origqname:%s, timer:%d, authdb:%d, referral:%d",
+ client->attributes,
+ client->query.attributes,
+ client->query.restarts, qbuf,
+ (int) client->query.timerset,
+ (int) client->query.authdbset,
+ (int) client->query.isreferral);
+ CTRACE(ISC_LOG_DEBUG(3), mbuf);
+#endif
+
+ if (event != NULL) {
+ /*
+ * We're returning from recursion. Restore the query context
+ * and resume.
+ */
+ want_restart = false;
+
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0)
+ {
+ CTRACE(ISC_LOG_DEBUG(3), "resume from RPZ recursion");
+#ifdef WANT_QUERYTRACE
+ {
+ char pbuf[DNS_NAME_FORMATSIZE] = "<unset>";
+ char fbuf[DNS_NAME_FORMATSIZE] = "<unset>";
+ if (rpz_st->r_name != NULL)
+ dns_name_format(rpz_st->r_name,
+ qbuf, sizeof(qbuf));
+ else
+ snprintf(qbuf, sizeof(qbuf),
+ "<unset>");
+ if (rpz_st->p_name != NULL)
+ dns_name_format(rpz_st->p_name,
+ pbuf, sizeof(pbuf));
+ if (rpz_st->fname != NULL)
+ dns_name_format(rpz_st->fname,
+ fbuf, sizeof(fbuf));
+
+ snprintf(mbuf, sizeof(mbuf) - 1,
+ "rpz rname:%s, pname:%s, fname:%s",
+ qbuf, pbuf, fbuf);
+ CTRACE(ISC_LOG_DEBUG(3), mbuf);
+ }
+#endif
+
+ is_zone = rpz_st->q.is_zone;
+ authoritative = rpz_st->q.authoritative;
+ RESTORE(zone, rpz_st->q.zone);
+ RESTORE(node, rpz_st->q.node);
+ RESTORE(db, rpz_st->q.db);
+ RESTORE(rdataset, rpz_st->q.rdataset);
+ RESTORE(sigrdataset, rpz_st->q.sigrdataset);
+ qtype = rpz_st->q.qtype;
+
+ if (event->node != NULL)
+ dns_db_detachnode(event->db, &event->node);
+ SAVE(rpz_st->r.db, event->db);
+ rpz_st->r.r_type = event->qtype;
+ SAVE(rpz_st->r.r_rdataset, event->rdataset);
+ query_putrdataset(client, &event->sigrdataset);
+ } else if (REDIRECT(client)) {
+ /*
+ * Restore saved state.
+ */
+ CTRACE(ISC_LOG_DEBUG(3),
+ "resume from redirect recursion");
+#ifdef WANT_QUERYTRACE
+ dns_name_format(client->query.redirect.fname,
+ qbuf, sizeof(qbuf));
+ dns_rdatatype_format(client->query.redirect.qtype,
+ tbuf, sizeof(tbuf));
+ snprintf(mbuf, sizeof(mbuf) - 1,
+ "redirect fname:%s, qtype:%s, auth:%d",
+ qbuf, tbuf,
+ client->query.redirect.authoritative);
+ CTRACE(ISC_LOG_DEBUG(3), mbuf);
+#endif
+ qtype = client->query.redirect.qtype;
+ INSIST(client->query.redirect.rdataset != NULL);
+ RESTORE(rdataset, client->query.redirect.rdataset);
+ RESTORE(sigrdataset,
+ client->query.redirect.sigrdataset);
+ RESTORE(db, client->query.redirect.db);
+ RESTORE(node, client->query.redirect.node);
+ RESTORE(zone, client->query.redirect.zone);
+ authoritative = client->query.redirect.authoritative;
+ is_zone = client->query.redirect.is_zone;
+
+ /*
+ * Free resources used while recursing.
+ */
+ query_putrdataset(client, &event->rdataset);
+ query_putrdataset(client, &event->sigrdataset);
+ if (event->node != NULL)
+ dns_db_detachnode(event->db, &event->node);
+ if (event->db != NULL)
+ dns_db_detach(&event->db);
+ } else {
+ CTRACE(ISC_LOG_DEBUG(3),
+ "resume from normal recursion");
+ authoritative = false;
+
+ qtype = event->qtype;
+ SAVE(db, event->db);
+ SAVE(node, event->node);
+ SAVE(rdataset, event->rdataset);
+ SAVE(sigrdataset, event->sigrdataset);
+ }
+ INSIST(rdataset != NULL);
+
+ if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
+ type = dns_rdatatype_any;
+ else
+ type = qtype;
+
+ if (DNS64(client)) {
+ client->query.attributes &= ~NS_QUERYATTR_DNS64;
+ dns64 = true;
+ }
+ if (DNS64EXCLUDE(client)) {
+ client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
+ dns64_exclude = true;
+ }
+
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0)
+ {
+ /*
+ * Has response policy changed out from under us?
+ */
+ if (rpz_st->rpz_ver != client->view->rpzs->rpz_ver) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ DNS_RPZ_INFO_LEVEL,
+ "query_find: RPZ settings "
+ "out of date "
+ "(rpz_ver %d, expected %d)",
+ client->view->rpzs->rpz_ver,
+ rpz_st->rpz_ver);
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: query_getnamebuf failed (1)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: query_newname failed (1)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
+ tname = rpz_st->fname;
+ } else if (REDIRECT(client)) {
+ tname = client->query.redirect.fname;
+ } else {
+ tname = dns_fixedname_name(&event->foundname);
+ }
+ result = dns_name_copy(tname, fname, NULL);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: dns_name_copy failed");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
+ rpz_st->r.r_result = event->result;
+ result = rpz_st->q.result;
+ free_devent(client, ISC_EVENT_PTR(&event), &event);
+ } else if (REDIRECT(client)) {
+ result = client->query.redirect.result;
+ is_zone = client->query.redirect.is_zone;
+ } else {
+ result = event->result;
+ }
+ resuming = true;
+ goto resume;
+ }
+
+ /*
+ * Not returning from recursion.
+ *
+ * First, check for a recent match in the view's SERVFAIL cache.
+ * If we find one, and it was from a query with CD=1, *or*
+ * if the current query has CD=0, then we can just return
+ * SERVFAIL now.
+ */
+ if (RECURSIONOK(client)) {
+ flags = 0;
+#ifdef ENABLE_AFL
+ if (ns_g_fuzz_type == ns_fuzz_resolver) {
+ failcache = false;
+ } else {
+ failcache = dns_badcache_find(client->view->failcache,
+ client->query.qname, qtype,
+ &flags, &client->tnow);
+ }
+#else
+ failcache = dns_badcache_find(client->view->failcache,
+ client->query.qname, qtype,
+ &flags, &client->tnow);
+#endif
+ if (failcache &&
+ (((flags & NS_FAILCACHE_CD) != 0) ||
+ ((client->message->flags & DNS_MESSAGEFLAG_CD) == 0)))
+ {
+ if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1))) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typename[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_name_format(client->query.qname,
+ namebuf, sizeof(namebuf));
+ dns_rdatatype_format(qtype, typename,
+ sizeof(typename));
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_DEBUG(1),
+ "servfail cache hit %s/%s (%s)",
+ namebuf, typename,
+ ((flags & NS_FAILCACHE_CD) != 0)
+ ? "CD=1"
+ : "CD=0");
+ }
+ client->attributes |= NS_CLIENTATTR_NOSETFC;
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * If it's a SIG query, we'll iterate the node.
+ */
+ if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
+ type = dns_rdatatype_any;
+ else
+ type = qtype;
+
+ restart:
+ CTRACE(ISC_LOG_DEBUG(3), "query_find: restart");
+ want_restart = false;
+ authoritative = false;
+ version = NULL;
+ zversion = NULL;
+ need_wildcardproof = false;
+ rpz = false;
+
+ if (client->view->checknames &&
+ !dns_rdata_checkowner(client->query.qname,
+ client->message->rdclass,
+ qtype, false)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typename[DNS_RDATATYPE_FORMATSIZE];
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+
+ dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(qtype, typename, sizeof(typename));
+ dns_rdataclass_format(client->message->rdclass, classname,
+ sizeof(classname));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
+ "check-names failure %s/%s/%s", namebuf,
+ typename, classname);
+ QUERY_ERROR(DNS_R_REFUSED);
+ goto cleanup;
+ }
+
+ /*
+ * Setup for root key sentinel processing.
+ */
+ if (client->view->root_key_sentinel &&
+ client->query.restarts == 0 &&
+ (qtype == dns_rdatatype_a ||
+ qtype == dns_rdatatype_aaaa) &&
+ (client->message->flags & DNS_MESSAGEFLAG_CD) == 0)
+ {
+ root_key_sentinel_detect(client);
+ }
+
+ /*
+ * First we must find the right database.
+ */
+ options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
+ if (dns_rdatatype_atparent(qtype) &&
+ !dns_name_equal(client->query.qname, dns_rootname))
+ options |= DNS_GETDB_NOEXACT;
+ result = query_getdb(client, client->query.qname, qtype, options,
+ &zone, &db, &version, &is_zone);
+ if (ISC_UNLIKELY((result != ISC_R_SUCCESS || !is_zone) &&
+ qtype == dns_rdatatype_ds &&
+ !RECURSIONOK(client) &&
+ (options & DNS_GETDB_NOEXACT) != 0))
+ {
+ /*
+ * If the query type is DS, look to see if we are
+ * authoritative for the child zone.
+ */
+ dns_db_t *tdb = NULL;
+ dns_zone_t *tzone = NULL;
+ dns_dbversion_t *tversion = NULL;
+
+ tresult = query_getzonedb(client, client->query.qname, qtype,
+ DNS_GETDB_PARTIAL, &tzone, &tdb,
+ &tversion);
+ if (tresult == ISC_R_SUCCESS) {
+ options &= ~DNS_GETDB_NOEXACT;
+ query_putrdataset(client, &rdataset);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ version = NULL;
+ RESTORE(version, tversion);
+ RESTORE(db, tdb);
+ RESTORE(zone, tzone);
+ is_zone = true;
+ result = ISC_R_SUCCESS;
+ } else {
+ if (tdb != NULL)
+ dns_db_detach(&tdb);
+ if (tzone != NULL)
+ dns_zone_detach(&tzone);
+ }
+ }
+ if (result != ISC_R_SUCCESS) {
+ if (result == DNS_R_REFUSED) {
+ if (WANTRECURSION(client)) {
+ inc_stats(client,
+ dns_nsstatscounter_recurserej);
+ } else
+ inc_stats(client, dns_nsstatscounter_authrej);
+ if (!PARTIALANSWER(client))
+ QUERY_ERROR(DNS_R_REFUSED);
+ } else {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: query_getdb failed");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ }
+ goto cleanup;
+ }
+
+ is_staticstub_zone = false;
+ if (is_zone) {
+ authoritative = true;
+ if (zone != NULL &&
+ dns_zone_gettype(zone) == dns_zone_staticstub)
+ is_staticstub_zone = true;
+ }
+
+ if (event == NULL && client->query.restarts == 0) {
+ if (is_zone) {
+ if (zone != NULL) {
+ /*
+ * if is_zone = true, zone = NULL then this is
+ * a DLZ zone. Don't attempt to attach zone.
+ */
+ dns_zone_attach(zone, &client->query.authzone);
+ }
+ dns_db_attach(db, &client->query.authdb);
+ }
+ client->query.authdbset = true;
+
+ /* Track TCP vs UDP stats per zone */
+ if (TCP(client))
+ inc_stats(client, dns_nsstatscounter_tcp);
+ else
+ inc_stats(client, dns_nsstatscounter_udp);
+ }
+
+ db_find:
+ CTRACE(ISC_LOG_DEBUG(3), "query_find: db_find");
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (ISC_UNLIKELY(dbuf == NULL)) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: query_getnamebuf failed (2)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ if (ISC_UNLIKELY(fname == NULL || rdataset == NULL)) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: query_newname failed (2)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: query_newrdataset failed (2)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Now look for an answer in the database. If this is a dns64
+ * AAAA lookup on a rpz database adjust the qname.
+ */
+ if (dns64 && rpz)
+ rpzqname = client->query.rpz_st->p_name;
+ else
+ rpzqname = client->query.qname;
+
+ result = dns_db_findext(db, rpzqname, version, type,
+ client->query.dboptions, client->now,
+ &node, fname, &cm, &ci, rdataset, sigrdataset);
+ /*
+ * Fixup fname and sigrdataset.
+ */
+ if (dns64 && rpz) {
+ isc_result_t rresult;
+
+ rresult = dns_name_copy(client->query.qname, fname, NULL);
+ RUNTIME_CHECK(rresult == ISC_R_SUCCESS);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+
+ if (!is_zone)
+ dns_cache_updatestats(client->view->cache, result);
+
+ resume:
+ CTRACE(ISC_LOG_DEBUG(3), "query_find: resume");
+
+ /*
+ * Rate limit these responses to this client.
+ * Do not delay counting and handling obvious referrals,
+ * since those won't come here again.
+ * Delay handling delegations for which we are certain to recurse and
+ * return here (DNS_R_DELEGATION, not a child of one of our
+ * own zones, and recursion enabled)
+ * Don't mess with responses rewritten by RPZ
+ * Count each response at most once.
+ */
+ if (client->view->rrl != NULL && !HAVECOOKIE(client) &&
+ ((fname != NULL && dns_name_isabsolute(fname)) ||
+ (result == ISC_R_NOTFOUND && !RECURSIONOK(client))) &&
+ !(result == DNS_R_DELEGATION && !is_zone && RECURSIONOK(client)) &&
+ (client->query.rpz_st == NULL ||
+ (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0)&&
+ (client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0)
+ {
+ dns_rdataset_t nc_rdataset;
+ bool wouldlog;
+ char log_buf[DNS_RRL_LOG_BUF_LEN];
+ isc_result_t nc_result, resp_result;
+ dns_rrl_result_t rrl_result;
+
+ client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
+
+ wouldlog = isc_log_wouldlog(ns_g_lctx, DNS_RRL_LOG_DROP);
+ tname = fname;
+ if (result == DNS_R_NXDOMAIN) {
+ /*
+ * Use the database origin name to rate limit NXDOMAIN
+ */
+ if (db != NULL)
+ tname = dns_db_origin(db);
+ resp_result = result;
+ } else if (result == DNS_R_NCACHENXDOMAIN &&
+ rdataset != NULL &&
+ dns_rdataset_isassociated(rdataset) &&
+ (rdataset->attributes &
+ DNS_RDATASETATTR_NEGATIVE) != 0) {
+ /*
+ * Try to use owner name in the negative cache SOA.
+ */
+ dns_fixedname_init(&fixed);
+ dns_rdataset_init(&nc_rdataset);
+ for (nc_result = dns_rdataset_first(rdataset);
+ nc_result == ISC_R_SUCCESS;
+ nc_result = dns_rdataset_next(rdataset)) {
+ dns_ncache_current(rdataset,
+ dns_fixedname_name(&fixed),
+ &nc_rdataset);
+ if (nc_rdataset.type == dns_rdatatype_soa) {
+ dns_rdataset_disassociate(&nc_rdataset);
+ tname = dns_fixedname_name(&fixed);
+ break;
+ }
+ dns_rdataset_disassociate(&nc_rdataset);
+ }
+ resp_result = DNS_R_NXDOMAIN;
+ } else if (result == DNS_R_NXRRSET ||
+ result == DNS_R_EMPTYNAME) {
+ resp_result = DNS_R_NXRRSET;
+ } else if (result == DNS_R_DELEGATION) {
+ resp_result = result;
+ } else if (result == ISC_R_NOTFOUND) {
+ /*
+ * Handle referral to ".", including when recursion
+ * is off or not requested and the hints have not
+ * been loaded or we have "additional-from-cache no".
+ */
+ tname = dns_rootname;
+ resp_result = DNS_R_DELEGATION;
+ } else {
+ resp_result = ISC_R_SUCCESS;
+ }
+ rrl_result = dns_rrl(client->view, &client->peeraddr,
+ TCP(client), client->message->rdclass,
+ qtype, tname, resp_result, client->now,
+ wouldlog, log_buf, sizeof(log_buf));
+ if (rrl_result != DNS_RRL_RESULT_OK) {
+ /*
+ * Log dropped or slipped responses in the query
+ * category so that requests are not silently lost.
+ * Starts of rate-limited bursts are logged in
+ * DNS_LOGCATEGORY_RRL.
+ *
+ * Dropped responses are counted with dropped queries
+ * in QryDropped while slipped responses are counted
+ * with other truncated responses in RespTruncated.
+ */
+ if (wouldlog) {
+ ns_client_log(client, DNS_LOGCATEGORY_RRL,
+ NS_LOGMODULE_QUERY,
+ DNS_RRL_LOG_DROP,
+ "%s", log_buf);
+ }
+ if (!client->view->rrl->log_only) {
+ if (rrl_result == DNS_RRL_RESULT_DROP) {
+ /*
+ * These will also be counted in
+ * dns_nsstatscounter_dropped
+ */
+ inc_stats(client,
+ dns_nsstatscounter_ratedropped);
+ QUERY_ERROR(DNS_R_DROP);
+ } else {
+ /*
+ * These will also be counted in
+ * dns_nsstatscounter_truncatedresp
+ */
+ inc_stats(client,
+ dns_nsstatscounter_rateslipped);
+ if (WANTCOOKIE(client)) {
+ client->message->flags &=
+ ~DNS_MESSAGEFLAG_AA;
+ client->message->flags &=
+ ~DNS_MESSAGEFLAG_AD;
+ client->message->rcode =
+ dns_rcode_badcookie;
+ } else {
+ client->message->flags |=
+ DNS_MESSAGEFLAG_TC;
+ if (resp_result ==
+ DNS_R_NXDOMAIN)
+ client->message->rcode =
+ dns_rcode_nxdomain;
+ }
+ }
+ goto cleanup;
+ }
+ }
+ } else if (!TCP(client) && client->view->requireservercookie &&
+ WANTCOOKIE(client) && !HAVECOOKIE(client)) {
+ client->message->flags &= ~DNS_MESSAGEFLAG_AA;
+ client->message->flags &= ~DNS_MESSAGEFLAG_AD;
+ client->message->rcode = dns_rcode_badcookie;
+ goto cleanup;
+ }
+
+ if (!RECURSING(client) &&
+ !dns_name_equal(client->query.qname, dns_rootname))
+ {
+ isc_result_t rresult;
+
+ rresult = rpz_rewrite(client, qtype, result, resuming,
+ rdataset, sigrdataset);
+ rpz_st = client->query.rpz_st;
+ switch (rresult) {
+ case ISC_R_SUCCESS:
+ break;
+ case DNS_R_DISALLOWED:
+ goto norpz;
+ case DNS_R_DELEGATION:
+ /*
+ * recursing for NS names or addresses,
+ * so save the main query state
+ */
+ rpz_st->q.qtype = qtype;
+ rpz_st->q.is_zone = is_zone;
+ rpz_st->q.authoritative = authoritative;
+ SAVE(rpz_st->q.zone, zone);
+ SAVE(rpz_st->q.db, db);
+ SAVE(rpz_st->q.node, node);
+ SAVE(rpz_st->q.rdataset, rdataset);
+ SAVE(rpz_st->q.sigrdataset, sigrdataset);
+ dns_name_copy(fname, rpz_st->fname, NULL);
+ rpz_st->q.result = result;
+ client->query.attributes |= NS_QUERYATTR_RECURSING;
+ goto cleanup;
+ default:
+ RECURSE_ERROR(rresult);
+ goto cleanup;
+ }
+
+ if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS)
+ rpz_st->state |= DNS_RPZ_REWRITTEN;
+ if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
+ rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU &&
+ (rpz_st->m.policy != DNS_RPZ_POLICY_TCP_ONLY ||
+ !TCP(client)) &&
+ rpz_st->m.policy != DNS_RPZ_POLICY_ERROR)
+ {
+ /*
+ * We got a hit and are going to answer with our
+ * fiction. Ensure that we answer with the name
+ * we looked up even if we were stopped short
+ * in recursion or for a deferral.
+ */
+ rresult = dns_name_copy(client->query.qname,
+ fname, NULL);
+ RUNTIME_CHECK(rresult == ISC_R_SUCCESS);
+ rpz_clean(&zone, &db, &node, NULL);
+ if (rpz_st->m.rdataset != NULL) {
+ query_putrdataset(client, &rdataset);
+ RESTORE(rdataset, rpz_st->m.rdataset);
+ } else if (rdataset != NULL &&
+ dns_rdataset_isassociated(rdataset)) {
+ dns_rdataset_disassociate(rdataset);
+ }
+ version = NULL;
+
+ RESTORE(node, rpz_st->m.node);
+ RESTORE(db, rpz_st->m.db);
+ RESTORE(version, rpz_st->m.version);
+ RESTORE(zone, rpz_st->m.zone);
+
+ switch (rpz_st->m.policy) {
+ case DNS_RPZ_POLICY_TCP_ONLY:
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ if (result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NCACHENXDOMAIN)
+ client->message->rcode =
+ dns_rcode_nxdomain;
+ rpz_log_rewrite(client, false,
+ rpz_st->m.policy,
+ rpz_st->m.type, zone,
+ rpz_st->p_name, NULL,
+ rpz_st->m.rpz->num);
+ goto cleanup;
+ case DNS_RPZ_POLICY_DROP:
+ QUERY_ERROR(DNS_R_DROP);
+ rpz_log_rewrite(client, false,
+ rpz_st->m.policy,
+ rpz_st->m.type, zone,
+ rpz_st->p_name, NULL,
+ rpz_st->m.rpz->num);
+ goto cleanup;
+ case DNS_RPZ_POLICY_NXDOMAIN:
+ result = DNS_R_NXDOMAIN;
+ nxrewrite = true;
+ rpz = true;
+ break;
+ case DNS_RPZ_POLICY_NODATA:
+ result = DNS_R_NXRRSET;
+ nxrewrite = true;
+ rpz = true;
+ break;
+ case DNS_RPZ_POLICY_RECORD:
+ result = rpz_st->m.result;
+ if (qtype == dns_rdatatype_any &&
+ result != DNS_R_CNAME) {
+ /*
+ * We will add all of the rdatasets of
+ * the node by iterating later,
+ * and set the TTL then.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ } else {
+ /*
+ * We will add this rdataset.
+ */
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ rpz_st->m.ttl);
+ }
+ rpz = true;
+ break;
+ case DNS_RPZ_POLICY_WILDCNAME:
+ result = dns_rdataset_first(rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname,
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+ result = rpz_add_cname(client, rpz_st,
+ &cname.cname,
+ fname, dbuf);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ fname = NULL;
+ want_restart = true;
+ goto cleanup;
+ case DNS_RPZ_POLICY_CNAME:
+ /*
+ * Add overridding CNAME from a named.conf
+ * response-policy statement
+ */
+ result = rpz_add_cname(client, rpz_st,
+ &rpz_st->m.rpz->cname,
+ fname, dbuf);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ fname = NULL;
+ want_restart = true;
+ goto cleanup;
+ default:
+ INSIST(0);
+ }
+
+ /*
+ * Turn off DNSSEC because the results of a
+ * response policy zone cannot verify.
+ */
+ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
+ NS_CLIENTATTR_WANTAD);
+ client->message->flags &= ~DNS_MESSAGEFLAG_AD;
+ query_putrdataset(client, &sigrdataset);
+ is_zone = true;
+ rpz_log_rewrite(client, false, rpz_st->m.policy,
+ rpz_st->m.type, zone, rpz_st->p_name,
+ NULL, rpz_st->m.rpz->num);
+ }
+ }
+
+ norpz:
+ /*
+ * If required, handle special "root-key-sentinel-is-ta-<keyid>" and
+ * "root-key-sentinel-not-ta-<keyid>" labels by returning SERVFAIL.
+ */
+ if (root_key_sentinel_return_servfail(client, is_zone,
+ rdataset, result))
+ {
+ /*
+ * Don't record this response in the SERVFAIL cache.
+ */
+ client->attributes |= NS_CLIENTATTR_NOSETFC;
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ /*
+ * This case is handled in the main line below.
+ */
+ break;
+ case DNS_R_GLUE:
+ case DNS_R_ZONECUT:
+ /*
+ * These cases are handled in the main line below.
+ */
+ INSIST(is_zone);
+ authoritative = false;
+ break;
+ case ISC_R_NOTFOUND:
+ /*
+ * The cache doesn't even have the root NS. Get them from
+ * the hints DB.
+ */
+ INSIST(!is_zone);
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ if (client->view->hints == NULL) {
+ /* We have no hints. */
+ result = ISC_R_FAILURE;
+ } else {
+ dns_db_attach(client->view->hints, &db);
+ result = dns_db_findext(db, dns_rootname,
+ NULL, dns_rdatatype_ns,
+ 0, client->now, &node,
+ fname, &cm, &ci,
+ rdataset, sigrdataset);
+ }
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Nonsensical root hints may require cleanup.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ /*
+ * We don't have any root server hints, but
+ * we may have working forwarders, so try to
+ * recurse anyway.
+ */
+ if (RECURSIONOK(client)) {
+ INSIST(!REDIRECT(client));
+ result = query_recurse(client, qtype,
+ client->query.qname,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS) {
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ if (dns64)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64;
+ if (dns64_exclude)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64EXCLUDE;
+ } else
+ RECURSE_ERROR(result);
+ goto cleanup;
+ } else {
+ /* Unable to give root server referral. */
+ CTRACE(ISC_LOG_ERROR,
+ "unable to give root server referral");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+ /*
+ * XXXRTH We should trigger root server priming here.
+ */
+ /* FALLTHROUGH */
+ case DNS_R_DELEGATION:
+ authoritative = false;
+ if (is_zone) {
+ /*
+ * Look to see if we are authoritative for the
+ * child zone if the query type is DS.
+ */
+ if (!RECURSIONOK(client) &&
+ (options & DNS_GETDB_NOEXACT) != 0 &&
+ qtype == dns_rdatatype_ds) {
+ dns_db_t *tdb = NULL;
+ dns_zone_t *tzone = NULL;
+ dns_dbversion_t *tversion = NULL;
+ result = query_getzonedb(client,
+ client->query.qname,
+ qtype,
+ DNS_GETDB_PARTIAL,
+ &tzone, &tdb,
+ &tversion);
+ if (result == ISC_R_SUCCESS) {
+ options &= ~DNS_GETDB_NOEXACT;
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client,
+ &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client,
+ &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ version = NULL;
+ RESTORE(version, tversion);
+ RESTORE(db, tdb);
+ RESTORE(zone, tzone);
+ authoritative = true;
+ goto db_find;
+ }
+ if (tdb != NULL)
+ dns_db_detach(&tdb);
+ if (tzone != NULL)
+ dns_zone_detach(&tzone);
+ }
+ /*
+ * We're authoritative for an ancestor of QNAME.
+ */
+ if (!USECACHE(client) || !RECURSIONOK(client)) {
+ bool detach = false;
+
+ dns_fixedname_init(&fixed);
+ dns_name_copy(fname,
+ dns_fixedname_name(&fixed), NULL);
+
+ /*
+ * If we don't have a cache, this is the best
+ * answer.
+ *
+ * If the client is making a nonrecursive
+ * query we always give out the authoritative
+ * delegation. This way even if we get
+ * junk in our cache, we won't fail in our
+ * role as the delegating authority if another
+ * nameserver asks us about a delegated
+ * subzone.
+ *
+ * We enable the retrieval of glue for this
+ * database by setting client->query.gluedb.
+ */
+ if (db != NULL &&
+ client->query.gluedb == NULL) {
+ dns_db_attach(db,
+ &client->query.gluedb);
+ detach = true;
+ }
+ client->query.isreferral = true;
+ /*
+ * We must ensure NOADDITIONAL is off,
+ * because the generation of
+ * additional data is required in
+ * delegations.
+ */
+ client->query.attributes &=
+ ~NS_QUERYATTR_NOADDITIONAL;
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &fname,
+ &rdataset, sigrdatasetp,
+ dbuf, DNS_SECTION_AUTHORITY);
+ if (detach) {
+ dns_db_detach(&client->query.gluedb);
+ }
+ if (WANTDNSSEC(client))
+ query_addds(client, db, node, version,
+ dns_fixedname_name(&fixed));
+ } else {
+ /*
+ * We might have a better answer or delegation
+ * in the cache. We'll remember the current
+ * values of fname, rdataset, and sigrdataset.
+ * We'll then go looking for QNAME in the
+ * cache. If we find something better, we'll
+ * use it instead.
+ */
+ query_keepname(client, fname, dbuf);
+ dns_db_detachnode(db, &node);
+ SAVE(zdb, db);
+ SAVE(zfname, fname);
+ SAVE(zversion, version);
+ SAVE(zrdataset, rdataset);
+ SAVE(zsigrdataset, sigrdataset);
+ dns_db_attach(client->view->cachedb, &db);
+ is_zone = false;
+ goto db_find;
+ }
+ } else {
+ if (zfname != NULL &&
+ (!dns_name_issubdomain(fname, zfname) ||
+ (is_staticstub_zone &&
+ dns_name_equal(fname, zfname)))) {
+ /*
+ * In the following cases use "authoritative"
+ * data instead of the cache delegation:
+ * 1. We've already got a delegation from
+ * authoritative data, and it is better
+ * than what we found in the cache.
+ * 2. The query name matches the origin name
+ * of a static-stub zone. This needs to be
+ * considered for the case where the NS of
+ * the static-stub zone and the cached NS
+ * are different. We still need to contact
+ * the nameservers configured in the
+ * static-stub zone.
+ */
+ query_releasename(client, &fname);
+ /*
+ * We've already done query_keepname() on
+ * zfname, so we must set dbuf to NULL to
+ * prevent query_addrrset() from trying to
+ * call query_keepname() again.
+ */
+ dbuf = NULL;
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client,
+ &sigrdataset);
+ version = NULL;
+
+ RESTORE(fname, zfname);
+ RESTORE(version, zversion);
+ RESTORE(rdataset, zrdataset);
+ RESTORE(sigrdataset, zsigrdataset);
+ /*
+ * We don't clean up zdb here because we
+ * may still need it. It will get cleaned
+ * up by the main cleanup code.
+ */
+ }
+
+ if (RECURSIONOK(client)) {
+ /*
+ * Recurse!
+ */
+ INSIST(!REDIRECT(client));
+ if (dns_rdatatype_atparent(type))
+ result = query_recurse(client, qtype,
+ client->query.qname,
+ NULL, NULL, resuming);
+ else if (dns64)
+ result = query_recurse(client,
+ dns_rdatatype_a,
+ client->query.qname,
+ NULL, NULL, resuming);
+ else
+ result = query_recurse(client, qtype,
+ client->query.qname,
+ fname, rdataset,
+ resuming);
+
+ if (result == ISC_R_SUCCESS) {
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ if (dns64)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64;
+ if (dns64_exclude)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64EXCLUDE;
+ } else if (result == DNS_R_DUPLICATE ||
+ result == DNS_R_DROP)
+ QUERY_ERROR(result);
+ else
+ RECURSE_ERROR(result);
+ } else {
+ bool detach = false;
+
+ dns_fixedname_init(&fixed);
+ dns_name_copy(fname,
+ dns_fixedname_name(&fixed), NULL);
+ /*
+ * This is the best answer.
+ */
+ client->query.attributes |=
+ NS_QUERYATTR_CACHEGLUEOK;
+ client->query.isreferral = true;
+
+ if (zdb != NULL &&
+ client->query.gluedb == NULL) {
+ dns_db_attach(zdb,
+ &client->query.gluedb);
+ detach = true;
+ }
+
+ /*
+ * We must ensure NOADDITIONAL is off,
+ * because the generation of
+ * additional data is required in
+ * delegations.
+ */
+ client->query.attributes &=
+ ~NS_QUERYATTR_NOADDITIONAL;
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &fname,
+ &rdataset, sigrdatasetp,
+ dbuf, DNS_SECTION_AUTHORITY);
+ client->query.attributes &=
+ ~NS_QUERYATTR_CACHEGLUEOK;
+ if (detach) {
+ dns_db_detach(&client->query.gluedb);
+ }
+
+ if (WANTDNSSEC(client))
+ query_addds(client, db, node, version,
+ dns_fixedname_name(&fixed));
+ }
+ }
+ goto cleanup;
+
+ case DNS_R_EMPTYNAME:
+ case DNS_R_NXRRSET:
+ iszone_nxrrset:
+ INSIST(is_zone);
+
+#ifdef dns64_bis_return_excluded_addresses
+ if (dns64)
+#else
+ if (dns64 && !dns64_exclude)
+#endif
+ {
+ /*
+ * Restore the answers from the previous AAAA lookup.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ RESTORE(rdataset, client->query.dns64_aaaa);
+ RESTORE(sigrdataset, client->query.dns64_sigaaaa);
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: "
+ "query_getnamebuf failed (3)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: "
+ "query_newname failed (3)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+ dns_name_copy(client->query.qname, fname, NULL);
+ dns64 = false;
+#ifdef dns64_bis_return_excluded_addresses
+ /*
+ * Resume the diverted processing of the AAAA response?
+ */
+ if (dns64_excluded)
+ break;
+#endif
+ } else if (result == DNS_R_NXRRSET &&
+ !ISC_LIST_EMPTY(client->view->dns64) &&
+ client->message->rdclass == dns_rdataclass_in &&
+ qtype == dns_rdatatype_aaaa)
+ {
+ /*
+ * Look to see if there are A records for this
+ * name.
+ */
+ SAVE(client->query.dns64_aaaa, rdataset);
+ SAVE(client->query.dns64_sigaaaa, sigrdataset);
+ client->query.dns64_ttl = dns64_ttl(db, version);
+ query_releasename(client, &fname);
+ dns_db_detachnode(db, &node);
+ type = qtype = dns_rdatatype_a;
+ dns64 = true;
+ goto db_find;
+ }
+
+ /*
+ * Look for a NSEC3 record if we don't have a NSEC record.
+ */
+ nxrrset_rrsig:
+ if (redirected)
+ goto cleanup;
+ if (!dns_rdataset_isassociated(rdataset) &&
+ WANTDNSSEC(client)) {
+ if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
+ dns_name_t *found;
+ dns_name_t *qname;
+
+ found = dns_fixedname_initname(&fixed);
+ qname = client->query.qname;
+
+ query_findclosestnsec3(qname, db, version,
+ client, rdataset,
+ sigrdataset, fname,
+ true, found);
+ /*
+ * Did we find the closest provable encloser
+ * instead? If so add the nearest to the
+ * closest provable encloser.
+ */
+ if (dns_rdataset_isassociated(rdataset) &&
+ !dns_name_equal(qname, found) &&
+ !(ns_g_nonearest &&
+ qtype != dns_rdatatype_ds))
+ {
+ unsigned int count;
+ unsigned int skip;
+
+ /*
+ * Add the closest provable encloser.
+ */
+ query_addrrset(client, &fname,
+ &rdataset, &sigrdataset,
+ dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ count = dns_name_countlabels(found)
+ + 1;
+ skip = dns_name_countlabels(qname) -
+ count;
+ dns_name_getlabelsequence(qname, skip,
+ count,
+ found);
+
+ fixfname(client, &fname, &dbuf, &b);
+ fixrdataset(client, &rdataset);
+ fixrdataset(client, &sigrdataset);
+ if (fname == NULL ||
+ rdataset == NULL ||
+ sigrdataset == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: "
+ "failure getting "
+ "closest encloser");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ /*
+ * 'nearest' doesn't exist so
+ * 'exist' is set to false.
+ */
+ query_findclosestnsec3(found, db,
+ version,
+ client,
+ rdataset,
+ sigrdataset,
+ fname,
+ false,
+ NULL);
+ }
+ } else {
+ query_releasename(client, &fname);
+ query_addwildcardproof(client, db, version,
+ client->query.qname,
+ false, true);
+ }
+ }
+ if (dns_rdataset_isassociated(rdataset)) {
+ /*
+ * If we've got a NSEC record, we need to save the
+ * name now because we're going call query_addsoa()
+ * below, and it needs to use the name buffer.
+ */
+ query_keepname(client, fname, dbuf);
+ } else if (fname != NULL) {
+ /*
+ * We're not going to use fname, and need to release
+ * our hold on the name buffer so query_addsoa()
+ * may use it.
+ */
+ query_releasename(client, &fname);
+ }
+
+ /*
+ * Add SOA to the additional section if generated by a RPZ
+ * rewrite.
+ */
+ associated = dns_rdataset_isassociated(rdataset);
+ section = nxrewrite ? DNS_SECTION_ADDITIONAL :
+ DNS_SECTION_AUTHORITY;
+
+ result = query_addsoa(client, db, version, UINT32_MAX,
+ associated, section);
+ if (result != ISC_R_SUCCESS) {
+ QUERY_ERROR(result);
+ goto cleanup;
+ }
+
+ /*
+ * Add NSEC record if we found one.
+ */
+ if (WANTDNSSEC(client)) {
+ if (dns_rdataset_isassociated(rdataset))
+ query_addnxrrsetnsec(client, db, version,
+ &fname, &rdataset,
+ &sigrdataset);
+ }
+ goto cleanup;
+
+ case DNS_R_EMPTYWILD:
+ empty_wild = true;
+ /* FALLTHROUGH */
+
+ case DNS_R_NXDOMAIN:
+ INSIST(is_zone || REDIRECT(client));
+ if (!empty_wild) {
+ tresult = redirect(client, fname, rdataset, &node,
+ &db, &version, type);
+ if (tresult == ISC_R_SUCCESS) {
+ inc_stats(client,
+ dns_nsstatscounter_nxdomainredirect);
+ break;
+ }
+ if (tresult == DNS_R_NXRRSET) {
+ redirected = true;
+ goto iszone_nxrrset;
+ }
+ if (tresult == DNS_R_NCACHENXRRSET) {
+ redirected = true;
+ is_zone = false;
+ goto ncache_nxrrset;
+ }
+ tresult = redirect2(client, fname, rdataset, &node,
+ &db, &version, type, &is_zone);
+ if (tresult == DNS_R_CONTINUE) {
+ inc_stats(client,
+ dns_nsstatscounter_nxdomainredirect_rlookup);
+ client->query.redirect.qtype = qtype;
+ INSIST(rdataset != NULL);
+ SAVE(client->query.redirect.rdataset, rdataset);
+ SAVE(client->query.redirect.sigrdataset,
+ sigrdataset);
+ SAVE(client->query.redirect.db, db);
+ SAVE(client->query.redirect.node, node);
+ SAVE(client->query.redirect.zone, zone);
+ client->query.redirect.result = DNS_R_NXDOMAIN;
+ dns_name_copy(fname,
+ client->query.redirect.fname,
+ NULL);
+ client->query.redirect.authoritative =
+ authoritative;
+ client->query.redirect.is_zone = is_zone;
+ goto cleanup;
+ }
+ if (tresult == ISC_R_SUCCESS) {
+ inc_stats(client,
+ dns_nsstatscounter_nxdomainredirect);
+ break;
+ }
+ if (tresult == DNS_R_NXRRSET) {
+ redirected = true;
+ goto iszone_nxrrset;
+ }
+ if (tresult == DNS_R_NCACHENXRRSET) {
+ redirected = true;
+ is_zone = false;
+ goto ncache_nxrrset;
+ }
+ }
+ if (dns_rdataset_isassociated(rdataset)) {
+ /*
+ * If we've got a NSEC record, we need to save the
+ * name now because we're going call query_addsoa()
+ * below, and it needs to use the name buffer.
+ */
+ query_keepname(client, fname, dbuf);
+ } else if (fname != NULL) {
+ /*
+ * We're not going to use fname, and need to release
+ * our hold on the name buffer so query_addsoa()
+ * may use it.
+ */
+ query_releasename(client, &fname);
+ }
+
+ /*
+ * Add SOA to the additional section if generated by a
+ * RPZ rewrite.
+ *
+ * If the query was for a SOA record force the
+ * ttl to zero so that it is possible for clients to find
+ * the containing zone of an arbitrary name with a stub
+ * resolver and not have it cached.
+ */
+ associated = dns_rdataset_isassociated(rdataset);
+ section = nxrewrite ? DNS_SECTION_ADDITIONAL :
+ DNS_SECTION_AUTHORITY;
+ ttl = UINT32_MAX;
+ if (!nxrewrite && qtype == dns_rdatatype_soa &&
+ zone != NULL && dns_zone_getzeronosoattl(zone))
+ ttl = 0;
+ result = query_addsoa(client, db, version, ttl, associated,
+ section);
+ if (result != ISC_R_SUCCESS) {
+ QUERY_ERROR(result);
+ goto cleanup;
+ }
+
+ if (WANTDNSSEC(client)) {
+ /*
+ * Add NSEC record if we found one.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ query_addrrset(client, &fname, &rdataset,
+ &sigrdataset,
+ NULL, DNS_SECTION_AUTHORITY);
+ query_addwildcardproof(client, db, version,
+ client->query.qname, false,
+ false);
+ }
+
+ /*
+ * Set message rcode.
+ */
+ if (empty_wild)
+ client->message->rcode = dns_rcode_noerror;
+ else
+ client->message->rcode = dns_rcode_nxdomain;
+ goto cleanup;
+
+ case DNS_R_NCACHENXDOMAIN:
+ tresult = redirect(client, fname, rdataset, &node,
+ &db, &version, type);
+ if (tresult == ISC_R_SUCCESS) {
+ inc_stats(client,
+ dns_nsstatscounter_nxdomainredirect);
+ break;
+ }
+ if (tresult == DNS_R_NXRRSET) {
+ redirected = true;
+ is_zone = true;
+ goto iszone_nxrrset;
+ }
+ if (tresult == DNS_R_NCACHENXRRSET) {
+ redirected = true;
+ result = tresult;
+ goto ncache_nxrrset;
+ }
+ tresult = redirect2(client, fname, rdataset, &node,
+ &db, &version, type, &is_zone);
+ if (tresult == DNS_R_CONTINUE) {
+ inc_stats(client,
+ dns_nsstatscounter_nxdomainredirect_rlookup);
+ SAVE(client->query.redirect.db, db);
+ SAVE(client->query.redirect.node, node);
+ SAVE(client->query.redirect.zone, zone);
+ client->query.redirect.qtype = qtype;
+ INSIST(rdataset != NULL);
+ SAVE(client->query.redirect.rdataset, rdataset);
+ SAVE(client->query.redirect.sigrdataset, sigrdataset);
+ client->query.redirect.result = DNS_R_NCACHENXDOMAIN;
+ dns_name_copy(fname, client->query.redirect.fname,
+ NULL);
+ client->query.redirect.authoritative = authoritative;
+ client->query.redirect.is_zone = is_zone;
+ goto cleanup;
+ }
+ if (tresult == ISC_R_SUCCESS) {
+ inc_stats(client,
+ dns_nsstatscounter_nxdomainredirect);
+ break;
+ }
+ if (tresult == DNS_R_NXRRSET) {
+ redirected = true;
+ is_zone = true;
+ goto iszone_nxrrset;
+ }
+ if (tresult == DNS_R_NCACHENXRRSET) {
+ redirected = true;
+ result = tresult;
+ goto ncache_nxrrset;
+ }
+ /* FALLTHROUGH */
+
+ case DNS_R_NCACHENXRRSET:
+ ncache_nxrrset:
+ INSIST(!is_zone);
+ authoritative = false;
+ /*
+ * Set message rcode, if required.
+ */
+ if (result == DNS_R_NCACHENXDOMAIN)
+ client->message->rcode = dns_rcode_nxdomain;
+ /*
+ * Look for RFC 1918 leakage from Internet.
+ */
+ if (result == DNS_R_NCACHENXDOMAIN &&
+ qtype == dns_rdatatype_ptr &&
+ client->message->rdclass == dns_rdataclass_in &&
+ dns_name_countlabels(fname) == 7)
+ warn_rfc1918(client, fname, rdataset);
+
+#ifdef dns64_bis_return_excluded_addresses
+ if (dns64)
+#else
+ if (dns64 && !dns64_exclude)
+#endif
+ {
+ /*
+ * Restore the answers from the previous AAAA lookup.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ RESTORE(rdataset, client->query.dns64_aaaa);
+ RESTORE(sigrdataset, client->query.dns64_sigaaaa);
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: "
+ "query_getnamebuf failed (4)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: "
+ "query_newname failed (4)");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+ dns_name_copy(client->query.qname, fname, NULL);
+ dns64 = false;
+#ifdef dns64_bis_return_excluded_addresses
+ if (dns64_excluded)
+ break;
+#endif
+ } else if (result == DNS_R_NCACHENXRRSET &&
+ !ISC_LIST_EMPTY(client->view->dns64) &&
+ client->message->rdclass == dns_rdataclass_in &&
+ qtype == dns_rdatatype_aaaa)
+ {
+ /*
+ * Look to see if there are A records for this
+ * name.
+ */
+
+ /*
+ * If the ttl is zero we need to workout if we have just
+ * decremented to zero or if there was no negative cache
+ * ttl in the answer.
+ */
+ if (rdataset->ttl != 0)
+ client->query.dns64_ttl = rdataset->ttl;
+ else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS)
+ client->query.dns64_ttl = 0;
+ SAVE(client->query.dns64_aaaa, rdataset);
+ SAVE(client->query.dns64_sigaaaa, sigrdataset);
+ query_releasename(client, &fname);
+ dns_db_detachnode(db, &node);
+ type = qtype = dns_rdatatype_a;
+ dns64 = true;
+ goto db_find;
+ }
+
+ /*
+ * We don't call query_addrrset() because we don't need any
+ * of its extra features (and things would probably break!).
+ */
+ if (dns_rdataset_isassociated(rdataset)) {
+ query_keepname(client, fname, dbuf);
+ dns_message_addname(client->message, fname,
+ DNS_SECTION_AUTHORITY);
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ fname = NULL;
+ rdataset = NULL;
+ }
+ goto cleanup;
+
+ case DNS_R_CNAME:
+ /*
+ * If we have a zero ttl from the cache refetch it.
+ */
+ if (!is_zone && !resuming && rdataset->ttl == 0 &&
+ RECURSIONOK(client))
+ {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ INSIST(!REDIRECT(client));
+ result = query_recurse(client, qtype,
+ client->query.qname,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS) {
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ if (dns64)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64;
+ if (dns64_exclude)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64EXCLUDE;
+ } else
+ RECURSE_ERROR(result);
+ goto cleanup;
+ }
+
+ /*
+ * Keep a copy of the rdataset. We have to do this because
+ * query_addrrset may clear 'rdataset' (to prevent the
+ * cleanup code from cleaning it up).
+ */
+ trdataset = rdataset;
+ /*
+ * Add the CNAME to the answer section.
+ */
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ if (WANTDNSSEC(client) &&
+ (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
+ {
+ dns_fixedname_init(&wildcardname);
+ dns_name_copy(fname, dns_fixedname_name(&wildcardname),
+ NULL);
+ need_wildcardproof = true;
+ }
+ if (NOQNAME(rdataset) && WANTDNSSEC(client))
+ noqname = rdataset;
+ else
+ noqname = NULL;
+ if (!is_zone && RECURSIONOK(client))
+ query_prefetch(client, fname, rdataset);
+ query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
+ DNS_SECTION_ANSWER);
+ if (noqname != NULL)
+ query_addnoqnameproof(client, noqname);
+ /*
+ * We set the PARTIALANSWER attribute so that if anything goes
+ * wrong later on, we'll return what we've got so far.
+ */
+ client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
+ /*
+ * Reset qname to be the target name of the CNAME and restart
+ * the query.
+ */
+ tname = NULL;
+ result = dns_message_gettempname(client->message, &tname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataset_first(trdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_rdataset_current(trdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_name_init(tname, NULL);
+ result = dns_name_dup(&cname.cname, client->mctx, tname);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ dns_rdata_freestruct(&cname);
+ goto cleanup;
+ }
+ dns_rdata_freestruct(&cname);
+ ns_client_qnamereplace(client, tname);
+ want_restart = true;
+ if (!WANTRECURSION(client))
+ options |= DNS_GETDB_NOLOG;
+ goto addauth;
+ case DNS_R_DNAME:
+ /*
+ * Compare the current qname to the found name. We need
+ * to know how many labels and bits are in common because
+ * we're going to have to split qname later on.
+ */
+ namereln = dns_name_fullcompare(client->query.qname, fname,
+ &order, &nlabels);
+ INSIST(namereln == dns_namereln_subdomain);
+ /*
+ * Keep a copy of the rdataset. We have to do this because
+ * query_addrrset may clear 'rdataset' (to prevent the
+ * cleanup code from cleaning it up).
+ */
+ trdataset = rdataset;
+ /*
+ * Add the DNAME to the answer section.
+ */
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ if (WANTDNSSEC(client) &&
+ (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
+ {
+ dns_fixedname_init(&wildcardname);
+ dns_name_copy(fname, dns_fixedname_name(&wildcardname),
+ NULL);
+ need_wildcardproof = true;
+ }
+ if (!is_zone && RECURSIONOK(client))
+ query_prefetch(client, fname, rdataset);
+ query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
+ DNS_SECTION_ANSWER);
+ /*
+ * We set the PARTIALANSWER attribute so that if anything goes
+ * wrong later on, we'll return what we've got so far.
+ */
+ client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
+ /*
+ * Get the target name of the DNAME.
+ */
+ tname = NULL;
+ result = dns_message_gettempname(client->message, &tname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataset_first(trdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_rdataset_current(trdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dname, NULL);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_name_clone(&dname.dname, tname);
+ dns_rdata_freestruct(&dname);
+ /*
+ * Construct the new qname consisting of
+ * <found name prefix>.<dname target>
+ */
+ prefix = dns_fixedname_initname(&fixed);
+ dns_name_split(client->query.qname, nlabels, prefix, NULL);
+ INSIST(fname == NULL);
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ result = dns_name_concatenate(prefix, tname, fname, NULL);
+ dns_message_puttempname(client->message, &tname);
+
+ /*
+ * RFC2672, section 4.1, subsection 3c says
+ * we should return YXDOMAIN if the constructed
+ * name would be too long.
+ */
+ if (result == DNS_R_NAMETOOLONG)
+ client->message->rcode = dns_rcode_yxdomain;
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ query_keepname(client, fname, dbuf);
+ /*
+ * Synthesize a CNAME consisting of
+ * <old qname> <dname ttl> CNAME <new qname>
+ * with <dname trust value>
+ *
+ * Synthesize a CNAME so old old clients that don't understand
+ * DNAME can chain.
+ *
+ * We do not try to synthesize a signature because we hope
+ * that security aware servers will understand DNAME. Also,
+ * even if we had an online key, making a signature
+ * on-the-fly is costly, and not really legitimate anyway
+ * since the synthesized CNAME is NOT in the zone.
+ */
+ result = query_add_cname(client, client->query.qname, fname,
+ trdataset->trust, trdataset->ttl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ /*
+ * Switch to the new qname and restart.
+ */
+ ns_client_qnamereplace(client, fname);
+ fname = NULL;
+ want_restart = true;
+ if (!WANTRECURSION(client))
+ options |= DNS_GETDB_NOLOG;
+ goto addauth;
+ default:
+ /*
+ * Something has gone wrong.
+ */
+ snprintf(errmsg, sizeof(errmsg) - 1,
+ "query_find: unexpected error after resuming: %s",
+ isc_result_totext(result));
+ CTRACE(ISC_LOG_ERROR, errmsg);
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+
+ if (WANTDNSSEC(client) &&
+ (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
+ {
+ dns_fixedname_init(&wildcardname);
+ dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
+ need_wildcardproof = true;
+ }
+
+#ifdef ALLOW_FILTER_AAAA
+ /*
+ * The filter-aaaa-on-v4 option should suppress AAAAs for IPv4
+ * clients if there is an A; filter-aaaa-on-v6 option does the same
+ * for IPv6 clients.
+ */
+ client->filter_aaaa = dns_aaaa_ok;
+ if (client->view->v4_aaaa != dns_aaaa_ok ||
+ client->view->v6_aaaa != dns_aaaa_ok)
+ {
+ result = ns_client_checkaclsilent(client, NULL,
+ client->view->aaaa_acl,
+ true);
+ if (result == ISC_R_SUCCESS &&
+ client->view->v4_aaaa != dns_aaaa_ok &&
+ is_v4_client(client))
+ client->filter_aaaa = client->view->v4_aaaa;
+ else if (result == ISC_R_SUCCESS &&
+ client->view->v6_aaaa != dns_aaaa_ok &&
+ is_v6_client(client))
+ client->filter_aaaa = client->view->v6_aaaa;
+ }
+
+#endif
+
+ if (type == dns_rdatatype_any) {
+ /*
+ * For minimal-any, we only add records that
+ * match this type or cover this type.
+ */
+ dns_rdatatype_t onetype = 0;
+#ifdef ALLOW_FILTER_AAAA
+ bool have_aaaa, have_a, have_sig;
+
+ /*
+ * If we are not authoritative, assume there is a A
+ * even in if it is not in our cache. This assumption could
+ * be wrong but it is a good bet.
+ */
+ have_aaaa = false;
+ have_a = !authoritative;
+ have_sig = false;
+#endif
+ /*
+ * XXXRTH Need to handle zonecuts with special case
+ * code.
+ */
+ n = 0;
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: type any; allrdatasets failed");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+
+ /*
+ * Calling query_addrrset() with a non-NULL dbuf is going
+ * to either keep or release the name. We don't want it to
+ * release fname, since we may have to call query_addrrset()
+ * more than once. That means we have to call query_keepname()
+ * now, and pass a NULL dbuf to query_addrrset().
+ *
+ * If we do a query_addrrset() below, we must set fname to
+ * NULL before leaving this block, otherwise we might try to
+ * cleanup fname even though we're using it!
+ */
+ query_keepname(client, fname, dbuf);
+ tname = fname;
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, rdataset);
+#ifdef ALLOW_FILTER_AAAA
+ /*
+ * Notice the presence of A and AAAAs so
+ * that AAAAs can be hidden from IPv4 clients.
+ */
+ if (client->filter_aaaa != dns_aaaa_ok) {
+ if (rdataset->type == dns_rdatatype_aaaa)
+ have_aaaa = true;
+ else if (rdataset->type == dns_rdatatype_a)
+ have_a = true;
+ }
+#endif
+ /*
+ * We found an NS RRset; no need to add one later.
+ */
+ if (qtype == dns_rdatatype_any &&
+ rdataset->type == dns_rdatatype_ns)
+ {
+ answer_has_ns = true;
+ }
+
+ if (is_zone && qtype == dns_rdatatype_any &&
+ !dns_db_issecure(db) &&
+ dns_rdatatype_isdnssec(rdataset->type)) {
+ /*
+ * The zone is transitioning from insecure
+ * to secure. Hide the dnssec records from
+ * ANY queries.
+ */
+ dns_rdataset_disassociate(rdataset);
+ } else if (client->view->minimal_any &&
+ !TCP(client) && !WANTDNSSEC(client) &&
+ qtype == dns_rdatatype_any &&
+ (rdataset->type == dns_rdatatype_sig ||
+ rdataset->type == dns_rdatatype_rrsig)) {
+ CTRACE(ISC_LOG_DEBUG(5), "query_find: "
+ "minimal-any skip signature");
+ dns_rdataset_disassociate(rdataset);
+ } else if (client->view->minimal_any &&
+ !TCP(client) && onetype != 0 &&
+ rdataset->type != onetype &&
+ rdataset->covers != onetype) {
+ CTRACE(ISC_LOG_DEBUG(5), "query_find: "
+ "minimal-any skip rdataset");
+ dns_rdataset_disassociate(rdataset);
+ } else if ((qtype == dns_rdatatype_any ||
+ rdataset->type == qtype) && rdataset->type != 0) {
+#ifdef ALLOW_FILTER_AAAA
+ if (dns_rdatatype_isdnssec(rdataset->type))
+ have_sig = true;
+#endif
+ if (NOQNAME(rdataset) && WANTDNSSEC(client))
+ noqname = rdataset;
+ else
+ noqname = NULL;
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL)
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ rpz_st->m.ttl);
+ if (!is_zone && RECURSIONOK(client)) {
+ dns_name_t *name;
+ name = (fname != NULL) ? fname : tname;
+ query_prefetch(client, name, rdataset);
+ }
+ /*
+ * Remember the first RRtype we find so we
+ * can skip others with minimal-any.
+ */
+ if (rdataset->type == dns_rdatatype_sig ||
+ rdataset->type == dns_rdatatype_rrsig)
+ onetype = rdataset->covers;
+ else
+ onetype = rdataset->type;
+ query_addrrset(client,
+ fname != NULL ? &fname : &tname,
+ &rdataset, NULL,
+ NULL, DNS_SECTION_ANSWER);
+ if (noqname != NULL)
+ query_addnoqnameproof(client, noqname);
+ n++;
+ INSIST(tname != NULL);
+ /*
+ * rdataset is non-NULL only in certain
+ * pathological cases involving DNAMEs.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ break;
+ } else {
+ /*
+ * We're not interested in this rdataset.
+ */
+ dns_rdataset_disassociate(rdataset);
+ }
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+
+#ifdef ALLOW_FILTER_AAAA
+ /*
+ * Filter AAAAs if there is an A and there is no signature
+ * or we are supposed to break DNSSEC.
+ */
+ if (client->filter_aaaa == dns_aaaa_break_dnssec)
+ client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
+ else if (client->filter_aaaa != dns_aaaa_ok &&
+ have_aaaa && have_a &&
+ (!have_sig || !WANTDNSSEC(client)))
+ client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
+#endif
+ if (fname != NULL)
+ dns_message_puttempname(client->message, &fname);
+
+ if (n == 0) {
+ /*
+ * No matching rdatasets found in cache. If we were
+ * searching for RRSIG/SIG, that's probably okay;
+ * otherwise this is an error condition.
+ */
+ if ((qtype == dns_rdatatype_rrsig ||
+ qtype == dns_rdatatype_sig) &&
+ result == ISC_R_NOMORE) {
+ if (!is_zone) {
+ authoritative = false;
+ dns_rdatasetiter_destroy(&rdsiter);
+ client->attributes &= ~NS_CLIENTATTR_RA;
+ goto addauth;
+ }
+
+ if (qtype == dns_rdatatype_rrsig &&
+ dns_db_issecure(db)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(client->query.qname,
+ namebuf,
+ sizeof(namebuf));
+ ns_client_log(client,
+ DNS_LOGCATEGORY_DNSSEC,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "missing signature "
+ "for %s", namebuf);
+ }
+
+ dns_rdatasetiter_destroy(&rdsiter);
+ fname = query_newname(client, dbuf, &b);
+ goto nxrrset_rrsig;
+ } else {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: no matching rdatasets "
+ "in cache");
+ result = DNS_R_SERVFAIL;
+ }
+ }
+
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_NOMORE) {
+ CTRACE(ISC_LOG_ERROR,
+ "query_find: dns_rdatasetiter_destroy failed");
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ } else {
+ /*
+ * This is the "normal" case -- an ordinary question to which
+ * we know the answer.
+ */
+
+ /*
+ * If we have a zero ttl from the cache refetch it.
+ */
+ if (!is_zone && !resuming && rdataset->ttl == 0 &&
+ RECURSIONOK(client))
+ {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ INSIST(!REDIRECT(client));
+ result = query_recurse(client, qtype,
+ client->query.qname,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS) {
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ if (dns64)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64;
+ if (dns64_exclude)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64EXCLUDE;
+ } else
+ RECURSE_ERROR(result);
+ goto cleanup;
+ }
+
+ /*
+ * Check to see if the AAAA RRset has non-excluded addresses
+ * in it. If not look for a A RRset.
+ *
+ * Note: the order of dns64_aaaaok() and filter_aaaa check is
+ * important. Both result is fetches being called but the
+ * dns64 case goes to db_find while the filter_aaaa case
+ * adds the records now for later potential exclusion.
+ */
+ INSIST(client->query.dns64_aaaaok == NULL);
+
+ if (qtype == dns_rdatatype_aaaa && !dns64_exclude &&
+ !ISC_LIST_EMPTY(client->view->dns64) &&
+ client->message->rdclass == dns_rdataclass_in &&
+ !dns64_aaaaok(client, rdataset, sigrdataset)) {
+ /*
+ * Look to see if there are A records for this
+ * name.
+ */
+ client->query.dns64_ttl = rdataset->ttl;
+ SAVE(client->query.dns64_aaaa, rdataset);
+ SAVE(client->query.dns64_sigaaaa, sigrdataset);
+ query_releasename(client, &fname);
+ dns_db_detachnode(db, &node);
+ type = qtype = dns_rdatatype_a;
+ dns64_exclude = dns64 = true;
+ goto db_find;
+ }
+
+#ifdef ALLOW_FILTER_AAAA
+ /*
+ * Optionally hide AAAAs from IPv4 clients if there is an A.
+ * We add the AAAAs now, but might refuse to render them later
+ * after DNSSEC is figured out.
+ * This could be more efficient, but the whole idea is
+ * so fundamentally wrong, unavoidably inaccurate, and
+ * unneeded that it is best to keep it as short as possible.
+ */
+ if (client->filter_aaaa == dns_aaaa_break_dnssec ||
+ (client->filter_aaaa == dns_aaaa_filter &&
+ (!WANTDNSSEC(client) || sigrdataset == NULL ||
+ !dns_rdataset_isassociated(sigrdataset))))
+ {
+ if (qtype == dns_rdatatype_aaaa) {
+ trdataset = query_newrdataset(client);
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_a, 0,
+ client->now,
+ trdataset, NULL);
+ if (dns_rdataset_isassociated(trdataset))
+ dns_rdataset_disassociate(trdataset);
+ query_putrdataset(client, &trdataset);
+
+ /*
+ * We have an AAAA but the A is not in our cache.
+ * Assume any result other than DNS_R_DELEGATION
+ * or ISC_R_NOTFOUND means there is no A and
+ * so AAAAs are ok.
+ * Assume there is no A if we can't recurse
+ * for this client, although that could be
+ * the wrong answer. What else can we do?
+ * Besides, that we have the AAAA and are using
+ * this mechanism suggests that we care more
+ * about As than AAAAs and would have cached
+ * the A if it existed.
+ */
+ if (result == ISC_R_SUCCESS) {
+ client->attributes |=
+ NS_CLIENTATTR_FILTER_AAAA;
+
+ } else if (authoritative ||
+ !RECURSIONOK(client) ||
+ (result != DNS_R_DELEGATION &&
+ result != ISC_R_NOTFOUND)) {
+ client->attributes &=
+ ~NS_CLIENTATTR_FILTER_AAAA;
+ } else {
+ /*
+ * 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.
+ */
+ INSIST(!REDIRECT(client));
+ result = query_recurse(client,
+ dns_rdatatype_a,
+ client->query.qname,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS) {
+ client->attributes |=
+ NS_CLIENTATTR_FILTER_AAAA_RC;
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ }
+ }
+
+ } else if (qtype == dns_rdatatype_a &&
+ (client->attributes &
+ NS_CLIENTATTR_FILTER_AAAA_RC) != 0) {
+ client->attributes &=
+ ~NS_CLIENTATTR_FILTER_AAAA_RC;
+ client->attributes |=
+ NS_CLIENTATTR_FILTER_AAAA;
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ goto cleanup;
+ }
+ }
+#endif
+
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ if (NOQNAME(rdataset) && WANTDNSSEC(client))
+ noqname = rdataset;
+ else
+ noqname = NULL;
+ /*
+ * Special case NS handling
+ */
+ if (is_zone && qtype == dns_rdatatype_ns) {
+ /*
+ * We've already got an NS, no need to add one in
+ * the authority section
+ */
+ if (dns_name_equal(client->query.qname,
+ dns_db_origin(db)))
+ {
+ answer_has_ns = true;
+ }
+
+ /*
+ * BIND 8 priming queries need the additional section.
+ */
+ if (dns_name_equal(client->query.qname, dns_rootname)) {
+ client->query.attributes &=
+ ~NS_QUERYATTR_NOADDITIONAL;
+ }
+ }
+
+ /*
+ * Return the time to expire for slave and master zones.
+ */
+ if (zone != NULL && is_zone && qtype == dns_rdatatype_soa &&
+ (client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
+ client->query.restarts == 0) {
+ dns_zone_t *raw = NULL, *mayberaw;
+
+ dns_zone_getraw(zone, &raw);
+ mayberaw = (raw != NULL) ? raw : zone;
+
+ if (dns_zone_gettype(mayberaw) == dns_zone_slave) {
+ isc_time_t expiretime;
+ uint32_t secs;
+ dns_zone_getexpiretime(zone, &expiretime);
+ secs = isc_time_seconds(&expiretime);
+ if (secs >= client->now &&
+ result == ISC_R_SUCCESS) {
+ client->attributes |=
+ NS_CLIENTATTR_HAVEEXPIRE;
+ client->expire = secs - client->now;
+ }
+ }
+ if (dns_zone_gettype(mayberaw) == dns_zone_master) {
+ dns_rdata_soa_t soa;
+ result = dns_rdataset_first(rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ client->expire = soa.expire;
+ client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
+ }
+ if (raw != NULL)
+ dns_zone_detach(&raw);
+ }
+
+ if (dns64) {
+ qtype = type = dns_rdatatype_aaaa;
+ result = query_dns64(client, &fname, rdataset,
+ sigrdataset, dbuf,
+ DNS_SECTION_ANSWER);
+ noqname = NULL;
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(client->message, &rdataset);
+ if (result == ISC_R_NOMORE) {
+#ifndef dns64_bis_return_excluded_addresses
+ if (dns64_exclude) {
+ if (!is_zone)
+ goto cleanup;
+ /*
+ * Add a fake SOA record.
+ */
+ (void)query_addsoa(client, db, version,
+ 600, false,
+ DNS_SECTION_AUTHORITY);
+ goto cleanup;
+ }
+#endif
+ if (is_zone)
+ goto iszone_nxrrset;
+ else
+ goto ncache_nxrrset;
+ } else if (result != ISC_R_SUCCESS) {
+ eresult = result;
+ goto cleanup;
+ }
+ } else if (client->query.dns64_aaaaok != NULL) {
+ query_filter64(client, &fname, rdataset, dbuf,
+ DNS_SECTION_ANSWER);
+ query_putrdataset(client, &rdataset);
+ } else {
+ if (!is_zone && RECURSIONOK(client))
+ query_prefetch(client, fname, rdataset);
+ query_addrrset(client, &fname, &rdataset,
+ sigrdatasetp, dbuf, DNS_SECTION_ANSWER);
+ }
+
+ if (noqname != NULL)
+ query_addnoqnameproof(client, noqname);
+ /*
+ * We shouldn't ever fail to add 'rdataset'
+ * because it's already in the answer.
+ */
+ INSIST(rdataset == NULL);
+ }
+
+ addauth:
+ CTRACE(ISC_LOG_DEBUG(3), "query_find: addauth");
+ /*
+ * Add NS records to the authority section (if we haven't already
+ * added them to the answer section).
+ */
+ if (!want_restart && !NOAUTHORITY(client)) {
+ if (is_zone) {
+ if (!answer_has_ns) {
+ (void)query_addns(client, db, version);
+ }
+ } else if (!answer_has_ns && qtype != dns_rdatatype_ns) {
+ if (fname != NULL) {
+ query_releasename(client, &fname);
+ }
+ query_addbestns(client);
+ }
+ }
+
+ /*
+ * Add NSEC records to the authority section if they're needed for
+ * DNSSEC wildcard proofs.
+ */
+ if (need_wildcardproof && dns_db_issecure(db))
+ query_addwildcardproof(client, db, version,
+ dns_fixedname_name(&wildcardname),
+ true, false);
+ cleanup:
+ CTRACE(ISC_LOG_DEBUG(3), "query_find: cleanup");
+ /*
+ * General cleanup.
+ */
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
+ rpz_match_clear(rpz_st);
+ rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
+ }
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (zdb != NULL) {
+ query_putrdataset(client, &zrdataset);
+ if (zsigrdataset != NULL)
+ query_putrdataset(client, &zsigrdataset);
+ if (zfname != NULL)
+ query_releasename(client, &zfname);
+ dns_db_detach(&zdb);
+ }
+ if (event != NULL) {
+ free_devent(client, ISC_EVENT_PTR(&event), &event);
+ }
+
+ /*
+ * AA bit.
+ */
+ if (client->query.restarts == 0 && !authoritative) {
+ /*
+ * We're not authoritative, so we must ensure the AA bit
+ * isn't set.
+ */
+ client->message->flags &= ~DNS_MESSAGEFLAG_AA;
+ }
+
+ /*
+ * Restart the query?
+ */
+ if (want_restart && client->query.restarts < MAX_RESTARTS) {
+ client->query.restarts++;
+ goto restart;
+ }
+
+ if (eresult != ISC_R_SUCCESS &&
+ (!PARTIALANSWER(client) || WANTRECURSION(client)
+ || eresult == DNS_R_DROP)) {
+ if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
+ /*
+ * This was a duplicate query that we are
+ * recursing on or the result of rate limiting.
+ * Don't send a response now for a duplicate query,
+ * because the original will still cause a response.
+ */
+ query_next(client, eresult);
+ } else {
+ /*
+ * If we don't have any answer to give the client,
+ * or if the client requested recursion and thus wanted
+ * the complete answer, send an error response.
+ */
+ INSIST(line >= 0);
+ query_error(client, eresult, line);
+ }
+ ns_client_detach(&client);
+ } else if (!RECURSING(client)) {
+ /*
+ * We are done. Set up sortlist data for the message
+ * rendering code, make a final tweak to the AA bit if the
+ * auth-nxdomain config option says so, then render and
+ * send the response.
+ */
+ setup_query_sortlist(client);
+
+ /*
+ * If this is a referral and the answer to the question
+ * is in the glue sort it to the start of the additional
+ * section.
+ */
+ if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) &&
+ client->message->rcode == dns_rcode_noerror &&
+ (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
+ answer_in_glue(client, qtype);
+
+ if (client->message->rcode == dns_rcode_nxdomain &&
+ client->view->auth_nxdomain == true)
+ client->message->flags |= DNS_MESSAGEFLAG_AA;
+
+ /*
+ * If the response is somehow unexpected for the client and this
+ * is a result of recursion, return an error to the caller
+ * to indicate it may need to be logged.
+ */
+ if (resuming &&
+ (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) ||
+ client->message->rcode != dns_rcode_noerror))
+ eresult = ISC_R_FAILURE;
+
+ query_send(client);
+ ns_client_detach(&client);
+ }
+ CTRACE(ISC_LOG_DEBUG(3), "query_find: done");
+
+ return (eresult);
+}
+
+static inline void
+log_tat(ns_client_t *client) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char clientbuf[ISC_NETADDR_FORMATSIZE];
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+ isc_netaddr_t netaddr;
+ char *tags = NULL;
+ size_t taglen = 0;
+
+ if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_INFO)) {
+ return;
+ }
+
+ if ((client->query.qtype != dns_rdatatype_null ||
+ !dns_name_istat(client->query.qname)) &&
+ (client->keytag == NULL ||
+ client->query.qtype != dns_rdatatype_dnskey))
+ {
+ return;
+ }
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
+ isc_netaddr_format(&netaddr, clientbuf, sizeof(clientbuf));
+ dns_rdataclass_format(client->view->rdclass, classname,
+ sizeof(classname));
+
+ if (client->query.qtype == dns_rdatatype_dnskey) {
+ uint16_t keytags = client->keytag_len / 2;
+ size_t len = taglen = sizeof("65000") * keytags + 1;
+ char *cp = tags = isc_mem_get(client->mctx, taglen);
+ int i = 0;
+
+ INSIST(client->keytag != NULL);
+ if (tags != NULL) {
+ while (keytags-- > 0U) {
+ int n;
+ uint16_t keytag;
+ keytag = (client->keytag[i * 2] << 8) |
+ client->keytag[i * 2 + 1];
+ n = snprintf(cp, len, " %u", keytag);
+ if (n > 0 && (size_t)n <= len) {
+ cp += n;
+ len -= n;
+ i++;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_TAT, NS_LOGMODULE_QUERY,
+ ISC_LOG_INFO, "trust-anchor-telemetry '%s/%s' from %s%s",
+ namebuf, classname, clientbuf, tags != NULL? tags : "");
+ if (tags != NULL) {
+ isc_mem_put(client->mctx, tags, taglen);
+ }
+}
+
+static inline void
+log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typename[DNS_RDATATYPE_FORMATSIZE];
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+ char onbuf[ISC_NETADDR_FORMATSIZE];
+ char ednsbuf[sizeof("E(65535)")] = { 0 };
+ dns_rdataset_t *rdataset;
+ int level = ISC_LOG_INFO;
+
+ if (! isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ INSIST(rdataset != NULL);
+ dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
+ dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
+ isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
+
+ if (client->ednsversion >= 0)
+ snprintf(ednsbuf, sizeof(ednsbuf), "E(%hd)",
+ client->ednsversion);
+
+ ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
+ level, "query: %s %s %s %s%s%s%s%s%s%s (%s)", namebuf,
+ classname, typename, WANTRECURSION(client) ? "+" : "-",
+ (client->signer != NULL) ? "S" : "", ednsbuf,
+ TCP(client) ? "T" : "",
+ ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
+ ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
+ HAVECOOKIE(client) ? "V" : WANTCOOKIE(client) ? "K" : "",
+ onbuf);
+}
+
+static inline void
+log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typename[DNS_RDATATYPE_FORMATSIZE];
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+ const char *namep, *typep, *classp, *sep1, *sep2;
+ dns_rdataset_t *rdataset;
+
+ if (!isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ namep = typep = classp = sep1 = sep2 = "";
+
+ /*
+ * Query errors can happen for various reasons. In some cases we cannot
+ * even assume the query contains a valid question section, so we should
+ * expect exceptional cases.
+ */
+ if (client->query.origqname != NULL) {
+ dns_name_format(client->query.origqname, namebuf,
+ sizeof(namebuf));
+ namep = namebuf;
+ sep1 = " for ";
+
+ rdataset = ISC_LIST_HEAD(client->query.origqname->list);
+ if (rdataset != NULL) {
+ dns_rdataclass_format(rdataset->rdclass, classname,
+ sizeof(classname));
+ classp = classname;
+ dns_rdatatype_format(rdataset->type, typename,
+ sizeof(typename));
+ typep = typename;
+ sep2 = "/";
+ }
+ }
+
+ ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
+ level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
+ isc_result_totext(result), sep1, namep, sep2,
+ classp, sep2, typep, __FILE__, line);
+}
+
+void
+ns_query_start(ns_client_t *client) {
+ isc_result_t result;
+ dns_message_t *message = client->message;
+ dns_rdataset_t *rdataset;
+ ns_client_t *qclient;
+ dns_rdatatype_t qtype;
+ unsigned int saved_extflags = client->extflags;
+ unsigned int saved_flags = client->message->flags;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE(ISC_LOG_DEBUG(3), "ns_query_start");
+
+ /*
+ * Test only.
+ */
+ if (ns_g_clienttest && !TCP(client)) {
+ result = ns_client_replace(client);
+ if (result == ISC_R_SHUTTINGDOWN) {
+ ns_client_next(client, result);
+ return;
+ } else if (result != ISC_R_SUCCESS) {
+ query_error(client, result, __LINE__);
+ return;
+ }
+ }
+
+ /*
+ * Ensure that appropriate cleanups occur.
+ */
+ client->next = query_next_callback;
+
+ /*
+ * Behave as if we don't support DNSSEC if not enabled.
+ */
+ if (!client->view->enablednssec) {
+ message->flags &= ~DNS_MESSAGEFLAG_CD;
+ client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
+ }
+
+ if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
+ client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
+
+ if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
+ client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
+
+ switch (client->view->minimalresponses) {
+ case dns_minimal_no:
+ break;
+ case dns_minimal_yes:
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+ break;
+ case dns_minimal_noauth:
+ client->query.attributes |= NS_QUERYATTR_NOAUTHORITY;
+ break;
+ case dns_minimal_noauthrec:
+ if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
+ client->query.attributes |= NS_QUERYATTR_NOAUTHORITY;
+ break;
+ }
+
+ if ((client->view->cachedb == NULL)
+ || (!client->view->additionalfromcache)) {
+ /*
+ * We don't have a cache. Turn off cache support and
+ * recursion.
+ */
+ client->query.attributes &=
+ ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
+ client->attributes |= NS_CLIENTATTR_NOSETFC;
+ } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
+ (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
+ /*
+ * If the client isn't allowed to recurse (due to
+ * "recursion no", the allow-recursion ACL, or the
+ * lack of a resolver in this view), or if it
+ * doesn't want recursion, turn recursion off.
+ */
+ client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
+ client->attributes |= NS_CLIENTATTR_NOSETFC;
+ }
+
+ /*
+ * Check for multiple question queries, since edns1 is dead.
+ */
+ if (message->counts[DNS_SECTION_QUESTION] > 1) {
+ query_error(client, DNS_R_FORMERR, __LINE__);
+ return;
+ }
+
+ /*
+ * Get the question name.
+ */
+ result = dns_message_firstname(message, DNS_SECTION_QUESTION);
+ if (result != ISC_R_SUCCESS) {
+ query_error(client, result, __LINE__);
+ return;
+ }
+ dns_message_currentname(message, DNS_SECTION_QUESTION,
+ &client->query.qname);
+ client->query.origqname = client->query.qname;
+ result = dns_message_nextname(message, DNS_SECTION_QUESTION);
+ if (result != ISC_R_NOMORE) {
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * There's more than one QNAME in the question
+ * section.
+ */
+ query_error(client, DNS_R_FORMERR, __LINE__);
+ } else
+ query_error(client, result, __LINE__);
+ return;
+ }
+
+ if (ns_g_server->log_queries)
+ log_query(client, saved_flags, saved_extflags);
+
+ /*
+ * Check for meta-queries like IXFR and AXFR.
+ */
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ INSIST(rdataset != NULL);
+ client->query.qtype = qtype = rdataset->type;
+ dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
+
+ log_tat(client);
+
+ if (dns_rdatatype_ismeta(qtype)) {
+ switch (qtype) {
+ case dns_rdatatype_any:
+ break; /* Let query_find handle it. */
+ case dns_rdatatype_ixfr:
+ case dns_rdatatype_axfr:
+ ns_xfr_start(client, rdataset->type);
+ return;
+ case dns_rdatatype_maila:
+ case dns_rdatatype_mailb:
+ query_error(client, DNS_R_NOTIMP, __LINE__);
+ return;
+ case dns_rdatatype_tkey:
+ result = dns_tkey_processquery(client->message,
+ ns_g_server->tkeyctx,
+ client->view->dynamickeys);
+ if (result == ISC_R_SUCCESS)
+ query_send(client);
+ else
+ query_error(client, result, __LINE__);
+ return;
+ default: /* TSIG, etc. */
+ query_error(client, DNS_R_FORMERR, __LINE__);
+ return;
+ }
+ }
+
+ /*
+ * Turn on minimal response for (C)DNSKEY and (C)DS queries.
+ */
+ if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds ||
+ qtype == dns_rdatatype_cdnskey || qtype == dns_rdatatype_cds)
+ {
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+ }
+
+ /*
+ * Maybe turn on minimal responses for ANY queries.
+ */
+ if (qtype == dns_rdatatype_any &&
+ client->view->minimal_any && !TCP(client))
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+
+ /*
+ * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
+ */
+ if (client->ednsversion >= 0 && client->udpsize <= 512U && !TCP(client))
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+
+ /*
+ * If the client has requested that DNSSEC checking be disabled,
+ * allow lookups to return pending data and instruct the resolver
+ * to return data before validation has completed.
+ *
+ * We don't need to set DNS_DBFIND_PENDINGOK when validation is
+ * disabled as there will be no pending data.
+ */
+ if (message->flags & DNS_MESSAGEFLAG_CD ||
+ qtype == dns_rdatatype_rrsig)
+ {
+ client->query.dboptions |= DNS_DBFIND_PENDINGOK;
+ client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
+ } else if (!client->view->enablevalidation)
+ client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
+
+ /*
+ * Allow glue NS records to be added to the authority section
+ * if the answer is secure.
+ */
+ if (message->flags & DNS_MESSAGEFLAG_CD)
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+
+ /*
+ * Set NS_CLIENTATTR_WANTAD if the client has set AD in the query.
+ * This allows AD to be returned on queries without DO set.
+ */
+ if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
+ client->attributes |= NS_CLIENTATTR_WANTAD;
+
+ /*
+ * This is an ordinary query.
+ */
+ result = dns_message_reply(message, true);
+ if (result != ISC_R_SUCCESS) {
+ query_next(client, result);
+ return;
+ }
+
+ /*
+ * Assume authoritative response until it is known to be
+ * otherwise.
+ *
+ * If "-T noaa" has been set on the command line don't set
+ * AA on authoritative answers.
+ */
+ if (!ns_g_noaa)
+ message->flags |= DNS_MESSAGEFLAG_AA;
+
+ /*
+ * Set AD. We must clear it if we add non-validated data to a
+ * response.
+ */
+ if (WANTDNSSEC(client) || WANTAD(client))
+ message->flags |= DNS_MESSAGEFLAG_AD;
+
+ qclient = NULL;
+ ns_client_attach(client, &qclient);
+ (void)query_find(qclient, NULL, qtype);
+}
diff --git a/bin/named/server.c b/bin/named/server.c
new file mode 100644
index 0000000..7f87ccf
--- /dev/null
+++ b/bin/named/server.c
@@ -0,0 +1,14277 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <isc/aes.h>
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/hmacsha.h>
+#include <isc/httpd.h>
+#include <isc/lex.h>
+#include <isc/meminfo.h>
+#include <isc/parseint.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/refcount.h>
+#include <isc/resource.h>
+#include <isc/sha2.h>
+#include <isc/socket.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 <isc/xml.h>
+
+#include <isccfg/grammar.h>
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <dns/acache.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/dyndb.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/keytable.h>
+#include <dns/keyvalues.h>
+#include <dns/lib.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/nta.h>
+#include <dns/order.h>
+#include <dns/peer.h>
+#include <dns/portlist.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/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 <dst/result.h>
+
+#include <named/client.h>
+#include <named/config.h>
+#include <named/control.h>
+#ifdef HAVE_GEOIP
+#include <named/geoip.h>
+#endif /* HAVE_GEOIP */
+#include <named/interfacemgr.h>
+#include <named/log.h>
+#include <named/logconf.h>
+#include <named/lwresd.h>
+#include <named/main.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/statschannel.h>
+#include <named/tkeyconf.h>
+#include <named/tsigconf.h>
+#include <named/zoneconf.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#include <stdlib.h>
+#endif
+
+#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 PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+
+#ifndef SIZE_AS_PERCENT
+#define SIZE_AS_PERCENT ((size_t)-2)
+#endif
+
+#ifdef TUNE_LARGE
+#define RESOLVER_NTASKS 523
+#define UDPBUFFERS 32768
+#define EXCLBUFFERS 32768
+#else
+#define RESOLVER_NTASKS 31
+#define UDPBUFFERS 1000
+#define EXCLBUFFERS 4096
+#endif /* TUNE_LARGE */
+
+/*%
+ * 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(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_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(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_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(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 ns_dispatch {
+ isc_sockaddr_t addr;
+ unsigned int dispatchgen;
+ dns_dispatch_t *dispatch;
+ ISC_LINK(struct ns_dispatch) link;
+};
+
+struct ns_cache {
+ dns_cache_t *cache;
+ dns_view_t *primaryview;
+ bool needflush;
+ bool adbsizeadjusted;
+ dns_rdataclass_t rdclass;
+ ISC_LINK(ns_cache_t) link;
+};
+
+struct dumpcontext {
+ isc_mem_t *mctx;
+ bool dumpcache;
+ bool dumpzones;
+ bool dumpadb;
+ bool dumpbad;
+ 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 {
+ ns_server_t *server;
+ bool reconfig;
+ isc_refcount_t refs;
+} ns_zoneload_t;
+
+typedef struct {
+ ns_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;
+
+/*
+ * 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
+};
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
+
+static void
+ns_server_reload(isc_task_t *task, isc_event_t *event);
+
+static isc_result_t
+ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ uint16_t family, ns_listenelt_t **target);
+static isc_result_t
+ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ uint16_t family, ns_listenlist_t **target);
+
+static isc_result_t
+configure_forward(const cfg_obj_t *config, dns_view_t *view, 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, cfg_aclconfctx_t *aclconf,
+ bool added, bool old_rpz_ok,
+ bool modify);
+
+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(ns_server_t *server, bool all);
+
+static void
+newzone_cfgctx_destroy(void **cfgp);
+
+static inline 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 inline 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
+static isc_result_t
+nzf_append(dns_view_t *view, const cfg_obj_t *zconfig);
+#endif
+
+/*%
+ * 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)ns_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, ns_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)ns_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, ns_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)ns_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, ns_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
+dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
+ bool managed, dst_key_t **target, isc_mem_t *mctx)
+{
+ dns_rdataclass_t viewclass;
+ dns_rdata_dnskey_t keystruct;
+ uint32_t flags, proto, alg;
+ const char *keystr, *keynamestr;
+ unsigned char keydata[4096];
+ isc_buffer_t keydatabuf;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_region_t r;
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname;
+ isc_buffer_t namebuf;
+ isc_result_t result;
+ dst_key_t *dstkey = NULL;
+
+ INSIST(target != NULL && *target == NULL);
+
+ flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
+ proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
+ alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
+ keyname = dns_fixedname_name(&fkeyname);
+ keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+
+ if (managed) {
+ const char *initmethod;
+ initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
+
+ if (strcasecmp(initmethod, "initial-key") != 0) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
+ "managed key '%s': "
+ "invalid initialization method '%s'",
+ keynamestr, initmethod);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ }
+
+ if (vconfig == NULL)
+ viewclass = dns_rdataclass_in;
+ else {
+ const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
+ CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
+ &viewclass));
+ }
+ keystruct.common.rdclass = viewclass;
+ 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 (flags > 0xffff)
+ CHECKM(ISC_R_RANGE, "key flags");
+ if (proto > 0xff)
+ CHECKM(ISC_R_RANGE, "key protocol");
+ if (alg > 0xff)
+ CHECKM(ISC_R_RANGE, "key algorithm");
+ keystruct.flags = (uint16_t)flags;
+ keystruct.protocol = (uint8_t)proto;
+ keystruct.algorithm = (uint8_t)alg;
+
+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
+ keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
+ CHECK(isc_base64_decodestring(keystr, &keydatabuf));
+ isc_buffer_usedregion(&keydatabuf, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
+ keystruct.algorithm == DST_ALG_RSAMD5) &&
+ r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
+ "%s key '%s' has a weak exponent",
+ managed ? "managed" : "trusted",
+ keynamestr);
+
+ CHECK(dns_rdata_fromstruct(NULL,
+ keystruct.common.rdclass,
+ keystruct.common.rdtype,
+ &keystruct, &rrdatabuf));
+ dns_fixedname_init(&fkeyname);
+ isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr));
+ isc_buffer_add(&namebuf, strlen(keynamestr));
+ CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
+ CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
+ mctx, &dstkey));
+
+ *target = dstkey;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (result == DST_R_NOCRYPTO) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
+ "ignoring %s key for '%s': no crypto support",
+ managed ? "managed" : "trusted",
+ keynamestr);
+ } else if (result == DST_R_UNSUPPORTEDALG) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
+ "skipping %s key for '%s': %s",
+ managed ? "managed" : "trusted",
+ keynamestr, isc_result_totext(result));
+ } else {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
+ "configuring %s key for '%s': %s",
+ managed ? "managed" : "trusted",
+ keynamestr, isc_result_totext(result));
+ result = ISC_R_FAILURE;
+ }
+
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+
+ return (result);
+}
+
+static isc_result_t
+load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
+ dns_view_t *view, bool managed,
+ dns_name_t *keyname, isc_mem_t *mctx)
+{
+ const cfg_listelt_t *elt, *elt2;
+ const cfg_obj_t *key, *keylist;
+ dst_key_t *dstkey = NULL;
+ 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)) {
+ key = cfg_listelt_value(elt2);
+ result = dstkey_fromconfig(vconfig, key, managed,
+ &dstkey, mctx);
+ if (result == DST_R_UNSUPPORTEDALG) {
+ result = ISC_R_SUCCESS;
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * If keyname was specified, we only add that key.
+ */
+ if (keyname != NULL &&
+ !dns_name_equal(keyname, dst_key_name(dstkey)))
+ {
+ dst_key_free(&dstkey);
+ continue;
+ }
+
+ CHECK(dns_keytable_add(secroots, managed, &dstkey));
+ }
+ }
+
+ cleanup:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ 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, 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 *global_managed_keys = 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;
+ bool need_mkey_dir = false;
+ 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);
+ (void) cfg_map_get(voptions, "managed-keys",
+ &view_managed_keys);
+ maps[i++] = voptions;
+ }
+ }
+
+ if (config != NULL) {
+ (void)cfg_map_get(config, "trusted-keys", &global_keys);
+ (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+
+ maps[i++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ result = dns_view_initsecroots(view, mctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "couldn't create keytable");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = dns_view_initntatable(view, ns_g_taskmgr, ns_g_timermgr);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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;
+ const cfg_obj_t *builtin_managed_keys = NULL;
+
+ /*
+ * If bind.keys exists and is populated, it overrides
+ * the managed-keys clause hard-coded in ns_g_config.
+ */
+ if (bindkeys != NULL) {
+ isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "obtaining root key for view %s "
+ "from '%s'",
+ view->name, ns_g_server->bindkeysfile);
+
+ (void)cfg_map_get(bindkeys, "trusted-keys",
+ &builtin_keys);
+ (void)cfg_map_get(bindkeys, "managed-keys",
+ &builtin_managed_keys);
+
+ if ((builtin_keys == NULL) &&
+ (builtin_managed_keys == NULL))
+ isc_log_write(ns_g_lctx,
+ DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_WARNING,
+ "dnssec-validation auto: "
+ "WARNING: root zone key "
+ "not found");
+ }
+
+ if ((builtin_keys == NULL) &&
+ (builtin_managed_keys == NULL))
+ {
+ isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using built-in root key for view %s",
+ view->name);
+
+ (void)cfg_map_get(ns_g_config, "trusted-keys",
+ &builtin_keys);
+ (void)cfg_map_get(ns_g_config, "managed-keys",
+ &builtin_managed_keys);
+ }
+
+ if (builtin_keys != NULL)
+ CHECK(load_view_keys(builtin_keys, vconfig, view,
+ false, dns_rootname, mctx));
+ if (builtin_managed_keys != NULL)
+ CHECK(load_view_keys(builtin_managed_keys, vconfig,
+ view, true, dns_rootname,
+ mctx));
+
+ if (!keyloaded(view, dns_rootname)) {
+ isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "root key not loaded");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ }
+
+ CHECK(load_view_keys(view_keys, vconfig, view, false,
+ NULL, mctx));
+ CHECK(load_view_keys(view_managed_keys, vconfig, view, true,
+ NULL, mctx));
+
+ if (view->rdclass == dns_rdataclass_in) {
+ CHECK(load_view_keys(global_keys, vconfig, view, false,
+ NULL, mctx));
+ CHECK(load_view_keys(global_managed_keys, vconfig, view,
+ true, NULL, mctx));
+ }
+
+ /*
+ * Add key zone for managed-keys.
+ */
+ need_mkey_dir = (auto_root || view_managed_keys != NULL);
+
+ obj = NULL;
+ (void)ns_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(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "invalid managed-keys-directory %s: %s",
+ directory, isc_result_totext(result));
+ goto cleanup;
+
+ } else if (need_mkey_dir && directory != NULL) {
+ if (!isc_file_isdirwritable(directory)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "managed-keys-directory '%s' "
+ "is not writable", directory);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+ } else if (need_mkey_dir) {
+ char cwd[PATH_MAX];
+
+ if (getcwd(cwd, sizeof(cwd)) == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to retrieve "
+ "current working directory");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (!isc_file_isdirwritable(cwd)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "working directory '%s' "
+ "is not writable", cwd);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+ }
+
+ CHECK(add_keydata_zone(view, directory, ns_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, isc_dscp_t *dscpp,
+ bool is_firstview)
+{
+ isc_result_t result = ISC_R_FAILURE;
+ dns_dispatch_t *disp;
+ isc_sockaddr_t sa;
+ unsigned int attrs, attrmask;
+ const cfg_obj_t *obj = NULL;
+ unsigned int maxdispatchbuffers = UDPBUFFERS;
+ isc_dscp_t dscp = -1;
+
+ switch (af) {
+ case AF_INET:
+ result = ns_config_get(maps, "query-source", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ result = ns_config_get(maps, "query-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ sa = *(cfg_obj_assockaddr(obj));
+ INSIST(isc_sockaddr_pf(&sa) == af);
+
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp != -1 && dscpp != NULL)
+ *dscpp = dscp;
+
+ /*
+ * 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:
+ INSIST(0);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Try to find a dispatcher that we can share.
+ */
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ switch (af) {
+ case AF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+ case AF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+ }
+ if (isc_sockaddr_getport(&sa) == 0) {
+ attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
+ maxdispatchbuffers = EXCLBUFFERS;
+ } else {
+ INSIST(obj != NULL);
+ if (is_firstview) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
+ "using specific query-source port "
+ "suppresses port randomization and can be "
+ "insecure.");
+ }
+ }
+
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+
+ disp = NULL;
+ result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
+ ns_g_taskmgr, &sa, 4096,
+ maxdispatchbuffers, 32768, 16411, 16433,
+ attrs, attrmask, &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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 = ns_config_getclass(cfg_tuple_get(ent, "class"),
+ dns_rdataclass_any, &rdclass);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = ns_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
+ mode = 0;
+#endif /* DNS_RDATASET_FIXED */
+ else if (!strcasecmp(str, "random"))
+ mode = DNS_RDATASETATTR_RANDOMIZE;
+ else if (!strcasecmp(str, "cyclic"))
+ mode = 0;
+ else
+ INSIST(0);
+
+ /*
+ * "*" 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 < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ 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 > 255)
+ ednsversion = 255;
+ 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 < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize));
+ }
+
+ 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, "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
+ INSIST(0);
+ }
+
+ 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;
+ result = dns_peer_settransferdscp(peer, cfg_obj_getdscp(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_add_reserved_dispatch(ns_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;
+ result = dns_peer_setnotifydscp(peer, cfg_obj_getdscp(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_add_reserved_dispatch(ns_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;
+ result = dns_peer_setquerydscp(peer, cfg_obj_getdscp(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+ }
+
+ *peerp = peer;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_peer_detach(&peer);
+ return (result);
+}
+
+#ifdef HAVE_DLOPEN
+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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dynamic database '%s' configuration failed: %s",
+ name, isc_result_totext(result));
+ return (result);
+}
+#endif
+
+
+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),
+ ns_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),
+ ns_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.
+ */
+ 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,
+ dns_nsstatscounter_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 ns_cache_t *
+cachelist_find(ns_cachelist_t *cachelist, const char *cachename,
+ dns_rdataclass_t rdclass)
+{
+ ns_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,
+ unsigned int new_cleaning_interval,
+ uint64_t new_max_cache_size)
+{
+ /*
+ * 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_getcleaninginterval(originview->cache) !=
+ new_cleaning_interval ||
+ 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(ns_g_server->zonemgr, zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+
+ return (ns_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(ns_g_server->zonemgr, zone));
+ dns_zone_setclass(zone, view->rdclass);
+ dns_zone_settype(zone, dns_zone_master);
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+ CHECK(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(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep,
+ viewname, reverse);
+
+cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+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, ns_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, ns_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_def, dns_ttl_t ttl_def,
+ const dns_rpz_zone_t *old, bool *old_rpz_okp)
+{
+ const cfg_obj_t *rpz_obj, *obj;
+ const char *str;
+ dns_rpz_zone_t *new;
+ 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, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "limit of %d response policy zones exceeded",
+ DNS_RPZ_MAX_ZONES);
+ return (ISC_R_FAILURE);
+ }
+
+ new = isc_mem_get(view->rpzs->mctx, sizeof(*new));
+ if (new == NULL) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "no memory for response policy zones");
+ return (ISC_R_NOMEMORY);
+ }
+
+ memset(new, 0, sizeof(*new));
+ result = isc_refcount_init(&new->refs, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(view->rpzs->mctx, new, sizeof(*new));
+ return (result);
+ }
+ dns_name_init(&new->origin, NULL);
+ dns_name_init(&new->client_ip, NULL);
+ dns_name_init(&new->ip, NULL);
+ dns_name_init(&new->nsdname, NULL);
+ dns_name_init(&new->nsip, NULL);
+ dns_name_init(&new->passthru, NULL);
+ dns_name_init(&new->drop, NULL);
+ dns_name_init(&new->tcp_only, NULL);
+ dns_name_init(&new->cname, NULL);
+ new->num = view->rpzs->p.num_zones++;
+ view->rpzs->zones[new->num] = new;
+
+ obj = cfg_tuple_get(rpz_obj, "recursive-only");
+ if (cfg_obj_isvoid(obj) ? recursive_only_def : cfg_obj_asboolean(obj)) {
+ view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(new->num);
+ } else {
+ view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(new->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(new->num);
+ } else {
+ view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(new->num);
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
+ if (cfg_obj_isuint32(obj)) {
+ new->max_policy_ttl = cfg_obj_asuint32(obj);
+ } else {
+ new->max_policy_ttl = ttl_def;
+ }
+ if (*old_rpz_okp && new->max_policy_ttl != old->max_policy_ttl)
+ *old_rpz_okp = false;
+
+ str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name"));
+ result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (dns_name_equal(&new->origin, dns_rootname)) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid zone name '%s'", str);
+ return (DNS_R_EMPTYLABEL);
+ }
+ for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones-1; ++rpz_num) {
+ if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin,
+ &new->origin)) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "duplicate '%s'", str);
+ result = DNS_R_DUPLICATE;
+ return (result);
+ }
+ }
+ if (*old_rpz_okp && !dns_name_equal(&old->origin, &new->origin))
+ *old_rpz_okp = false;
+
+ result = configure_rpz_name2(view, rpz_obj, &new->client_ip,
+ DNS_RPZ_CLIENT_IP_ZONE, &new->origin);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = configure_rpz_name2(view, rpz_obj, &new->ip,
+ DNS_RPZ_IP_ZONE, &new->origin);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = configure_rpz_name2(view, rpz_obj, &new->nsdname,
+ DNS_RPZ_NSDNAME_ZONE, &new->origin);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = configure_rpz_name2(view, rpz_obj, &new->nsip,
+ DNS_RPZ_NSIP_ZONE, &new->origin);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = configure_rpz_name(view, rpz_obj, &new->passthru,
+ DNS_RPZ_PASSTHRU_NAME, "name");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = configure_rpz_name(view, rpz_obj, &new->drop,
+ DNS_RPZ_DROP_NAME, "name");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = configure_rpz_name(view, rpz_obj, &new->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)) {
+ new->policy = DNS_RPZ_POLICY_GIVEN;
+ } else {
+ str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name"));
+ new->policy = dns_rpz_str2policy(str);
+ INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
+ if (new->policy == DNS_RPZ_POLICY_CNAME) {
+ str = cfg_obj_asstring(cfg_tuple_get(obj, "cname"));
+ result = configure_rpz_name(view, rpz_obj, &new->cname,
+ str, "cname");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ }
+ if (*old_rpz_okp && (new->policy != old->policy ||
+ !dns_name_equal(&old->cname, &new->cname)))
+ *old_rpz_okp = false;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj,
+ bool *old_rpz_okp)
+{
+ const cfg_listelt_t *zone_element;
+ const cfg_obj_t *sub_obj;
+ bool recursive_only_def;
+ dns_ttl_t ttl_def;
+ dns_rpz_zones_t *new;
+ const dns_rpz_zones_t *old;
+ dns_view_t *pview;
+ 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);
+
+ result = dns_rpz_new_zones(&view->rpzs, view->mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ new = view->rpzs;
+
+ sub_obj = cfg_tuple_get(rpz_obj, "recursive-only");
+ if (!cfg_obj_isvoid(sub_obj) &&
+ !cfg_obj_asboolean(sub_obj))
+ recursive_only_def = false;
+ else
+ recursive_only_def = true;
+
+ sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec");
+ if (!cfg_obj_isvoid(sub_obj) &&
+ cfg_obj_asboolean(sub_obj))
+ new->p.break_dnssec = true;
+ else
+ new->p.break_dnssec = false;
+
+ sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
+ if (cfg_obj_isuint32(sub_obj))
+ ttl_def = cfg_obj_asuint32(sub_obj);
+ else
+ ttl_def = DNS_RPZ_MAX_TTL_DEFAULT;
+
+ sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots");
+ if (cfg_obj_isuint32(sub_obj))
+ new->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1;
+ else
+ new->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))
+ new->p.qname_wait_recurse = true;
+ else
+ new->p.qname_wait_recurse = false;
+
+ sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse");
+ if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj))
+ new->p.nsip_wait_recurse = true;
+ else
+ new->p.nsip_wait_recurse = false;
+
+ pview = NULL;
+ result = dns_viewlist_find(&ns_g_server->viewlist,
+ view->name, view->rdclass, &pview);
+ if (result == ISC_R_SUCCESS) {
+ 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 != NULL || !*old_rpz_okp);
+ 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_def, ttl_def,
+ old_zone, old_rpz_okp);
+ if (result != ISC_R_SUCCESS) {
+ if (pview != NULL)
+ 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 != NULL && memcmp(&old->p, &new->p, sizeof(new->p)) != 0)
+ *old_rpz_okp = false;
+ if (*old_rpz_okp) {
+ dns_rpz_detach_rpzs(&view->rpzs);
+ dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs);
+ } else if (old != NULL && pview != NULL) {
+ pview->rpzs->rpz_ver += 1;
+ view->rpzs->rpz_ver = pview->rpzs->rpz_ver;
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_DEBUG_LEVEL1,
+ "updated RPZ policy: version %d",
+ view->rpzs->rpz_ver);
+ }
+
+ if (pview != NULL)
+ 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;
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "catz: allow-new-zones statement missing from "
+ "config; cannot add zone from the catalog");
+ goto cleanup;
+ }
+
+ isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE);
+ dns_name_totext(dns_catz_entry_getname(ev->entry), true, &namebuf);
+ isc_buffer_putuint8(&namebuf, 0);
+
+ /* Zone shouldn't already exist */
+ result = dns_zt_find(ev->view->zonetable,
+ dns_catz_entry_getname(ev->entry), 0, NULL, &zone);
+
+ if (ev->mod == true) {
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: error \"%s\" while trying to "
+ "modify zone \"%s\"",
+ isc_result_totext(result),
+ nameb);
+ goto cleanup;
+ } else {
+ if (!dns_zone_getadded(zone)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_WARNING,
+ "catz: catz_addmodzone_taskaction: "
+ "zone '%s' is not a dynamically "
+ "added zone",
+ nameb);
+ goto cleanup;
+ }
+ if (dns_zone_get_parentcatz(zone) != ev->origin) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_delzone_taskaction: "
+ "zone '%s' exists in multiple "
+ "catalog zones",
+ nameb);
+ goto cleanup;
+ }
+ dns_zone_detach(&zone);
+ }
+
+ } else {
+ if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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_buffer3(cfg->add_parser, confbuf, "catz", 0,
+ &cfg_type_addzoneconf, &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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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, cfg->actx,
+ true, false, ev->mod);
+ dns_view_freeze(ev->view);
+ isc_task_endexclusive(task);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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,
+ dns_catz_entry_getname(ev->entry), 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_loadnew(zone);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_t *dbp = NULL;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "catz: dns_zone_loadnew() 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_zone_detach(&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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_delzone_taskaction: "
+ "zone '%s' not found", cname);
+ goto cleanup;
+ }
+
+ if (!dns_zone_getadded(zone)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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_zone_detach(&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;
+ isc_task_t *task;
+ isc_result_t result;
+ isc_taskaction_t action;
+
+ 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);
+ }
+
+ event = (catz_chgzone_event_t *) isc_event_allocate(view->mctx, origin,
+ type, action, NULL,
+ sizeof(*event));
+ if (event == NULL)
+ return (ISC_R_NOMEMORY);
+
+ 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_zone_attach(origin, &event->origin);
+ dns_view_attach(view, &event->view);
+
+ task = NULL;
+ result = isc_taskmgr_excltask(taskmgr, &task);
+ REQUIRE(result == ISC_R_SUCCESS);
+ 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, 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_view_t *pview = NULL;
+
+ 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, ns_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, ns_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;
+
+ result = dns_viewlist_find(&ns_g_server->viewlist,
+ view->name,
+ view->rdclass, &pview);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /*
+ * xxxwpk todo: reconfigure the zone!!!!
+ */
+ cfg_obj_log(catz_obj, ns_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
+ */
+ result = dns_catz_get_iterator(zone, &it);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL,
+ "catz: unable to create iterator");
+ goto cleanup;
+ }
+
+ 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);
+ RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
+
+ dns_zone_setview(dnszone, view);
+ if (view->acache != NULL)
+ dns_zone_setacache(dnszone, view->acache);
+ 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))
+ result = ns_config_getipandkeylist(config, 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, ns_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_isuint32(obj))
+ opts->min_update_interval = cfg_obj_asuint32(obj);
+
+ cleanup:
+ if (pview != NULL)
+ dns_view_detach(&pview);
+ 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, const cfg_obj_t *config,
+ const cfg_obj_t *catz_obj)
+{
+ const cfg_listelt_t *zone_element;
+ const dns_catz_zones_t *old = NULL;
+ dns_view_t *pview = NULL;
+ isc_result_t result;
+
+ /* xxxwpk TODO do it cleaner, once, somewhere */
+ ns_catz_cbdata.server = ns_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->catzs, &ns_catz_zonemodmethods,
+ view->mctx, ns_g_taskmgr, ns_g_timermgr));
+
+ result = dns_viewlist_find(&ns_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result == ISC_R_SUCCESS)
+ old = pview->catzs;
+
+ if (old != NULL) {
+ dns_catz_catzs_detach(&view->catzs);
+ dns_catz_catzs_attach(pview->catzs, &view->catzs);
+ dns_catz_prereconfig(view->catzs);
+ }
+
+ while (zone_element != NULL) {
+ CHECK(configure_catz_zone(view, 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 != NULL)
+ dns_view_detach(&pview);
+
+ return (result);
+}
+
+#define CHECK_RRL(cond, pat, val1, val2) \
+ do { \
+ if (!(cond)) { \
+ cfg_obj_log(obj, ns_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, ns_g_lctx,
+ ns_g_aclconfctx, ns_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, dns_name_t *name,
+ dns_name_t *origin, 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, dns_name_t *name,
+ 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 *zone, 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 *myzone = 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 (zone != 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(zone, typec, dbargv, view->mctx);
+ if (result != ISC_R_SUCCESS)
+ zone = NULL;
+
+ if (zone != NULL && dns_zone_gettype(zone) != dns_zone_master)
+ zone = NULL;
+ if (zone != NULL && dns_zone_getfile(zone) != NULL)
+ zone = NULL;
+ if (zone != NULL) {
+ dns_zone_getraw(zone, &myzone);
+ if (myzone != NULL) {
+ dns_zone_detach(&myzone);
+ zone = NULL;
+ }
+ }
+ }
+
+ if (zone == NULL) {
+ CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &myzone));
+ zone = myzone;
+ CHECK(dns_zone_setorigin(zone, name));
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+ if (db == NULL)
+ CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
+ empty_dbtype));
+ dns_zone_setclass(zone, view->rdclass);
+ dns_zone_settype(zone, dns_zone_master);
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+ }
+
+ 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_setoption2(zone, DNS_ZONEOPT2_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "automatic empty zone%s%s: %s",
+ sep, viewname, namebuf);
+
+ cleanup:
+ if (myzone != NULL)
+ dns_zone_detach(&myzone);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, false);
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ INSIST(version == NULL);
+
+ 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 = ns_g_defaultdnstap;
+ const cfg_obj_t *dlist = NULL;
+ dns_dtmsgtype_t dttypes = 0;
+ dns_dtmode_t dmode;
+ unsigned int i;
+ struct fstrm_iothr_options *fopt = NULL;
+
+ result = ns_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, "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;
+ }
+
+ 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 (ns_g_server->dtenv == NULL && dttypes != 0) {
+ obj = NULL;
+ CHECKM(ns_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);
+
+ fopt = fstrm_iothr_options_init();
+ fstrm_iothr_options_set_num_input_queues(fopt, ns_g_cpus);
+ fstrm_iothr_options_set_queue_model(fopt,
+ FSTRM_IOTHR_QUEUE_MODEL_MPSC);
+
+ obj = NULL;
+ result = ns_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 = ns_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 = ns_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 = ns_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 = ns_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 = ns_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 = ns_config_get(maps, "fstrm-set-reopen-interval",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_reopen_interval(fopt, i);
+ }
+
+ CHECKM(dns_dt_create(ns_g_mctx, dmode, dpath, &fopt,
+ &ns_g_server->dtenv),
+ "unable to create dnstap environment");
+ }
+
+ if (ns_g_server->dtenv == NULL)
+ return (ISC_R_SUCCESS);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnstap-version", &obj);
+ if (result != ISC_R_SUCCESS) {
+ /* not specified; use the product and version */
+ dns_dt_setversion(ns_g_server->dtenv, PRODUCT " " VERSION);
+ } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) {
+ /* Quoted string */
+ dns_dt_setversion(ns_g_server->dtenv, cfg_obj_asstring(obj));
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnstap-identity", &obj);
+ if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
+ /* "hostname" is interpreted as boolean true */
+ char buf[256];
+ result = ns_os_gethostname(buf, sizeof(buf));
+ if (result == ISC_R_SUCCESS)
+ dns_dt_setidentity(ns_g_server->dtenv, buf);
+ } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) {
+ /* Quoted string */
+ dns_dt_setidentity(ns_g_server->dtenv, cfg_obj_asstring(obj));
+ }
+
+ dns_dt_attach(ns_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(ns_g_mctx, 1, &acl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_iptable_addprefix2(acl->iptable, &addr, 96,
+ true, false);
+ if (result == ISC_R_SUCCESS)
+ dns_acl_attach(acl, &ns_g_mapped);
+ dns_acl_detach(&acl);
+ return (result);
+}
+
+/*
+ * 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,
+ ns_cachelist_t *cachelist, 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 *dlvobj = NULL;
+ unsigned int dlzargc;
+ char **dlzargv;
+ const cfg_obj_t *dyndb_list;
+ const cfg_obj_t *disabled;
+ const cfg_obj_t *obj, *obj2;
+ const cfg_listelt_t *element;
+ in_port_t port;
+ dns_cache_t *cache = NULL;
+ isc_result_t result;
+ unsigned int cleaning_interval;
+ size_t max_cache_size;
+ uint32_t max_cache_size_percent = 0;
+ size_t max_acache_size;
+ size_t max_adb_size;
+ uint32_t lame_ttl, fail_ttl;
+ dns_tsig_keyring_t *ring = 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 reused_cache = 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;
+ ns_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;
+ isc_dscp_t dscp4 = -1, dscp6 = -1;
+ dns_dyndbctx_t *dctx = 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++] = ns_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(ns_config_getport(config, &port), "port");
+ dns_view_setdstport(view, port);
+
+ /*
+ * Create additional cache for this view and zones under the view
+ * if explicitly enabled.
+ * XXX950 default to on.
+ */
+ obj = NULL;
+ (void)ns_config_get(maps, "acache-enable", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj)) {
+ cmctx = NULL;
+ CHECK(isc_mem_create(0, 0, &cmctx));
+ CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
+ ns_g_timermgr));
+ isc_mem_setname(cmctx, "acache", NULL);
+ isc_mem_detach(&cmctx);
+ }
+ if (view->acache != NULL) {
+ obj = NULL;
+ result = ns_config_get(maps, "acache-cleaning-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_acache_setcleaninginterval(view->acache,
+ cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-acache-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isstring(obj)) {
+ str = cfg_obj_asstring(obj);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ max_acache_size = 0;
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > SIZE_MAX) {
+ cfg_obj_log(obj, ns_g_lctx,
+ ISC_LOG_WARNING,
+ "'max-acache-size "
+ "%" PRIu64 "' "
+ "is too large for this "
+ "system; reducing to %lu",
+ value, (unsigned long)SIZE_MAX);
+ value = SIZE_MAX;
+ }
+ max_acache_size = (size_t) value;
+ }
+ dns_acache_setcachesize(view->acache, max_acache_size);
+ }
+
+ /*
+ * 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 &&
+ ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) {
+ CHECK(configure_rpz(view, obj, &old_rpz_ok));
+ }
+
+ obj = NULL;
+ if (view->rdclass == dns_rdataclass_in && need_hints &&
+ ns_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) {
+ CHECK(configure_catz(view, config, obj));
+ }
+
+ /*
+ * 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, actx, false, old_rpz_ok,
+ false));
+ }
+
+ /*
+ * 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 = ns_config_get(maps, "cleaning-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ cleaning_interval = cfg_obj_asuint32(obj) * 60;
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-cache-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ 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, ns_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, ns_g_lctx,
+ ISC_LOG_WARNING,
+ "Unable to determine amount of physical "
+ "memory, setting 'max-cache-size' to "
+ "unlimited");
+ } else {
+ cfg_obj_log(obj, ns_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 = ns_checknames_get(maps, "response", &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
+ INSIST(0);
+
+ obj = NULL;
+ result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ zero_no_soattl = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_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 = ns_config_get(maps, "dns64-server", &myobj);
+ if (result == ISC_R_SUCCESS)
+ server = cfg_obj_asstring(myobj);
+ else
+ server = NULL;
+
+ myobj = NULL;
+ result = ns_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,
+ ns_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,
+ ns_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,
+ ns_g_lctx, actx,
+ mctx, 0, &excluded);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ } else {
+ if (ns_g_mapped == NULL) {
+ result = create_mapped_acl();
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ dns_acl_attach(ns_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 = ns_config_get(maps, "dnssec-accept-expired", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->acceptexpired = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-validation", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ view->enablevalidation = cfg_obj_asboolean(obj);
+ } else {
+ /* If dnssec-validation is not boolean, it must be "auto" */
+ view->enablevalidation = true;
+ auto_root = true;
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-cache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxcachettl = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-ncache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxncachettl = cfg_obj_asuint32(obj);
+ if (view->maxncachettl > 7 * 24 * 3600)
+ view->maxncachettl = 7 * 24 * 3600;
+
+ /*
+ * 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 unsharable, 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 = ns_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,
+ cleaning_interval, max_cache_size)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(&ns_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(3),
+ "reusing existing cache");
+ reused_cache = true;
+ 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.
+ */
+ CHECK(isc_mem_create(0, 0, &cmctx));
+ isc_mem_setname(cmctx, "cache", NULL);
+ CHECK(isc_mem_create(0, 0, &hmctx));
+ isc_mem_setname(hmctx, "cache_heap", NULL);
+ CHECK(dns_cache_create3(cmctx, hmctx, ns_g_taskmgr,
+ ns_g_timermgr, view->rdclass,
+ cachename, "rbt", 0, NULL,
+ &cache));
+ isc_mem_detach(&cmctx);
+ isc_mem_detach(&hmctx);
+ }
+ nsc = isc_mem_get(mctx, sizeof(*nsc));
+ if (nsc == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ 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_setcache2(view, cache, shared_cache);
+
+ /*
+ * cache-file cannot be inherited if views are present, but this
+ * should be caught by the configuration checking stage.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "cache-file", &obj);
+ if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
+ CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
+ if (!reused_cache && !shared_cache)
+ CHECK(dns_cache_load(cache));
+ }
+
+ dns_cache_setcleaninginterval(cache, cleaning_interval);
+ dns_cache_setcachesize(cache, max_cache_size);
+
+ dns_cache_detach(&cache);
+
+ /*
+ * Resolver.
+ *
+ * XXXRTH Hardwired number of tasks.
+ */
+ CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, &dscp4,
+ (ISC_LIST_PREV(view, link)
+ == NULL)));
+ CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, &dscp6,
+ (ISC_LIST_PREV(view, link)
+ == NULL)));
+ if (dispatch4 == NULL && dispatch6 == NULL) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "unable to obtain neither an IPv4 nor"
+ " 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(ns_g_udpdisp, MAX_UDP_DISPATCH);
+ CHECK(dns_view_createresolver(view, ns_g_taskmgr, RESOLVER_NTASKS,
+ ndisp, ns_g_socketmgr, ns_g_timermgr,
+ resopts, ns_g_dispatchmgr,
+ dispatch4, dispatch6));
+
+ if (dscp4 == -1)
+ dscp4 = ns_g_dscp;
+ if (dscp6 == -1)
+ dscp6 = ns_g_dscp;
+ if (dscp4 != -1)
+ dns_resolver_setquerydscp4(view->resolver, dscp4);
+ if (dscp6 != -1)
+ dns_resolver_setquerydscp6(view->resolver, dscp6);
+
+ /*
+ * 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 = ns_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;
+
+ if (strcasecmp(resp, "drop") == 0)
+ r = DNS_R_DROP;
+ else if (strcasecmp(resp, "fail") == 0)
+ r = DNS_R_SERVFAIL;
+ else
+ INSIST(0);
+
+ dns_resolver_setquotaresponse(view->resolver,
+ dns_quotatype_server, r);
+ }
+
+ obj = NULL;
+ result = ns_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 = ns_config_get(maps, "lame-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ lame_ttl = cfg_obj_asuint32(obj);
+ if (lame_ttl > 1800)
+ lame_ttl = 1800;
+ dns_resolver_setlamettl(view->resolver, lame_ttl);
+
+ /*
+ * Set the resolver's query timeout.
+ */
+ obj = NULL;
+ result = ns_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);
+
+ /* 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 = ns_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 = ns_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 = ns_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 = ns_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 supported DNSSEC algorithms.
+ */
+ dns_resolver_reset_algorithms(view->resolver);
+ disabled = NULL;
+ (void)ns_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/DLV digest types.
+ */
+ dns_resolver_reset_ds_digests(view->resolver);
+ disabled = NULL;
+ (void)ns_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)ns_config_get(maps, "forward", &forwardtype);
+ (void)ns_config_get(maps, "forwarders", &forwarders);
+ if (forwarders != NULL)
+ CHECK(configure_forward(config, view, dns_rootname,
+ forwarders, forwardtype));
+
+ /*
+ * Dual Stack Servers.
+ */
+ alternates = NULL;
+ (void)ns_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, ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "no root hints for view '%s'",
+ view->name);
+ }
+
+ /*
+ * Configure the view's TSIG keys.
+ */
+ CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
+ if (ns_g_server->sessionkey != NULL) {
+ CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname,
+ ns_g_server->sessionkey));
+ }
+ dns_view_setkeyring(view, ring);
+ dns_tsigkeyring_detach(&ring);
+
+ /*
+ * See if we can re-use a dynamic key ring.
+ */
+ result = dns_viewlist_find(&ns_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)ns_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)ns_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_g_server->aclenv);
+
+ /*
+ * 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, ns_g_mctx,
+ &view->matchclients));
+ CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations",
+ NULL, actx, ns_g_mctx,
+ &view->matchdestinations));
+
+ /*
+ * Configure the "match-recursive-only" option.
+ */
+ obj = NULL;
+ (void)ns_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 = ns_config_get(maps, "recursion", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->recursion = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "auth-nxdomain", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->auth_nxdomain = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "minimal-any", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->minimal_any = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+ }
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+
+ obj = NULL;
+ result = ns_config_get(maps, "trust-anchor-telemetry", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->trust_anchor_telemetry = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "root-key-sentinel", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->root_key_sentinel = cfg_obj_asboolean(obj);
+
+ /*
+ * Set sources where additional data and CNAME/DNAME
+ * targets for authoritative answers may be found.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "additional-from-auth", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->additionalfromauth = cfg_obj_asboolean(obj);
+ if (view->recursion && ! view->additionalfromauth) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
+ "'additional-from-auth no' is only supported "
+ "with 'recursion no'");
+ view->additionalfromauth = true;
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "additional-from-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->additionalfromcache = cfg_obj_asboolean(obj);
+ if (view->recursion && ! view->additionalfromcache) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
+ "'additional-from-cache no' is only supported "
+ "with 'recursion no'");
+ view->additionalfromcache = true;
+ }
+
+ CHECK(configure_view_acl(vconfig, config, ns_g_config,
+ "allow-query-cache-on", NULL, actx,
+ ns_g_mctx, &view->cacheonacl));
+
+ /*
+ * Set the "allow-query", "allow-query-cache", "allow-recursion",
+ * and "allow-recursion-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,
+ ns_g_mctx, &view->queryacl));
+
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL,
+ "allow-query-cache", NULL, actx,
+ ns_g_mctx, &view->cacheacl));
+
+ 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,
+ ns_g_mctx, &view->recursionacl));
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL,
+ "allow-recursion-on", NULL, actx,
+ ns_g_mctx, &view->recursiononacl));
+ }
+
+ if (view->recursion) {
+ /*
+ * "allow-query-cache" inherits from "allow-recursion" if set,
+ * otherwise from "allow-query" if set.
+ * "allow-recursion" inherits from "allow-query-cache" 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);
+ }
+ }
+ 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);
+ }
+ }
+
+ /*
+ * If any are still unset, we now get default "allow-recursion",
+ * "allow-recursion-on" and "allow-query-cache" ACLs from
+ * the global config.
+ */
+ if (view->recursionacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, ns_g_config,
+ "allow-recursion", NULL,
+ actx, ns_g_mctx,
+ &view->recursionacl));
+ }
+ if (view->recursiononacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, ns_g_config,
+ "allow-recursion-on", NULL,
+ actx, ns_g_mctx,
+ &view->recursiononacl));
+ }
+ if (view->cacheacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, ns_g_config,
+ "allow-query-cache", NULL,
+ actx, ns_g_mctx,
+ &view->cacheacl));
+ }
+ } else if (view->cacheacl == NULL) {
+ /*
+ * We're not recursive; if "allow-query-cache" hasn't been
+ * set at the options/view level, set it to none.
+ */
+ CHECK(dns_acl_none(mctx, &view->cacheacl));
+ }
+
+ if (view->queryacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, ns_g_config,
+ "allow-query", NULL,
+ actx, ns_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, ns_g_config,
+ "no-case-compress", NULL, actx,
+ ns_g_mctx, &view->nocasecompress));
+
+ /*
+ * Disable name compression completely, this is a tradeoff
+ * between CPU and network usage.
+ */
+ obj = NULL;
+ result = ns_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, ns_g_config,
+ "deny-answer-addresses", "acl",
+ actx, ns_g_mctx,
+ &view->denyansweracl));
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
+ "except-from", ns_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", ns_g_mctx,
+ &view->denyanswernames));
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
+ "except-from", ns_g_mctx,
+ &view->answernames_exclude));
+
+ /*
+ * Configure sortlist, if set
+ */
+ CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
+ &view->sortlist));
+
+ /*
+ * Configure default allow-notify, allow-update
+ * and allow-update-forwarding ACLs, so they can be
+ * inherited by zones. (Note these cannot be set at
+ * options/view level.)
+ */
+ if (view->notifyacl == NULL) {
+ CHECK(configure_view_acl(vconfig, config, ns_g_config,
+ "allow-notify", NULL, actx,
+ ns_g_mctx, &view->notifyacl));
+ }
+ if (view->updateacl == NULL) {
+ CHECK(configure_view_acl(NULL, NULL, ns_g_config,
+ "allow-update", NULL, actx,
+ ns_g_mctx, &view->updateacl));
+ }
+ if (view->upfwdacl == NULL) {
+ CHECK(configure_view_acl(NULL, NULL, ns_g_config,
+ "allow-update-forwarding", NULL, actx,
+ ns_g_mctx, &view->upfwdacl));
+ }
+
+ /*
+ * Configure default allow-transer ACL so it can be inherited
+ * by zones. (Note this *can* be set at options or view level.)
+ */
+ if (view->transferacl == NULL) {
+ CHECK(configure_view_acl(vconfig, config, ns_g_config,
+ "allow-transfer", NULL, actx,
+ ns_g_mctx, &view->transferacl));
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "provide-ixfr", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->provideixfr = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "request-nsid", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requestnsid = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "send-cookie", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->sendcookie = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "require-server-cookie", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requireservercookie = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "v6-bias", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->v6bias = cfg_obj_asuint32(obj) * 1000;
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-clients-per-query", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ max_clients_per_query = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_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 = ns_config_get(maps, "max-recursion-depth", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-recursion-queries", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_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;
+
+ if (strcasecmp(resp, "drop") == 0)
+ r = DNS_R_DROP;
+ else if (strcasecmp(resp, "fail") == 0)
+ r = DNS_R_SERVFAIL;
+ else
+ INSIST(0);
+
+ dns_resolver_setquotaresponse(view->resolver,
+ dns_quotatype_zone, r);
+ }
+
+#ifdef ALLOW_FILTER_AAAA
+ obj = NULL;
+ result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj))
+ view->v4_aaaa = dns_aaaa_filter;
+ else
+ view->v4_aaaa = dns_aaaa_ok;
+ } else {
+ const char *v4_aaaastr = cfg_obj_asstring(obj);
+ if (strcasecmp(v4_aaaastr, "break-dnssec") == 0)
+ view->v4_aaaa = dns_aaaa_break_dnssec;
+ else
+ INSIST(0);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "filter-aaaa-on-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj))
+ view->v6_aaaa = dns_aaaa_filter;
+ else
+ view->v6_aaaa = dns_aaaa_ok;
+ } else {
+ const char *v6_aaaastr = cfg_obj_asstring(obj);
+ if (strcasecmp(v6_aaaastr, "break-dnssec") == 0)
+ view->v6_aaaa = dns_aaaa_break_dnssec;
+ else
+ INSIST(0);
+ }
+
+ CHECK(configure_view_acl(vconfig, config, ns_g_config,
+ "filter-aaaa", NULL, actx,
+ ns_g_mctx, &view->aaaa_acl));
+#endif
+ obj = NULL;
+ result = ns_config_get(maps, "prefetch", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const cfg_obj_t *trigger, *eligible;
+
+ trigger = cfg_tuple_get(obj, "trigger");
+ view->prefetch_trigger = cfg_obj_asuint32(trigger);
+ if (view->prefetch_trigger > 10)
+ view->prefetch_trigger = 10;
+ eligible = cfg_tuple_get(obj, "eligible");
+ if (cfg_obj_isvoid(eligible)) {
+ int m;
+ for (m = 1; maps[m] != NULL; m++) {
+ obj = NULL;
+ result = ns_config_get(&maps[m],
+ "prefetch", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ eligible = cfg_tuple_get(obj, "eligible");
+ if (cfg_obj_isuint32(eligible))
+ break;
+ }
+ INSIST(cfg_obj_isuint32(eligible));
+ }
+ view->prefetch_eligible = cfg_obj_asuint32(eligible);
+ if (view->prefetch_eligible < view->prefetch_trigger + 6)
+ view->prefetch_eligible = view->prefetch_trigger + 6;
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-enable", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->enablednssec = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(optionmaps, "dnssec-lookaside", &obj);
+ if (result == ISC_R_SUCCESS) {
+ /* "auto" is deprecated, log a warning if seen */
+ const char *dom;
+ dlvobj = cfg_listelt_value(cfg_list_first(obj));
+ dom = cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain"));
+ if (cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) {
+ /* If "no", skip; if "auto", log warning */
+ if (!strcasecmp(dom, "no")) {
+ result = ISC_R_NOTFOUND;
+ } else if (!strcasecmp(dom, "auto")) {
+ /*
+ * Warning logged by libbind9.
+ */
+ result = ISC_R_NOTFOUND;
+ }
+ }
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dns_name_t *dlv, *iscdlv;
+ dns_fixedname_t f;
+
+ /* Also log a warning if manually configured to dlv.isc.org */
+ iscdlv = dns_fixedname_initname(&f);
+ CHECK(dns_name_fromstring(iscdlv, "dlv.isc.org", 0, NULL));
+
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ obj = cfg_tuple_get(obj, "trust-anchor");
+
+ dlv = dns_fixedname_name(&view->dlv_fixed);
+ CHECK(dns_name_fromstring(dlv, cfg_obj_asstring(obj),
+ DNS_NAME_DOWNCASE, NULL));
+ if (dns_name_equal(dlv, iscdlv)) {
+ /*
+ * Warning logged by libbind9.
+ */
+ view->dlv = NULL;
+ } else {
+ view->dlv = dlv;
+ }
+ }
+ } else {
+ view->dlv = NULL;
+ }
+
+ /*
+ * 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 = ns_config_get(maps, "dnssec-must-be-secure", &obj);
+ if (result == ISC_R_SUCCESS)
+ CHECK(mustbesecure(obj, view->resolver));
+
+ obj = NULL;
+ result = ns_config_get(maps, "nta-recheck", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->nta_recheck = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "nta-lifetime", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->nta_lifetime = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_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 = ns_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));
+ CHECK(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);
+
+#ifdef HAVE_DLOPEN
+ 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,
+ ns_g_lctx, view,
+ ns_g_server->zonemgr,
+ ns_g_server->task,
+ ns_g_timermgr, &dctx));
+ }
+
+ CHECK(configure_dyndb(dyndb, mctx, dctx));
+ }
+#endif
+
+ /*
+ * Setup automatic empty zones. If recursion is off then
+ * they are disabled by default.
+ */
+ obj = NULL;
+ (void)ns_config_get(maps, "empty-zones-enable", &obj);
+ (void)ns_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 && !lwresd_g_useresolvconf) {
+ 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;
+
+ name = dns_fixedname_initname(&fixed);
+
+ obj = NULL;
+ result = ns_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 = ns_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 = ns_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
+ INSIST(0);
+ }
+
+ 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,
+ &dnsforwarders);
+ if (result == ISC_R_SUCCESS &&
+ dnsforwarders->fwdpolicy == dns_fwdpolicy_only)
+ continue;
+
+ /*
+ * See if we can re-use a existing zone.
+ */
+ result = dns_viewlist_find(&ns_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;
+ result = ns_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 = ns_config_get(maps, "servfail-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ fail_ttl = cfg_obj_asuint32(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 = ns_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;
+
+#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:
+ 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.
+ */
+ if (ns_g_lwresdonly && ns_g_port != 0)
+ port = ns_g_port;
+ else
+ CHECKM(ns_config_getport(config, &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, ns_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, ns_g_lctx,
+ ISC_LOG_ERROR,
+ "port '%u' out of range",
+ val);
+ return (ISC_R_RANGE);
+ }
+ myport = (in_port_t) val;
+ }
+ CHECK(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);
+ CHECK(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, dns_name_t *origin,
+ const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype)
+{
+ const cfg_obj_t *portobj, *dscpobj;
+ const cfg_obj_t *faddresses;
+ const cfg_listelt_t *element;
+ dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
+ dns_forwarderlist_t fwdlist;
+ dns_forwarder_t *fwd;
+ isc_result_t result;
+ in_port_t port;
+ isc_dscp_t dscp = -1;
+
+ ISC_LIST_INIT(fwdlist);
+
+ /*
+ * Determine which port to send forwarded requests to.
+ */
+ if (ns_g_lwresdonly && ns_g_port != 0)
+ port = ns_g_port;
+ else
+ CHECKM(ns_config_getport(config, &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, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t) val;
+ }
+ }
+
+ /*
+ * DSCP value for forwarded requests.
+ */
+ dscp = ns_g_dscp;
+ if (forwarders != NULL) {
+ dscpobj = cfg_tuple_get(forwarders, "dscp");
+ if (cfg_obj_isuint32(dscpobj)) {
+ if (cfg_obj_asuint32(dscpobj) > 63) {
+ cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+ "dscp value '%u' is out of range",
+ cfg_obj_asuint32(dscpobj));
+ return (ISC_R_RANGE);
+ }
+ dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+ }
+ }
+
+ 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));
+ if (fwd == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ fwd->addr = *cfg_obj_assockaddr(forwarder);
+ if (isc_sockaddr_getport(&fwd->addr) == 0)
+ isc_sockaddr_setport(&fwd->addr, port);
+ fwd->dscp = cfg_obj_getdscp(forwarder);
+ if (fwd->dscp == -1)
+ fwd->dscp = dscp;
+ ISC_LINK_INIT(fwd, link);
+ ISC_LIST_APPEND(fwdlist, fwd, link);
+ }
+
+ if (ISC_LIST_EMPTY(fwdlist)) {
+ if (forwardtype != NULL)
+ cfg_obj_log(forwardtype, ns_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
+ INSIST(0);
+ }
+ }
+
+ 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, ns_g_lctx, ISC_LOG_WARNING,
+ "could not set up forwarding for domain '%s': %s",
+ namebuf, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ 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(ns_config_getclass(classobj, dns_rdataclass_in,
+ &viewclass));
+ if (dns_rdataclass_ismeta(viewclass)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_mctx, viewclass, viewname, &view);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_entropy_getdata(ns_g_entropy, view->secret,
+ sizeof(view->secret), NULL, 0);
+ if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&view);
+ return (result);
+ }
+
+#ifdef HAVE_GEOIP
+ view->aclenv.geoip = ns_g_geoip;
+#endif
+
+ 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, 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 *signing = NULL;
+ const cfg_obj_t *viewobj = NULL;
+ isc_result_t result;
+ 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;
+
+ 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(ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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, ns_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, ns_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, ns_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, ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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))
+ CHECK(dns_view_adddelegationonly(view, origin));
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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))
+ CHECK(dns_view_adddelegationonly(view, origin));
+ goto cleanup;
+ }
+
+ /*
+ * "delegation-only zones" aren't zones either.
+ */
+ if (strcasecmp(ztypestr, "delegation-only") == 0) {
+ result = 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, ns_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(ns_g_server->zonemgr,
+ &zone));
+ CHECK(dns_zone_setorigin(zone, origin));
+ dns_zone_setview(zone, view);
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr,
+ zone));
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+ }
+ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf,
+ 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, ns_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.
+ */
+ for (rpz_num = 0; ; ++rpz_num) {
+ if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones) {
+ 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 master zone cannot
+ * be reused if the options specify a slave 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(&ns_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 && !ns_zone_reusable(zone, zconfig))
+ dns_zone_detach(&zone);
+
+ 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);
+ if (view->acache != NULL)
+ dns_zone_setacache(zone, view->acache);
+ } else {
+ /*
+ * We cannot reuse an existing zone, we have
+ * to create a new one.
+ */
+ CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone));
+ CHECK(dns_zone_setorigin(zone, origin));
+ dns_zone_setview(zone, view);
+ if (view->acache != NULL)
+ dns_zone_setacache(zone, view->acache);
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+ dns_zone_setstats(zone, ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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);
+
+ /*
+ * 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))
+ CHECK(dns_view_adddelegationonly(view, origin));
+ }
+
+ /*
+ * Mark whether the zone was originally added at runtime or not
+ */
+ dns_zone_setadded(zone, added);
+
+ signing = NULL;
+ if ((strcasecmp(ztypestr, "master") == 0 ||
+ strcasecmp(ztypestr, "slave") == 0) &&
+ cfg_map_get(zoptions, "inline-signing", &signing) == ISC_R_SUCCESS &&
+ cfg_obj_asboolean(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);
+ if (view->acache != NULL)
+ dns_zone_setacache(raw, view->acache);
+ dns_zone_setstats(raw, ns_g_server->zonestats);
+ CHECK(dns_zone_link(zone, raw));
+ }
+ if (cfg_map_get(zoptions, "ixfr-from-differences",
+ &ixfrfromdiffs) == ISC_R_SUCCESS)
+ {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "zone '%s': 'ixfr-from-differences' is "
+ "ignored for inline-signed zones",
+ zname);
+ }
+ }
+
+ /*
+ * Configure the zone.
+ */
+ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, 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, false);
+
+ 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(&ns_g_server->viewlist,
+ view->name, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND &&
+ result != ISC_R_SUCCESS)
+ return (result);
+
+ if (pview != NULL && pview->managed_keys != NULL) {
+ dns_zone_attach(pview->managed_keys, &view->managed_keys);
+ dns_zone_setview(pview->managed_keys, view);
+ dns_view_detach(&pview);
+ dns_zone_synckeyzone(view->managed_keys);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* No existing keydata zone was found; create one */
+ CHECK(dns_zonemgr_createzone(ns_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_zone_setview(zone, view);
+ dns_zone_settype(zone, dns_zone_key);
+ dns_zone_setclass(zone, view->rdclass);
+
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+
+ if (view->acache != NULL)
+ dns_zone_setacache(zone, view->acache);
+
+ 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, ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 = ns_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, ns_g_lctx, ISC_LOG_WARNING,
+ "option 'directory' contains relative path '%s'",
+ directory);
+
+ result = isc_dir_chdir(directory);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
+ "change directory to '%s' failed: %s",
+ directory, isc_result_totext(result));
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+scan_interfaces(ns_server_t *server, bool verbose) {
+ isc_result_t result;
+ bool match_mapped = server->aclenv.match_mapped;
+#ifdef HAVE_GEOIP
+ bool use_ecs = server->aclenv.geoip_use_ecs;
+#endif
+
+ result = ns_interfacemgr_scan(server->interfacemgr, verbose);
+ /*
+ * Update the "localhost" and "localnets" ACLs to match the
+ * current set of network interfaces.
+ */
+ dns_aclenv_copy(&server->aclenv,
+ ns_interfacemgr_getaclenv(server->interfacemgr));
+
+ server->aclenv.match_mapped = match_mapped;
+#ifdef HAVE_GEOIP
+ server->aclenv.geoip_use_ecs = use_ecs;
+#endif
+
+ return (result);
+}
+
+static isc_result_t
+add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
+ isc_dscp_t dscp, bool wcardport_ok)
+{
+ ns_listenelt_t *lelt = NULL;
+ dns_acl_t *src_acl = NULL;
+ isc_result_t result;
+ isc_sockaddr_t any_sa6;
+ isc_netaddr_t netaddr;
+
+ REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
+
+ isc_sockaddr_any6(&any_sa6);
+ if (!isc_sockaddr_equal(&any_sa6, addr) &&
+ (wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
+ isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
+
+ result = dns_acl_create(mctx, 0, &src_acl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_iptable_addprefix(src_acl->iptable,
+ &netaddr, 128, true);
+ if (result != ISC_R_SUCCESS)
+ goto clean;
+
+ result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
+ dscp, src_acl, &lelt);
+ if (result != ISC_R_SUCCESS)
+ goto clean;
+ ISC_LIST_APPEND(list->elts, lelt, link);
+ }
+
+ return (ISC_R_SUCCESS);
+
+ clean:
+ INSIST(lelt == NULL);
+ dns_acl_detach(&src_acl);
+
+ return (result);
+}
+
+/*
+ * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
+ * to update the listening interfaces accordingly.
+ * We currently only consider IPv6, because this only affects IPv6 wildcard
+ * sockets.
+ */
+static void
+adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
+ isc_result_t result;
+ ns_listenlist_t *list = NULL;
+ dns_view_t *view;
+ dns_zone_t *zone, *next;
+ isc_sockaddr_t addr, *addrp;
+ isc_dscp_t dscp = -1;
+
+ result = ns_listenlist_create(mctx, &list);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ dns_dispatch_t *dispatch6;
+
+ dispatch6 = dns_resolver_dispatchv6(view->resolver);
+ if (dispatch6 == NULL)
+ continue;
+ result = dns_dispatch_getlocaladdress(dispatch6, &addr);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /*
+ * We always add non-wildcard address regardless of whether
+ * the port is 'any' (the fourth arg is TRUE): if the port is
+ * specific, we need to add it since it may conflict with a
+ * listening interface; if it's zero, we'll dynamically open
+ * query ports, and some of them may override an existing
+ * wildcard IPv6 port.
+ */
+ /* XXXMPA fix dscp */
+ result = add_listenelt(mctx, list, &addr, dscp, true);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ zone = NULL;
+ for (result = dns_zone_first(server->zonemgr, &zone);
+ result == ISC_R_SUCCESS;
+ next = NULL, result = dns_zone_next(zone, &next), zone = next) {
+ dns_view_t *zoneview;
+
+ /*
+ * At this point the zone list may contain a stale zone
+ * just removed from the configuration. To see the validity,
+ * check if the corresponding view is in our current view list.
+ * There may also be old zones that are still in the process
+ * of shutting down and have detached from their old view
+ * (zoneview == NULL).
+ */
+ zoneview = dns_zone_getview(zone);
+ if (zoneview == NULL)
+ continue;
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL && view != zoneview;
+ view = ISC_LIST_NEXT(view, link))
+ ;
+ if (view == NULL)
+ continue;
+
+ addrp = dns_zone_getnotifysrc6(zone);
+ dscp = dns_zone_getnotifysrc6dscp(zone);
+ result = add_listenelt(mctx, list, addrp, dscp, false);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ addrp = dns_zone_getxfrsource6(zone);
+ dscp = dns_zone_getxfrsource6dscp(zone);
+ result = add_listenelt(mctx, list, addrp, dscp, false);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ ns_interfacemgr_adjust(server->interfacemgr, list, true);
+
+ clean:
+ ns_listenlist_detach(&list);
+ return;
+
+ fail:
+ /*
+ * Even when we failed the procedure, most of other interfaces
+ * should work correctly. We therefore just warn it.
+ */
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "could not adjust the listen-on list; "
+ "some interfaces may not work");
+ goto clean;
+}
+
+/*
+ * This event callback is invoked to do periodic network interface
+ * scanning. It is also called by ns_server_scan_interfaces(),
+ * invoked by "rndc scan"
+ */
+
+static void
+interface_timer_tick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ ns_server_t *server = (ns_server_t *) event->ev_arg;
+ INSIST(task == server->task);
+ UNUSED(task);
+
+ isc_event_free(&event);
+
+ /*
+ * XXX should scan interfaces unlocked and get exclusive access
+ * only to replace ACLs.
+ */
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ scan_interfaces(server, false);
+ isc_task_endexclusive(server->task);
+}
+
+static void
+heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
+ ns_server_t *server = (ns_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_rdataset_t rdataset;
+ dns_rdataset_t sigrdataset;
+ dns_fetch_t *fetch;
+} 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;
+
+ UNUSED(task);
+ INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
+ INSIST(event->ev_arg != NULL);
+
+ 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);
+ 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 *dst, dns_name_t **origin, dns_keytable_t *keytable,
+ dns_keynode_t *keynode)
+{
+ dns_keynode_t *firstnode = keynode;
+ dns_keynode_t *nextnode;
+ unsigned int i, n = 0;
+ uint16_t ids[12];
+ isc_textregion_t r;
+ char label[64];
+ int m;
+
+ REQUIRE(origin != NULL && *origin == NULL);
+
+ do {
+ dst_key_t *key = dns_keynode_key(keynode);
+ if (key != NULL) {
+ *origin = dst_key_name(key);
+ if (n < (sizeof(ids)/sizeof(ids[0]))) {
+ ids[n] = dst_key_id(key);
+ n++;
+ }
+ }
+ nextnode = NULL;
+ (void)dns_keytable_nextkeynode(keytable, keynode, &nextnode);
+ if (keynode != firstnode)
+ dns_keytable_detachkeynode(keytable, &keynode);
+ keynode = nextnode;
+ } while (keynode != NULL);
+
+ 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(dst, label, *origin, 0, NULL));
+}
+
+static void
+dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
+ struct dotat_arg *dotat_arg = arg;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixed, fdomain;
+ dns_name_t *tatname, *domain;
+ dns_rdataset_t nameservers;
+ dns_name_t *origin = NULL;
+ isc_result_t result;
+ dns_view_t *view;
+ isc_task_t *task;
+ ns_tat_t *tat;
+
+ REQUIRE(keytable != NULL);
+ REQUIRE(keynode != NULL);
+ REQUIRE(arg != NULL);
+
+ view = dotat_arg->view;
+ task = dotat_arg->task;
+
+ tatname = dns_fixedname_initname(&fixed);
+ result = get_tat_qname(tatname, &origin, keytable, keynode);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+
+ dns_name_format(tatname, namebuf, sizeof(namebuf));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO,
+ "%s: sending trust-anchor-telemetry query '%s/NULL'",
+ view->name, namebuf);
+
+ tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat));
+ if (tat == NULL)
+ return;
+
+ tat->mctx = NULL;
+ tat->task = NULL;
+ tat->fetch = NULL;
+ dns_rdataset_init(&tat->rdataset);
+ dns_rdataset_init(&tat->sigrdataset);
+ isc_mem_attach(dotat_arg->view->mctx, &tat->mctx);
+ isc_task_attach(task, &tat->task);
+
+ /*
+ * 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.
+ *
+ * 'origin' holds the domain name at 'keynode', i.e. the domain name
+ * for which the trust anchors to be reported by this TAT query are
+ * defined.
+ *
+ * After the dns_view_findzonecut() call, 'domain' will hold the
+ * deepest zone cut we can find for 'origin' while 'nameservers' will
+ * hold the NS RRset at that zone cut.
+ */
+ domain = dns_fixedname_initname(&fdomain);
+ dns_rdataset_init(&nameservers);
+ result = dns_view_findzonecut(view, origin, domain, 0, 0, true,
+ &nameservers, NULL);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_resolver_createfetch(view->resolver, tatname,
+ dns_rdatatype_null, domain,
+ &nameservers, NULL, 0,
+ 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) {
+ isc_task_detach(&tat->task);
+ isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat));
+ }
+}
+
+static void
+tat_timer_tick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ ns_server_t *server = (ns_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 = 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(ns_server_t *server, char **field, const char *value) {
+ char *copy;
+
+ if (value != NULL) {
+ copy = isc_mem_strdup(server->mctx, value);
+ if (copy == NULL)
+ return (ISC_R_NOMEMORY);
+ } 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(ns_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 (ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_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, \
+ ns_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) {
+ const char *type;
+
+ if (dns_zone_getview(zone) != uap)
+ return (ISC_R_SUCCESS);
+
+ switch (dns_zone_gettype(zone)) {
+ case dns_zone_master:
+ type = "master";
+ break;
+ case dns_zone_slave:
+ type = "slave";
+ break;
+ case dns_zone_stub:
+ type = "stub";
+ break;
+ case dns_zone_staticstub:
+ type = "static-stub";
+ break;
+ case dns_zone_redirect:
+ type = "redirect";
+ break;
+ default:
+ type = "other";
+ break;
+ }
+ dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+cleanup_session_key(ns_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)
+ dns_tsigkey_detach(&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,
+ dns_name_t *keyname, const char *algstr,
+ dns_name_t *algname, unsigned int algtype,
+ uint16_t bits, isc_mem_t *mctx,
+ dns_tsigkey_t **tsigkeyp)
+{
+ 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;
+ isc_stdtime_t now;
+ dns_tsigkey_t *tsigkey = NULL;
+ FILE *fp = NULL;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Dump the key to the buffer for later use. Should be done before
+ * we transfer the ownership of key to tsigkey.
+ */
+ 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));
+
+ /* Store the key in tsigkey. */
+ isc_stdtime_get(&now);
+ CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key,
+ false, NULL, now, now, mctx, NULL,
+ &tsigkey));
+
+ /* Dump the key to the key file. */
+ fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, true);
+ if (fp == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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;
+
+ dst_key_free(&key);
+
+ *tsigkeyp = tsigkey;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+ if (key != NULL)
+ dst_key_free(&key);
+
+ return (result);
+}
+
+static isc_result_t
+configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
+ isc_mem_t *mctx)
+{
+ const char *keyfile, *keynamestr, *algstr;
+ unsigned int algtype;
+ dns_fixedname_t fname;
+ dns_name_t *keyname, *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 = ns_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 = ns_g_defaultsessionkeyfile;
+
+ obj = NULL;
+ result = ns_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 = ns_config_get(maps, "session-keyalg", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ algstr = cfg_obj_asstring(obj);
+ algname = NULL;
+ result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits);
+ if (result != ISC_R_SUCCESS) {
+ const char *s = " (keeping current key)";
+
+ cfg_obj_log(obj, ns_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));
+ if (server->session_keyname == NULL)
+ goto cleanup;
+ dns_name_init(server->session_keyname, NULL);
+ CHECK(dns_name_dup(keyname, mctx, server->session_keyname));
+
+ server->session_keyfile = isc_mem_strdup(mctx, keyfile);
+ if (server->session_keyfile == NULL)
+ goto cleanup;
+
+ server->session_keyalg = algtype;
+ server->session_keybits = bits;
+
+ CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr,
+ algname, algtype, bits, mctx,
+ &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(ns_g_addparser);
+ result = cfg_parse_file(ns_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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);
+
+ CHECK(migrate_nzf(view));
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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;
+
+ 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 *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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ result = ns_config_get(maps, "allow-new-zones", &nz);
+ if (result == ISC_R_SUCCESS)
+ allow = cfg_obj_asboolean(nz);
+
+#ifdef HAVE_LMDB
+ result = ns_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, ns_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, ns_g_lctx,
+ ISC_LOG_ERROR,
+ "'lmdb-mapsize "
+ "%" PRId64 "' "
+ "is too large",
+ mapsize);
+ return (ISC_R_FAILURE);
+ }
+ }
+#else
+ UNUSED(obj);
+#endif /* HAVE_LMDB */
+
+ /*
+ * A non-empty catalog-zones statement implies allow-new-zones
+ */
+ if (!allow) {
+ const cfg_obj_t *cz = NULL;
+ result = ns_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));
+ if (nzcfg == NULL) {
+ dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * 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(ns_g_addparser, &nzcfg->add_parser);
+ isc_mem_attach(view->mctx, &nzcfg->mctx);
+ cfg_aclconfctx_attach(actx, &nzcfg->actx);
+
+ result = dns_view_setnewzones(view, allow, 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;
+ dns_zone_t *raw = 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(&ns_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;
+ }
+
+ dns_zone_getraw(zone, &raw);
+
+ if (result == ISC_R_SUCCESS) {
+ dns_zone_setviewcommit(zone);
+ if (raw != NULL)
+ dns_zone_setviewcommit(raw);
+ } else {
+ dns_zone_setviewrevert(zone);
+ if (raw != NULL)
+ dns_zone_setviewrevert(raw);
+ }
+
+ if (raw != NULL) {
+ dns_zone_detach(&raw);
+ }
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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, &ns_g_server->viewlist, 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;
+
+ REQUIRE(view != NULL);
+ REQUIRE(key != NULL);
+ REQUIRE(data != NULL);
+ REQUIRE(text != NULL);
+ REQUIRE(zoneconfig != NULL && *zoneconfig == NULL);
+
+ if (*text == NULL) {
+ result = isc_buffer_allocate(view->mctx, text, 256);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ } 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, 5 + zone_name_len + 1 +
+ zone_config_len + 2);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ putstr(text, "zone ");
+ putmem(text, (const void *) zone_name, zone_name_len);
+ putstr(text, " ");
+ putmem(text, (const void *) zone_config, zone_config_len);
+ putstr(text, ";\n");
+
+ cfg_parser_reset(ns_g_addparser);
+ result = cfg_parse_buffer3(ns_g_addparser, *text, zone_name, 0,
+ &cfg_type_addzoneconf, &zoneconf);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_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.
+ */
+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(ns_g_addparser, &zconfigobj);
+ }
+
+ if (text != NULL) {
+ isc_buffer_free(&text);
+ }
+ if (zconfigobj != NULL) {
+ cfg_obj_destroy(ns_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,
+ &ns_g_server->viewlist, 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);
+ }
+
+ result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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);
+ 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);
+
+ CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi));
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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);
+
+ if (zoneconf != NULL) {
+ cfg_obj_destroy(ns_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(ns_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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ obj = NULL;
+ (void) ns_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "skipping lock-file check ");
+ return (ISC_R_SUCCESS);
+ } else if (ns_g_forcelock) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "'lock-file' has no effect "
+ "because the server was run with -X");
+ server->lockfile = isc_mem_strdup(server->mctx,
+ ns_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 (ns_g_forcelock && ns_g_defaultlockfile != NULL) {
+ INSIST(server->lockfile == NULL);
+ server->lockfile = isc_mem_strdup(server->mctx,
+ ns_g_defaultlockfile);
+ }
+
+ if (server->lockfile == NULL)
+ return (ISC_R_SUCCESS);
+
+ if (ns_os_issingleton(server->lockfile))
+ return (ISC_R_SUCCESS);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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, ns_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 *views;
+ dns_view_t *view = NULL;
+ dns_view_t *view_next;
+ dns_viewlist_t tmpviewlist;
+ dns_viewlist_t viewlist, builtin_viewlist;
+ in_port_t listen_port, udpport_low, udpport_high;
+ int i;
+ 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_resourcevalue_t nfiles;
+ isc_result_t result, tresult;
+ uint32_t heartbeat_interval;
+ uint32_t interface_interval;
+ uint32_t reserved;
+ uint32_t udpsize;
+ uint32_t transfer_message_size;
+ ns_cache_t *nsc;
+ ns_cachelist_t cachelist, tmpcachelist;
+ ns_altsecret_t *altsecret;
+ ns_altsecretlist_t altsecrets, tmpaltsecrets;
+ unsigned int maxsocks;
+ uint32_t softquota = 0;
+
+ ISC_LIST_INIT(viewlist);
+ ISC_LIST_INIT(builtin_viewlist);
+ ISC_LIST_INIT(cachelist);
+ ISC_LIST_INIT(altsecrets);
+
+ /* Create the ACL configuration context */
+ if (ns_g_aclconfctx != NULL) {
+ cfg_aclconfctx_detach(&ns_g_aclconfctx);
+ }
+ CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx));
+
+ /*
+ * Shut down all dyndb instances.
+ */
+ dns_dyndb_cleanup(false);
+
+ /*
+ * Parse the global default pseudo-config file.
+ */
+ if (first_time) {
+ result = ns_config_parsedefaults(ns_g_parser, &ns_g_config);
+ if (result != ISC_R_SUCCESS) {
+ ns_main_earlyfatal("unable to load "
+ "internal defaults: %s",
+ isc_result_totext(result));
+ }
+ RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
+ &ns_g_defaults) == ISC_R_SUCCESS);
+ }
+
+ /*
+ * Parse the configuration file using the new config code.
+ */
+ config = NULL;
+
+ /*
+ * Unless this is lwresd with the -C option, parse the config file.
+ */
+ if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "loading configuration from '%s'",
+ filename);
+ CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
+ cfg_parser_setcallback(conf_parser, directory_callback, NULL);
+ result = cfg_parse_file(conf_parser, filename,
+ &cfg_type_namedconf, &config);
+ }
+
+ /*
+ * If this is lwresd with the -C option, or lwresd with no -C or -c
+ * option where the above parsing failed, parse resolv.conf.
+ */
+ if (ns_g_lwresdonly &&
+ (lwresd_g_useresolvconf ||
+ (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
+ {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "loading configuration from '%s'",
+ lwresd_g_resolvconffile);
+ if (conf_parser != NULL) {
+ cfg_parser_destroy(&conf_parser);
+ }
+ CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
+ result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser,
+ &config);
+ }
+ CHECK(result);
+
+ /*
+ * Check the validity of the configuration.
+ */
+ CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
+
+ /*
+ * 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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ /*
+ * 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 = ns_config_get(maps, "bindkeys-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->bindkeysfile,
+ cfg_obj_asstring(obj)), "strdup");
+
+ if (access(server->bindkeysfile, R_OK) == 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reading built-in trust anchors "
+ "from file '%s'", server->bindkeysfile);
+
+ CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx,
+ &bindkeys_parser));
+
+ result = cfg_parse_file(bindkeys_parser, server->bindkeysfile,
+ &cfg_type_bindkeys, &bindkeys);
+ CHECK(result);
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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));
+
+ /*
+ * Check if max number of open sockets that the system allows is
+ * sufficiently large. Failing this condition is not necessarily fatal,
+ * but may cause subsequent runtime failures for a busy recursive
+ * server.
+ */
+ result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);
+ if (result != ISC_R_SUCCESS) {
+ maxsocks = 0;
+ }
+ result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
+ if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "max open files (%" PRIu64 ")"
+ " is smaller than max sockets (%u)",
+ nfiles, maxsocks);
+ }
+
+ /*
+ * Set the number of socket reserved for TCP, stdio etc.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "reserved-sockets", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ reserved = cfg_obj_asuint32(obj);
+ if (maxsocks != 0) {
+ if (maxsocks < 128U) { /* Prevent underflow. */
+ reserved = 0;
+ } else if (reserved > maxsocks - 128U) { /* Minimum UDP space. */
+ reserved = maxsocks - 128;
+ }
+ }
+ /* Minimum TCP/stdio space. */
+ if (reserved < 128U) {
+ reserved = 128;
+ }
+ if (reserved + 128U > maxsocks && maxsocks != 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "less than 128 UDP sockets available after "
+ "applying 'reserved-sockets' and 'maxsockets'");
+ }
+ isc__socketmgr_setreserved(ns_g_socketmgr, reserved);
+
+#ifdef HAVE_GEOIP
+ /*
+ * 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 = ns_config_get(maps, "geoip-directory", &obj);
+ if (result == ISC_R_SUCCESS && cfg_obj_isstring(obj)) {
+ char *dir;
+ DE_CONST(cfg_obj_asstring(obj), dir);
+ ns_geoip_load(dir);
+ } else {
+ ns_geoip_load(NULL);
+ }
+ ns_g_aclconfctx->geoip = ns_g_geoip;
+
+ obj = NULL;
+ result = ns_config_get(maps, "geoip-use-ecs", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ ns_g_server->aclenv.geoip_use_ecs = cfg_obj_asboolean(obj);
+#endif /* HAVE_GEOIP */
+
+ /*
+ * Configure various server options.
+ */
+ configure_server_quota(maps, "transfers-out", &server->xfroutquota);
+ configure_server_quota(maps, "tcp-clients", &server->tcpquota);
+ configure_server_quota(maps, "recursive-clients",
+ &server->recursionquota);
+
+ if (server->recursionquota.max > 1000) {
+ int margin = ISC_MAX(100, ns_g_cpus + 1);
+ if (margin > server->recursionquota.max - 100) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "'recursive-clients %d' too low when "
+ "running with %d worker threads",
+ server->recursionquota.max, ns_g_cpus);
+ CHECK(ISC_R_RANGE);
+ }
+ softquota = server->recursionquota.max - margin;
+ } else {
+ softquota = (server->recursionquota.max * 90) / 100;
+ }
+
+ isc_quota_soft(&server->recursionquota, softquota);
+
+ /*
+ * Set "blackhole". Only legal at options level; there is
+ * no default.
+ */
+ CHECK(configure_view_acl(NULL, config, NULL, "blackhole", NULL,
+ ns_g_aclconfctx, ns_g_mctx,
+ &server->blackholeacl));
+ if (server->blackholeacl != NULL) {
+ dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
+ server->blackholeacl);
+ }
+
+ /*
+ * Set "keep-response-order". Only legal at options or
+ * global defaults level.
+ */
+ CHECK(configure_view_acl(NULL, config, ns_g_config,
+ "keep-response-order", NULL,
+ ns_g_aclconfctx, ns_g_mctx,
+ &server->keepresporder));
+
+ obj = NULL;
+ result = ns_config_get(maps, "match-mapped-addresses", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ server->aclenv.match_mapped = cfg_obj_asboolean(obj);
+
+ CHECKM(ns_statschannels_configure(ns_g_server, config, ns_g_aclconfctx),
+ "configuring statistics server(s)");
+
+ /*
+ * Configure sets of UDP query source ports.
+ */
+ CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
+ "creating UDP port set");
+ CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
+ "creating UDP port set");
+
+ usev4ports = NULL;
+ usev6ports = NULL;
+ avoidv4ports = NULL;
+ avoidv6ports = NULL;
+
+ (void)ns_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_g_disable4) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using default UDP/IPv4 port range: "
+ "[%d, %d]", udpport_low, udpport_high);
+ }
+ }
+ (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
+ if (avoidv4ports != NULL) {
+ portset_fromconf(v4portset, avoidv4ports, false);
+ }
+
+ (void)ns_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_g_disable6) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using default UDP/IPv6 port range: "
+ "[%d, %d]", udpport_low, udpport_high);
+ }
+ }
+ (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
+ if (avoidv6ports != NULL) {
+ portset_fromconf(v6portset, avoidv6ports, false);
+ }
+
+ dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
+
+ /*
+ * Set the EDNS UDP size when we don't match a view.
+ */
+ obj = NULL;
+ result = ns_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;
+ }
+ ns_g_udpsize = (uint16_t)udpsize;
+
+ /* Set the transfer message size for TCP */
+ obj = NULL;
+ result = ns_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->transfer_tcp_message_size = (uint16_t) transfer_message_size;
+
+ /*
+ * Configure the zone manager.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "transfers-in", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "transfers-per-ns", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-rate", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "startup-notify-rate", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_setstartupnotifyrate(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_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 (ns_g_port != 0) {
+ listen_port = ns_g_port;
+ } else {
+ CHECKM(ns_config_getport(config, &listen_port), "port");
+ }
+
+ /*
+ * Determing the default DSCP code point.
+ */
+ CHECKM(ns_config_getdscp(config, &ns_g_dscp), "dscp");
+
+ /*
+ * Find the listen queue depth.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "tcp-listen-queue", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ ns_g_listen = cfg_obj_asuint32(obj);
+ if ((ns_g_listen > 0) && (ns_g_listen < 10)) {
+ ns_g_listen = 10;
+ }
+
+ /*
+ * 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, we can't use it here, since it isn't
+ * used if we're in lwresd mode. This way is easier.
+ */
+ if (options != NULL) {
+ (void)cfg_map_get(options, "listen-on", &clistenon);
+ }
+ if (clistenon != NULL) {
+ /* check return code? */
+ (void)ns_listenlist_fromconfig(clistenon, config,
+ ns_g_aclconfctx,
+ ns_g_mctx, AF_INET,
+ &listenon);
+ } else if (!ns_g_lwresdonly) {
+ /*
+ * Not specified, use default.
+ */
+ CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
+ -1, true, &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 return code? */
+ (void)ns_listenlist_fromconfig(clistenon, config,
+ ns_g_aclconfctx,
+ ns_g_mctx, AF_INET6,
+ &listenon);
+ } else if (!ns_g_lwresdonly) {
+ /*
+ * Not specified, use default.
+ */
+ CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
+ -1, true, &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 = scan_interfaces(server, 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 = ns_config_get(maps, "interface-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ interface_interval = cfg_obj_asuint32(obj) * 60;
+ 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 = ns_config_get(maps, "automatic-interface-scan", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ server->interface_auto = cfg_obj_asboolean(obj);
+
+ /*
+ * Configure the dialup heartbeat timer.
+ */
+ obj = NULL;
+ result = ns_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, ns_g_tat_interval, 0);
+ CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker, NULL,
+ &interval, false));
+
+ /*
+ * Write the PID file.
+ */
+ obj = NULL;
+ if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) {
+ if (cfg_obj_isvoid(obj)) {
+ ns_os_writepidfile(NULL, first_time);
+ } else {
+ ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
+ }
+ } else if (ns_g_lwresdonly) {
+ ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
+ } else {
+ ns_os_writepidfile(ns_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, ns_g_mctx);
+
+ 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,
+ ns_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,
+ ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "sizing zone task pool based on %d zones", num_zones);
+ CHECK(dns_zonemgr_setsize(ns_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, bindkeys, ns_g_mctx,
+ ns_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, bindkeys,
+ ns_g_mctx, ns_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(ns_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, bindkeys,
+ ns_g_mctx, ns_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(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
+ &t),
+ "configuring TKEY");
+ if (server->tkeyctx != NULL) {
+ dns_tkeyctx_destroy(&server->tkeyctx);
+ }
+ server->tkeyctx = t;
+ }
+
+ /*
+ * Bind the control port(s).
+ */
+ CHECKM(ns_controls_configure(ns_g_server->controls, config,
+ ns_g_aclconfctx),
+ "binding control channel(s)");
+
+ /*
+ * Bind the lwresd port(s).
+ */
+ CHECKM(ns_lwresd_configure(ns_g_mctx, config),
+ "binding lightweight resolver ports");
+
+ /*
+ * Open the source of entropy.
+ */
+ if (first_time) {
+ obj = NULL;
+ result = ns_config_get(maps, "random-device", &obj);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "no source of entropy found");
+ } else {
+ const char *randomdev = cfg_obj_asstring(obj);
+ int level = ISC_LOG_ERROR;
+ result = isc_entropy_createfilesource(ns_g_entropy,
+ randomdev);
+#ifdef PATH_RANDOMDEV
+ if (ns_g_fallbackentropy != NULL) {
+ level = ISC_LOG_INFO;
+ }
+#endif
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ level,
+ "could not open entropy source "
+ "%s: %s",
+ randomdev,
+ isc_result_totext(result));
+ }
+#ifdef PATH_RANDOMDEV
+ if (ns_g_fallbackentropy != NULL) {
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO,
+ "using pre-chroot entropy source "
+ "%s",
+ PATH_RANDOMDEV);
+ isc_entropy_detach(&ns_g_entropy);
+ isc_entropy_attach(ns_g_fallbackentropy,
+ &ns_g_entropy);
+ }
+ isc_entropy_detach(&ns_g_fallbackentropy);
+ }
+#endif
+ }
+ }
+
+#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) {
+ ns_os_changeuser();
+ }
+
+ /*
+ * Check that the working directory is writable.
+ */
+ if (!isc_file_isdirwritable(".")) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "the working directory is not writable");
+ }
+
+#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 (ns_g_logstderr) {
+ const cfg_obj_t *logobj = NULL;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 = ns_log_configure(NULL, logobj);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "checking logging configuration "
+ "failed: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ }
+ } else {
+ const cfg_obj_t *logobj = NULL;
+
+ CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
+ "creating new logging configuration");
+
+ logobj = NULL;
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj != NULL) {
+ CHECKM(ns_log_configure(logc, logobj),
+ "configuring logging");
+ } else {
+ CHECKM(ns_log_setdefaultchannels(logc),
+ "setting up default logging channels");
+ CHECKM(ns_log_setunmatchedcategory(logc),
+ "setting up default 'category unmatched'");
+ CHECKM(ns_log_setdefaultcategory(logc),
+ "setting up default 'category default'");
+ }
+
+ CHECKM(isc_logconfig_use(ns_g_lctx, logc),
+ "installing logging configuration");
+ logc = NULL;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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 (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
+ server->log_queries = 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)
+ server->log_queries = true;
+ }
+ }
+ }
+ }
+
+ obj = NULL;
+ if (options != NULL &&
+ cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) {
+ ns_g_memstatistics = cfg_obj_asboolean(obj);
+ } else {
+ ns_g_memstatistics = (isc_mem_debugging & ISC_MEM_DEBUGRECORD);
+ }
+
+ obj = NULL;
+ if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) {
+ ns_main_setmemstats(cfg_obj_asstring(obj));
+ } else if (ns_g_memstatistics) {
+ ns_main_setmemstats("named.memstats");
+ } else {
+ ns_main_setmemstats(NULL);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "statistics-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = ns_config_get(maps, "dump-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = ns_config_get(maps, "secroots-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = ns_config_get(maps, "recursing-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = ns_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 = ns_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 = ns_config_get(maps, "server-id", &obj);
+ server->server_usehostname = false;
+ if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
+ /* The parser translates "hostname" to true */
+ server->server_usehostname = cfg_obj_asboolean(obj);
+ result = setstring(server, &server->server_id, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ } else if (result == ISC_R_SUCCESS) {
+ /* Found a quoted string */
+ CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
+ } else {
+ result = setstring(server, &server->server_id, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+
+ obj = NULL;
+ result = ns_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 = ns_config_get(maps, "answer-cookie", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ server->answercookie = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "cookie-algorithm", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
+#if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES)
+ server->cookiealg = ns_cookiealg_aes;
+#else
+ INSIST(0);
+#endif
+ } else if (strcasecmp(cfg_obj_asstring(obj), "sha1") == 0) {
+ server->cookiealg = ns_cookiealg_sha1;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "sha256") == 0) {
+ server->cookiealg = ns_cookiealg_sha256;
+ } else {
+ INSIST(0);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "cookie-secret", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *str;
+ bool first = true;
+ isc_buffer_t b;
+ unsigned int usedlength;
+
+ 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->secret, 0,
+ sizeof(server->secret));
+ isc_buffer_init(&b, server->secret,
+ sizeof(server->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->mctx,
+ sizeof(*altsecret));
+ if (altsecret == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ 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->mctx, altsecret,
+ sizeof(*altsecret));
+ goto cleanup;
+ }
+ ISC_LIST_INITANDAPPEND(altsecrets,
+ altsecret, link);
+ }
+
+ usedlength = isc_buffer_usedlength(&b);
+ switch (server->cookiealg) {
+ case ns_cookiealg_aes:
+ if (usedlength != ISC_AES128_KEYLENGTH) {
+ CHECKM(ISC_R_RANGE,
+ "AES cookie-secret must be "
+ "128 bits");
+ }
+ break;
+ case ns_cookiealg_sha1:
+ if (usedlength != ISC_SHA1_DIGESTLENGTH) {
+ CHECKM(ISC_R_RANGE,
+ "SHA1 cookie-secret must be "
+ "160 bits");
+ }
+ break;
+ case ns_cookiealg_sha256:
+ if (usedlength != ISC_SHA256_DIGESTLENGTH) {
+ CHECKM(ISC_R_RANGE,
+ "SHA256 cookie-secret must be "
+ "256 bits");
+ }
+ break;
+ }
+ }
+ } else {
+ result = isc_entropy_getdata(ns_g_entropy,
+ server->secret,
+ sizeof(server->secret),
+ NULL,
+ 0);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Swap altsecrets lists.
+ */
+ tmpaltsecrets = server->altsecrets;
+ server->altsecrets = altsecrets;
+ altsecrets = tmpaltsecrets;
+
+ (void) ns_server_loadnta(server);
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (logc != NULL) {
+ isc_logconfig_destroy(&logc);
+ }
+
+ if (v4portset != NULL) {
+ isc_portset_destroy(ns_g_mctx, &v4portset);
+ }
+
+ if (v6portset != NULL) {
+ isc_portset_destroy(ns_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);
+ }
+
+ 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, false,
+ removed, view);
+ }
+ dns_view_detach(&view);
+ }
+
+ /* 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));
+ }
+
+ /* Same cleanup for altsecrets list. */
+ while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) {
+ ISC_LIST_UNLINK(altsecrets, altsecret, link);
+ isc_mem_put(server->mctx, altsecret, sizeof(*altsecret));
+ }
+
+ /*
+ * Adjust the listening interfaces in accordance with the source
+ * addresses specified in views and zones.
+ */
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ adjust_interfaces(server, ns_g_mctx);
+ }
+
+ /*
+ * Record the time of most recent configuration
+ */
+ tresult = isc_time_now(&ns_g_configtime);
+ if (tresult != ISC_R_SUCCESS) {
+ ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_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;
+ ns_server_t *server = zl->server;
+ bool reconfig = zl->reconfig;
+ unsigned int refs;
+
+
+ /*
+ * Force zone maintenance. Do this after loading
+ * so that we know when we need to force AXFR of
+ * slave zones whose master files are missing.
+ *
+ * We use the zoneload reference counter to let us
+ * know when all views are finished.
+ */
+ isc_refcount_decrement(&zl->refs, &refs);
+ if (refs != 0)
+ return (ISC_R_SUCCESS);
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "any newly configured zones are now loaded");
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "all zones loaded");
+ }
+
+ CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
+ "forcing zone maintenance");
+
+ ns_os_started();
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_NOTICE, "running");
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+load_zones(ns_server_t *server, bool init, bool reconfig) {
+ isc_result_t result;
+ dns_view_t *view;
+ ns_zoneload_t *zl;
+ unsigned int refs = 0;
+
+ zl = isc_mem_get(server->mctx, sizeof (*zl));
+ if (zl == NULL)
+ return (ISC_R_NOMEMORY);
+ 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);
+ 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);
+ 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, NULL);
+ CHECK(dns_view_asyncload2(view, view_loaded, zl, reconfig));
+ }
+
+ cleanup:
+ isc_refcount_decrement(&zl->refs, &refs);
+ if (refs == 0) {
+ isc_refcount_destroy(&zl->refs);
+ isc_mem_put(server->mctx, zl, sizeof (*zl));
+ } else if (init) {
+ /*
+ * Place the task manager into privileged mode. This
+ * ensures that after we leave task-exclusive mode, no
+ * other tasks will be able to run except for the ones
+ * that are loading zones. (This should only be done during
+ * the initial server setup; it isn't necessary during
+ * a reload.)
+ */
+ isc_taskmgr_setmode(ns_g_taskmgr, isc_taskmgrmode_privileged);
+ }
+
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+static void
+run_server(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ ns_server_t *server = (ns_server_t *)event->ev_arg;
+
+ INSIST(task == server->task);
+
+ isc_event_free(&event);
+
+ CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
+ &ns_g_dispatchmgr),
+ "creating dispatch manager");
+
+ dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
+
+ CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
+ ns_g_socketmgr, ns_g_dispatchmgr,
+ server->task, &server->interfacemgr),
+ "creating interface manager");
+
+ CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task,
+ interface_timer_tick,
+ server, &server->interface_timer),
+ "creating interface timer");
+
+ CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task,
+ heartbeat_timer_tick,
+ server, &server->heartbeat_timer),
+ "creating heartbeat timer");
+
+ CHECKFATAL(isc_timer_create(ns_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(ns_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task, pps_timer_tick,
+ server, &server->pps_timer),
+ "creating pps timer");
+
+ CHECKFATAL(cfg_parser_create(ns_g_mctx, ns_g_lctx, &ns_g_parser),
+ "creating default configuration parser");
+
+ CHECKFATAL(cfg_parser_create(ns_g_mctx, ns_g_lctx, &ns_g_addparser),
+ "creating additional configuration parser");
+
+ if (ns_g_lwresdonly)
+ CHECKFATAL(load_configuration(lwresd_g_conffile, server,
+ true),
+ "loading configuration");
+ else
+ CHECKFATAL(load_configuration(ns_g_conffile, server, true),
+ "loading configuration");
+
+ isc_hash_init();
+
+ CHECKFATAL(load_zones(server, true, false), "loading zones");
+#ifdef ENABLE_AFL
+ ns_g_run_done = true;
+#endif
+}
+
+void
+ns_server_flushonshutdown(ns_server_t *server, bool flush) {
+
+ REQUIRE(NS_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;
+ ns_server_t *server = (ns_server_t *)event->ev_arg;
+ bool flush = server->flushonshutdown;
+ ns_cache_t *nsc;
+ ns_altsecret_t *altsecret;
+
+ UNUSED(task);
+ INSIST(task == server->task);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "shutting down%s",
+ flush ? ": flushing changes" : "");
+
+ ns_statschannels_shutdown(server);
+ ns_controls_shutdown(server->controls);
+ end_reserved_dispatches(server, true);
+ cleanup_session_key(server, server->mctx);
+
+ if (ns_g_aclconfctx != NULL)
+ cfg_aclconfctx_detach(&ns_g_aclconfctx);
+
+ cfg_obj_destroy(ns_g_parser, &ns_g_config);
+ cfg_parser_destroy(&ns_g_parser);
+ cfg_parser_destroy(&ns_g_addparser);
+
+ (void) ns_server_saventa(server);
+
+ 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);
+ }
+
+ 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));
+ }
+
+ while ((altsecret = ISC_LIST_HEAD(server->altsecrets)) != NULL) {
+ ISC_LIST_UNLINK(server->altsecrets, altsecret, link);
+ isc_mem_put(server->mctx, altsecret, sizeof(*altsecret));
+ }
+
+ isc_timer_detach(&server->interface_timer);
+ isc_timer_detach(&server->heartbeat_timer);
+ isc_timer_detach(&server->pps_timer);
+ isc_timer_detach(&server->tat_timer);
+
+ ns_interfacemgr_shutdown(server->interfacemgr);
+ ns_interfacemgr_detach(&server->interfacemgr);
+
+ dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
+
+ dns_zonemgr_shutdown(server->zonemgr);
+
+ if (ns_g_sessionkey != NULL) {
+ dns_tsigkey_detach(&ns_g_sessionkey);
+ dns_name_free(&ns_g_sessionkeyname, server->mctx);
+ }
+
+ if (server->keepresporder != NULL)
+ dns_acl_detach(&server->keepresporder);
+
+ if (server->blackholeacl != NULL)
+ dns_acl_detach(&server->blackholeacl);
+
+#ifdef HAVE_DNSTAP
+ dns_dt_shutdown();
+#endif
+#ifdef HAVE_GEOIP
+ dns_geoip_shutdown();
+#endif
+
+ dns_db_detach(&server->in_roothints);
+
+ isc_task_endexclusive(server->task);
+
+ isc_task_detach(&server->task);
+
+ isc_event_free(&event);
+}
+
+void
+ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
+ isc_result_t result;
+ ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
+
+ if (server == NULL)
+ fatal("allocating server object", ISC_R_NOMEMORY);
+
+ server->mctx = mctx;
+ server->task = NULL;
+
+ /* Initialize configuration data with default values. */
+ result = isc_quota_init(&server->xfroutquota, 10);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = isc_quota_init(&server->tcpquota, 10);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = isc_quota_init(&server->recursionquota, 100);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ result = dns_aclenv_init(mctx, &server->aclenv);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+#ifdef HAVE_GEOIP
+ /* Initialize GeoIP before using ACL environment */
+ ns_geoip_init();
+ server->aclenv.geoip = ns_g_geoip;
+#endif
+
+ /* Initialize server data structures. */
+ server->zonemgr = NULL;
+ server->interfacemgr = NULL;
+ ISC_LIST_INIT(server->viewlist);
+ server->in_roothints = NULL;
+ server->blackholeacl = NULL;
+ server->keepresporder = NULL;
+
+ /* Must be first. */
+ CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy,
+ ns_g_engine, ISC_ENTROPY_GOODONLY),
+ "initializing DST");
+
+ CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
+ &server->in_roothints),
+ "setting up root hints");
+
+ CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
+ "initializing reload event lock");
+ server->reload_event =
+ isc_event_allocate(ns_g_mctx, server,
+ NS_EVENT_RELOAD,
+ ns_server_reload,
+ server,
+ sizeof(isc_event_t));
+ CHECKFATAL(server->reload_event == NULL ?
+ ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "allocating reload event");
+
+ server->tkeyctx = NULL;
+ CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
+ &server->tkeyctx),
+ "creating TKEY context");
+
+ /*
+ * 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(ns_g_taskmgr, 0, &server->task),
+ "creating server task");
+ isc_task_setname(server->task, "server", server);
+ isc_taskmgr_setexcltask(ns_g_taskmgr, server->task);
+ CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
+ "isc_task_onshutdown");
+ CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
+ "isc_app_onrun");
+
+ server->interface_timer = NULL;
+ server->heartbeat_timer = NULL;
+ server->pps_timer = NULL;
+ server->tat_timer = NULL;
+
+ server->interface_interval = 0;
+ server->heartbeat_interval = 0;
+
+ CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
+ ns_g_socketmgr, &server->zonemgr),
+ "dns_zonemgr_create");
+ CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000),
+ "dns_zonemgr_setsize");
+
+ server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
+ CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "isc_mem_strdup");
+ server->nsstats = NULL;
+ server->rcvquerystats = NULL;
+ server->opcodestats = NULL;
+ server->rcodestats = NULL;
+ server->zonestats = NULL;
+ server->resolverstats = NULL;
+ server->sockstats = NULL;
+ server->udpinstats4 = NULL;
+ server->udpoutstats4 = NULL;
+ server->udpinstats6 = NULL;
+ server->udpoutstats6 = NULL;
+ server->tcpinstats4 = NULL;
+ server->tcpoutstats4 = NULL;
+ server->tcpinstats6 = NULL;
+ server->tcpoutstats6 = NULL;
+ CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats,
+ isc_sockstatscounter_max),
+ "isc_stats_create");
+ isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats);
+
+ server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys");
+ CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY :
+ ISC_R_SUCCESS,
+ "isc_mem_strdup");
+
+ server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
+ CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "isc_mem_strdup");
+
+ server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots");
+ CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY :
+ ISC_R_SUCCESS,
+ "isc_mem_strdup");
+
+ server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
+ CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "isc_mem_strdup");
+
+ server->hostname_set = false;
+ server->hostname = NULL;
+ server->version_set = false;
+ server->version = NULL;
+ server->server_usehostname = false;
+ server->server_id = NULL;
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats,
+ dns_nsstatscounter_max),
+ "dns_stats_create (server)");
+
+ CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,
+ &server->rcvquerystats),
+ "dns_stats_create (rcvquery)");
+
+ CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),
+ "dns_stats_create (opcode)");
+
+ CHECKFATAL(dns_rcodestats_create(ns_g_mctx, &server->rcodestats),
+ "dns_stats_create (rcode)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats,
+ dns_zonestatscounter_max),
+ "dns_stats_create (zone)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats,
+ dns_resstatscounter_max),
+ "dns_stats_create (resolver)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats4,
+ dns_sizecounter_in_max),
+ "dns_stats_create (inbound UDP IPv4 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats4,
+ dns_sizecounter_out_max),
+ "dns_stats_create (outbound UDP IPv4 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats6,
+ dns_sizecounter_in_max),
+ "dns_stats_create (inbound UDP IPv6 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats6,
+ dns_sizecounter_out_max),
+ "dns_stats_create (outbound UDP IPv6 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats4,
+ dns_sizecounter_in_max),
+ "dns_stats_create (inbound TCP IPv4 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats4,
+ dns_sizecounter_out_max),
+ "dns_stats_create (outbound TCP IPv4 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats6,
+ dns_sizecounter_in_max),
+ "dns_stats_create (inbound TCP IPv6 traffic size)");
+
+ CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats6,
+ dns_sizecounter_out_max),
+ "dns_stats_create (outbound TCP IPv6 traffic size)");
+
+ server->flushonshutdown = false;
+ server->log_queries = false;
+
+ server->controls = NULL;
+ CHECKFATAL(ns_controls_create(server, &server->controls),
+ "ns_controls_create");
+ server->dispatchgen = 0;
+ ISC_LIST_INIT(server->dispatches);
+
+ ISC_LIST_INIT(server->statschannels);
+
+ ISC_LIST_INIT(server->cachelist);
+
+ ISC_LIST_INIT(server->altsecrets);
+
+ server->sessionkey = NULL;
+ server->session_keyfile = NULL;
+ server->session_keyname = NULL;
+ server->session_keyalg = DST_ALG_UNKNOWN;
+ server->session_keybits = 0;
+
+ server->lockfile = NULL;
+
+ server->dtenv = NULL;
+ server->answercookie = true;
+
+ server->magic = NS_SERVER_MAGIC;
+ *serverp = server;
+}
+
+void
+ns_server_destroy(ns_server_t **serverp) {
+ ns_server_t *server = *serverp;
+ REQUIRE(NS_SERVER_VALID(server));
+
+#ifdef HAVE_DNSTAP
+ if (server->dtenv != NULL)
+ dns_dt_detach(&server->dtenv);
+#endif /* HAVE_DNSTAP */
+
+ ns_controls_destroy(&server->controls);
+
+ isc_stats_detach(&server->nsstats);
+ dns_stats_detach(&server->rcvquerystats);
+ dns_stats_detach(&server->opcodestats);
+ dns_stats_detach(&server->rcodestats);
+ isc_stats_detach(&server->zonestats);
+ isc_stats_detach(&server->resolverstats);
+ isc_stats_detach(&server->sockstats);
+ isc_stats_detach(&server->udpinstats4);
+ isc_stats_detach(&server->udpoutstats4);
+ isc_stats_detach(&server->udpinstats6);
+ isc_stats_detach(&server->udpoutstats6);
+ isc_stats_detach(&server->tcpinstats4);
+ isc_stats_detach(&server->tcpoutstats4);
+ isc_stats_detach(&server->tcpinstats6);
+ isc_stats_detach(&server->tcpoutstats6);
+
+ 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->server_id != NULL)
+ isc_mem_free(server->mctx, server->server_id);
+ if (server->lockfile != NULL)
+ isc_mem_free(server->mctx, server->lockfile);
+
+ if (server->zonemgr != NULL)
+ dns_zonemgr_detach(&server->zonemgr);
+
+ if (server->tkeyctx != NULL)
+ dns_tkeyctx_destroy(&server->tkeyctx);
+
+ dst_lib_destroy();
+
+ isc_event_free(&server->reload_event);
+
+ INSIST(ISC_LIST_EMPTY(server->viewlist));
+ INSIST(ISC_LIST_EMPTY(server->cachelist));
+
+ dns_aclenv_destroy(&server->aclenv);
+
+ isc_quota_destroy(&server->recursionquota);
+ isc_quota_destroy(&server->tcpquota);
+ isc_quota_destroy(&server->xfroutquota);
+
+ server->magic = 0;
+ isc_mem_put(server->mctx, server, sizeof(*server));
+ *serverp = NULL;
+}
+
+static void
+fatal(const char *msg, isc_result_t result) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_CRITICAL, "%s: %s", msg,
+ isc_result_totext(result));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_CRITICAL, "exiting (due to fatal error)");
+ ns_os_shutdown();
+ exit(1);
+}
+
+static void
+start_reserved_dispatches(ns_server_t *server) {
+
+ REQUIRE(NS_SERVER_VALID(server));
+
+ server->dispatchgen++;
+}
+
+static void
+end_reserved_dispatches(ns_server_t *server, bool all) {
+ ns_dispatch_t *dispatch, *nextdispatch;
+
+ REQUIRE(NS_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
+ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) {
+ ns_dispatch_t *dispatch;
+ in_port_t port;
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_result_t result;
+ unsigned int attrs, attrmask;
+
+ REQUIRE(NS_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));
+ if (dispatch == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ dispatch->addr = *addr;
+ dispatch->dispatchgen = server->dispatchgen;
+ dispatch->dispatch = NULL;
+
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ switch (isc_sockaddr_pf(addr)) {
+ case AF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+ case AF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+
+ result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
+ ns_g_taskmgr, &dispatch->addr, 4096,
+ UDPBUFFERS, 32768, 16411, 16433,
+ attrs, attrmask, &dispatch->dispatch);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
+
+ return;
+
+ cleanup:
+ if (dispatch != NULL)
+ isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "unable to create dispatch for reserved port %s: %s",
+ addrbuf, isc_result_totext(result));
+}
+
+
+static isc_result_t
+loadconfig(ns_server_t *server) {
+ isc_result_t result;
+ start_reserved_dispatches(server);
+ result = load_configuration(ns_g_lwresdonly ?
+ lwresd_g_conffile : ns_g_conffile,
+ server, false);
+ if (result == ISC_R_SUCCESS) {
+ end_reserved_dispatches(server, false);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading configuration succeeded");
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "reloading configuration failed: %s",
+ isc_result_totext(result));
+ }
+
+ return (result);
+}
+
+static isc_result_t
+reload(ns_server_t *server) {
+ isc_result_t result;
+ CHECK(loadconfig(server));
+
+ result = load_zones(server, false, false);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading zones succeeded");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "reloading zones failed: %s",
+ isc_result_totext(result));
+
+ cleanup:
+ return (result);
+}
+
+/*
+ * Handle a reload event (from SIGHUP).
+ */
+static void
+ns_server_reload(isc_task_t *task, isc_event_t *event) {
+ ns_server_t *server = (ns_server_t *)event->ev_arg;
+
+ INSIST(task == server->task);
+ UNUSED(task);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "received SIGHUP signal to reload zones");
+ (void)reload(server);
+
+ LOCK(&server->reload_event_lock);
+ INSIST(server->reload_event == NULL);
+ server->reload_event = event;
+ UNLOCK(&server->reload_event_lock);
+}
+
+void
+ns_server_reloadwanted(ns_server_t *server) {
+ LOCK(&server->reload_event_lock);
+ if (server->reload_event != NULL)
+ isc_task_send(server->task, &server->reload_event);
+ UNLOCK(&server->reload_event_lock);
+}
+
+void
+ns_server_scan_interfaces(ns_server_t *server) {
+ isc_result_t result;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "automatic interface rescan");
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ scan_interfaces(server, true);
+ isc_task_endexclusive(server->task);
+}
+
+/*
+ * 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(ns_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];
+
+ 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() */
+ strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE);
+ if (zonename != NULL)
+ strlcpy(zonename, 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) {
+ 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;
+ }
+
+ 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
+ns_server_retransfercommand(ns_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;
+
+ 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_slave || type == dns_zone_stub)
+ dns_zone_forcereload(zone);
+ else
+ result = ISC_R_NOTFOUND;
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*
+ * Act on a "reload" command from the command channel.
+ */
+isc_result_t
+ns_server_reloadcommand(ns_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;
+
+ 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_slave || type == dns_zone_stub) {
+ dns_zone_refresh(zone);
+ dns_zone_detach(&zone);
+ msg = "zone refresh queued";
+ } else {
+ result = dns_zone_load(zone);
+ 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
+ns_server_reconfigcommand(ns_server_t *server) {
+ isc_result_t result;
+
+ CHECK(loadconfig(server));
+
+ result = load_zones(server, false, true);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "scheduled loading new zones");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "loading new zones failed: %s",
+ isc_result_totext(result));
+cleanup:
+ return (result);
+}
+
+/*
+ * Act on a "notify" command from the command channel.
+ */
+isc_result_t
+ns_server_notifycommand(ns_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";
+
+ 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
+ns_server_refreshcommand(ns_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 slave or stub zone";
+ dns_zonetype_t type;
+
+ 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_slave || 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
+ns_server_togglequerylog(ns_server_t *server, isc_lex_t *lex) {
+ bool value;
+ char *ptr;
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ value = server->log_queries ? false : true;
+ } 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 (server->log_queries == value)
+ return (ISC_R_SUCCESS);
+
+ server->log_queries = value;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "query logging is now %s",
+ server->log_queries ? "on" : "off");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ uint16_t family, 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 = ns_listenelt_fromconfig(listener, config, actx,
+ mctx, family, &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);
+}
+
+/*
+ * Create a listen list from the corresponding configuration
+ * data structure.
+ */
+static isc_result_t
+ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ uint16_t family, ns_listenelt_t **target)
+{
+ isc_result_t result;
+ const cfg_obj_t *portobj, *dscpobj;
+ in_port_t port;
+ isc_dscp_t dscp = -1;
+ ns_listenelt_t *delt = NULL;
+ REQUIRE(target != NULL && *target == NULL);
+
+ portobj = cfg_tuple_get(listener, "port");
+ if (!cfg_obj_isuint32(portobj)) {
+ if (ns_g_port != 0) {
+ port = ns_g_port;
+ } else {
+ result = ns_config_getport(config, &port);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else {
+ if (cfg_obj_asuint32(portobj) >= UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port value '%u' is out of range",
+ cfg_obj_asuint32(portobj));
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t)cfg_obj_asuint32(portobj);
+ }
+
+ dscpobj = cfg_tuple_get(listener, "dscp");
+ if (!cfg_obj_isuint32(dscpobj))
+ dscp = ns_g_dscp;
+ else {
+ if (cfg_obj_asuint32(dscpobj) > 63) {
+ cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+ "dscp value '%u' is out of range",
+ cfg_obj_asuint32(dscpobj));
+ return (ISC_R_RANGE);
+ }
+ dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+ }
+
+ result = ns_listenelt_create(mctx, port, dscp, NULL, &delt);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"),
+ config, ns_g_lctx, actx, mctx, 0,
+ family, &delt->acl);
+ if (result != ISC_R_SUCCESS) {
+ ns_listenelt_destroy(delt);
+ return (result);
+ }
+ *target = delt;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_dumpstats(ns_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 = ns_stats_dump(server, fp);
+
+ cleanup:
+ if (fp != NULL)
+ (void)isc_stdio_close(fp);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpstats complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpstats failed: %s",
+ dns_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);
+ if (zle == NULL)
+ return (ISC_R_NOMEMORY);
+ 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);
+ if (vle == NULL)
+ return (ISC_R_NOMEMORY);
+ 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, true,
+ 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)
+ {
+ 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_dumptostreaminc(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",
+ dns_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",
+ dns_result_totext(result));
+ goto nextzone;
+ }
+ dns_db_currentversion(dctx->db, &dctx->version);
+ result = dns_master_dumptostreaminc(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",
+ dns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpdb complete");
+ cleanup:
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpdb failed: %s", dns_result_totext(result));
+ dumpcontext_destroy(dctx);
+}
+
+isc_result_t
+ns_server_dumpdb(ns_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;
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ dctx = isc_mem_get(server->mctx, sizeof(*dctx));
+ if (dctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dctx->mctx = server->mctx;
+ dctx->dumpcache = true;
+ dctx->dumpadb = true;
+ dctx->dumpbad = true;
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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, "-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) {
+ putstr(text, "view '");
+ putstr(text, ptr);
+ putstr(text, "' not found");
+ 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:
+ if (dctx != NULL)
+ dumpcontext_destroy(dctx);
+ return (result);
+}
+
+isc_result_t
+ns_server_dumpsecroots(ns_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];
+
+ /* 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"));
+
+ 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;
+ }
+ CHECK(putstr(text, "\n Start view "));
+ CHECK(putstr(text, view->name));
+ CHECK(putstr(text, "\n Secure roots:\n\n"));
+ 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;
+ }
+ CHECK(putstr(text, "\n Negative trust anchors:\n\n"));
+ CHECK(dns_ntatable_totext(ntatable, text));
+ }
+ if (ptr != NULL)
+ ptr = next_token(lex, text);
+ } while (ptr != NULL);
+
+ cleanup:
+ if (isc_buffer_usedlength(*text) > 0) {
+ if (fp != NULL)
+ (void)putstr(text, "\n");
+ else
+ (void)putnull(text);
+ }
+ if (secroots != NULL)
+ dns_keytable_detach(&secroots);
+ if (ntatable != NULL)
+ dns_ntatable_detach(&ntatable);
+ if (fp != NULL) {
+ fprintf(fp, "%.*s", (int) isc_buffer_usedlength(*text),
+ (char *) isc_buffer_base(*text));
+ isc_buffer_clear(*text);
+ (void)isc_stdio_close(fp);
+ }
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpsecroots complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpsecroots failed: %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+isc_result_t
+ns_server_dumprecursing(ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumprecursing complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumprecursing failed: %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+isc_result_t
+ns_server_setdebuglevel(ns_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 (ns_g_debuglevel < 99)
+ ns_g_debuglevel++;
+ } else {
+ newlevel = strtol(ptr, &endp, 10);
+ if (*endp != '\0' || newlevel < 0 || newlevel > 99)
+ return (ISC_R_RANGE);
+ ns_g_debuglevel = (unsigned int)newlevel;
+ }
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "debug level is now %u", ns_g_debuglevel);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_validation(ns_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;
+
+ /* 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)
+ continue;
+ CHECK(dns_view_flushcache(view));
+
+ if (set) {
+ 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, ")"));
+ CHECK(putnull(text));
+ first = false;
+ }
+ }
+
+ 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
+ns_server_flushcache(ns_server_t *server, isc_lex_t *lex) {
+ char *ptr;
+ dns_view_t *view;
+ bool flushed;
+ bool found;
+ isc_result_t result;
+ ns_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_flushcache2(nsc->primaryview, false);
+ if (result != ISC_R_SUCCESS) {
+ flushed = false;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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_flushcache2(view, true);
+ if (result != ISC_R_SUCCESS) {
+ flushed = false;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing cache in view '%s' succeeded",
+ ptr);
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing caches in all views succeeded");
+ result = ISC_R_SUCCESS;
+ } else {
+ if (!found) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_server_flushnode(ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing %s '%s' in cache view '%s' "
+ "succeeded",
+ tree ? "tree" : "name",
+ target, viewname);
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_server_status(ns_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];
+
+ if (ns_g_server->version_set) {
+ ob = " (";
+ cb = ")";
+ if (ns_g_server->version == NULL)
+ alt = "version.bind/txt/ch disabled";
+ else
+ alt = ns_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(&ns_g_boottime, boottime,
+ sizeof(boottime));
+ isc_time_formathttptimestamp(&ns_g_configtime, configtime,
+ sizeof(configtime));
+
+ snprintf(line, sizeof(line), "version: %s %s%s%s <id:%s>%s%s%s\n",
+ ns_g_product, ns_g_version,
+ (*ns_g_description != '\0') ? " " : "",
+ ns_g_description, ns_g_srcid, ob, alt, cb);
+ CHECK(putstr(text, line));
+
+ result = ns_os_gethostname(hostname, sizeof(hostname));
+ if (result != ISC_R_SUCCESS)
+ strlcpy(hostname, "localhost", sizeof(hostname));
+ snprintf(line, sizeof(line), "running on %s: %s\n",
+ hostname, ns_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 (ns_g_chrootdir != NULL) {
+ snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n",
+ ns_g_conffile, ns_g_chrootdir, ns_g_conffile);
+ } else {
+ snprintf(line, sizeof(line), "configuration file: %s\n",
+ ns_g_conffile);
+ }
+ CHECK(putstr(text, line));
+
+#ifdef ISC_PLATFORM_USETHREADS
+ snprintf(line, sizeof(line), "CPUs found: %u\n", ns_g_cpus_detected);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "worker threads: %u\n", ns_g_cpus);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "UDP listeners per interface: %u\n",
+ ns_g_udpdisp);
+ CHECK(putstr(text, line));
+#else
+ snprintf(line, sizeof(line), "CPUs found: N/A (threads disabled)\n");
+ CHECK(putstr(text, line));
+#endif
+
+ 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", ns_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",
+ server->log_queries ? "ON" : "OFF");
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "recursive clients: %d/%d/%d\n",
+ server->recursionquota.used, server->recursionquota.soft,
+ server->recursionquota.max);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "tcp clients: %d/%d\n",
+ server->tcpquota.used, server->tcpquota.max);
+ 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
+ns_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";
+
+ /* 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, ring->mctx);
+ 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
+ns_server_tsigdelete(ns_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];
+
+ (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, ring->mctx);
+ 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
+ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text) {
+ isc_result_t result;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+
+ 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)) {
+ 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) {
+ isc_task_endexclusive(server->task);
+ 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) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ 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
+ns_server_rekey(ns_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;
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ if (strcasecmp(ptr, NS_COMMAND_SIGN) == 0)
+ fullsign = true;
+
+ 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_master) {
+ dns_zone_detach(&zone);
+ return (DNS_R_NOTMASTER);
+ }
+
+ keyopts = dns_zone_getkeyopts(zone);
+
+ /* "rndc loadkeys" requires "auto-dnssec maintain". */
+ 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
+ns_server_sync(ns_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;
+
+ (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);
+ }
+
+ 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, false,
+ synczone, &cleanup);
+ if (result != ISC_R_SUCCESS &&
+ tresult == ISC_R_SUCCESS)
+ tresult = result;
+ }
+ isc_task_endexclusive(server->task);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_server_freeze(ns_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;
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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_master) {
+ dns_zone_detach(&mayberaw);
+ return (DNS_R_NOTMASTER);
+ }
+
+ 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;
+ }
+ }
+ }
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_smf_add_message(isc_buffer_t **text) {
+ 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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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("", "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) {
+ isc_buffer_t **text = arg;
+
+ putmem(text, buf, len);
+}
+
+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;
+
+ view = dns_zone_getview(zone);
+
+ nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf));
+
+ LOCK(&view->new_zone_lock);
+
+ 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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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;
+
+ result = isc_buffer_allocate(view->mctx, &text, 256);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "Unable to allocate buffer in "
+ "nzd_save(): %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+ if (zoptions == NULL) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "Unable to get options from config in "
+ "nzd_save()");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &text);
+
+ 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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "Error committing "
+ "NZD database: %s",
+ mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ }
+ }
+ *txnp = NULL;
+
+ UNLOCK(&view->new_zone_lock);
+
+ if (text != NULL) {
+ isc_buffer_free(&text);
+ }
+
+ return (result);
+}
+
+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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_WARNING, "mdb_dbi_open: %s",
+ mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ }
+
+ mdb_txn_abort(txn);
+ return (result);
+}
+
+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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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);
+}
+
+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);
+}
+
+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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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);
+}
+
+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;
+
+ /*
+ * 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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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(ns_g_addparser);
+ result = cfg_parse_file(ns_g_addparser, view->new_zone_file,
+ &cfg_type_addzoneconf, &nzf_config);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL, NS_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));
+
+ CHECK(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);
+ cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &text);
+
+ 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(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_addparser, &nzf_config);
+ }
+
+ return (result);
+}
+
+#endif /* HAVE_LMDB */
+
+static isc_result_t
+newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp,
+ cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp,
+ isc_buffer_t **text)
+{
+ isc_result_t result;
+ isc_buffer_t argbuf;
+ 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;
+
+ REQUIRE(viewp != NULL && *viewp == NULL);
+ REQUIRE(zoneobjp != NULL && *zoneobjp == NULL);
+ REQUIRE(zoneconfp != NULL && *zoneconfp == 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
+ INSIST(0);
+
+ /*
+ * Convert the "addzone" or "modzone" to just "zone", for
+ * the benefit of the parser
+ */
+ isc_buffer_forward(&argbuf, 3);
+
+ cfg_parser_reset(ns_g_addparser);
+ CHECK(cfg_parse_buffer3(ns_g_addparser, &argbuf, bn, 0,
+ &cfg_type_addzoneconf, &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), "redirect") == 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);
+ }
+
+ /* Make sense of optional class argument */
+ obj = cfg_tuple_get(zoneobj, "class");
+ CHECK(ns_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;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (zoneconf != NULL)
+ cfg_obj_destroy(ns_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(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
+ dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj,
+ 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;
+
+ UNUSED(zoneconf);
+#endif /* HAVE_LMDB */
+
+ /* Zone shouldn't already exist */
+ 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;
+
+#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 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 */
+ /* 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 */
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /* Mark view unfrozen and configure zone */
+ dns_view_thaw(view);
+ result = configure_zone(cfg->config, zoneobj, cfg->vconfig,
+ server->mctx, view, &server->viewlist,
+ 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? */
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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_loadnew(zone);
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ /* 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);
+#endif /* HAVE_LMDB */
+
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ return (result);
+}
+
+static isc_result_t
+do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
+ dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj,
+ 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;
+#endif /* HAVE_LMDB */
+
+ /* Zone must already exist */
+ 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
+
+ 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 */
+ /* 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,
+ 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? */
+ 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_loadnew(zone);
+
+ /*
+ * 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ 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);
+#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
+ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text) {
+ isc_result_t result;
+ bool addzone;
+ 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;
+
+ 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, text));
+
+ /* Are we accepting new zones in this view? */
+#ifdef HAVE_LMDB
+ if (view->new_zone_db == NULL)
+#else
+ 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 (addzone)
+ CHECK(do_addzone(server, cfg, view, dnsname, zoneconf,
+ zoneobj, text));
+ else
+ CHECK(do_modzone(server, cfg, view, dnsname, zonename,
+ zoneobj, text));
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s zone %s in view %s via %s",
+ addzone ? "added" : "updated",
+ zonename, view->name,
+ addzone ? NS_COMMAND_ADDZONE : NS_COMMAND_MODZONE);
+
+ /* Changing a zone counts as reconfiguration */
+ CHECK(isc_time_now(&ns_g_configtime));
+
+ cleanup:
+ if (isc_buffer_usedlength(*text) > 0)
+ (void) putnull(text);
+ if (zoneconf != NULL)
+ cfg_obj_destroy(ns_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 ns_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, *raw = NULL, *mayberaw;
+ char zonename[DNS_NAME_FORMATSIZE];
+ dns_view_t *view;
+ ns_cfgctx_t *cfg;
+ dns_db_t *dbp = NULL;
+ bool added;
+ isc_result_t result;
+#ifdef HAVE_LMDB
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+#endif
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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) */
+ added = dns_zone_getadded(zone);
+
+ if (added && cfg != NULL) {
+#ifdef HAVE_LMDB
+ /* Make sure we can open the NZD database */
+ result = nzd_open(view, 0, &txn, &dbi);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "unable to "
+ "delete zone configuration: %s",
+ isc_result_totext(result));
+ }
+#else
+ result = delete_zoneconf(view, cfg->add_parser,
+ cfg->nzf_config,
+ dns_zone_getorigin(zone),
+ nzf_writeconf);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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/slave 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_WARNING,
+ "file %s not removed: %s",
+ file, isc_result_totext(result));
+ }
+ }
+ }
+
+#ifdef HAVE_LMDB
+ if (txn != NULL)
+ (void) nzd_close(&txn, false);
+#endif
+ if (raw != NULL)
+ dns_zone_detach(&raw);
+ dns_zone_detach(&zone);
+ isc_mem_put(ns_g_mctx, dz, sizeof(*dz));
+ isc_task_detach(&task);
+}
+
+/*
+ * Act on a "delzone" command from the command channel.
+ */
+isc_result_t
+ns_server_delzone(ns_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;
+
+ /* 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);
+ CHECK(dns_zt_unmount(view->zonetable, zone));
+
+ /* Send cleanup event */
+ dz = isc_mem_get(ns_g_mctx, sizeof(*dz));
+ if (dz == NULL)
+ CHECK(ISC_R_NOMEMORY);
+
+ dz->cleanup = cleanup;
+ dz->zone = NULL;
+ dns_zone_attach(zone, &dz->zone);
+ dzevent = isc_event_allocate(ns_g_mctx, server, NS_EVENT_DELZONE,
+ rmzone, dz, sizeof(isc_event_t));
+ if (dzevent == NULL)
+ CHECK(ISC_R_NOMEMORY);
+
+ dns_zone_gettask(zone, &task);
+ isc_task_send(task, &dzevent);
+ dz = NULL;
+
+ /* Inform user about cleaning up stub/slave 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_slave ||
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "zone %s scheduled for removal via delzone", zonename);
+
+ /* Removing a zone counts as reconfiguration */
+ CHECK(isc_time_now(&ns_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);
+ if (dz != NULL) {
+ dns_zone_detach(&dz->zone);
+ isc_mem_put(ns_g_mctx, dz, sizeof(*dz));
+ }
+
+ 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)
+{
+ 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))
+ break;
+ } else if (strcasecmp(vname, name) == 0)
+ break;
+
+ obj = NULL;
+ }
+
+ return (obj);
+}
+
+static void
+emitzone(void *arg, const char *buf, int len) {
+ isc_buffer_t **tpp = arg;
+ putmem(tpp, buf, len);
+}
+
+/*
+ * Act on a "showzone" command from the command channel.
+ */
+isc_result_t
+ns_server_showzone(ns_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;
+ bool exclusive = false;
+#ifdef HAVE_LMDB
+ cfg_obj_t *nzconfig = NULL;
+#endif /* HAVE_LMDB */
+
+ /* Parse parameters */
+ CHECK(zone_from_args(server, lex, NULL, &zone, zonename,
+ text, true));
+ if (zone == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ 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;
+ }
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ exclusive = true;
+
+ /* Find the view statement */
+ vconfig = find_name_in_list_from_map(cfg->config, "view", view->name);
+
+ /* 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);
+
+#ifndef HAVE_LMDB
+ if (zconfig == NULL && cfg->nzf_config != NULL)
+ zconfig = find_name_in_list_from_map(cfg->nzf_config,
+ "zone", zonename);
+#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);
+
+ putstr(text, "zone ");
+ cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, text);
+ putstr(text, ";");
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+#ifdef HAVE_LMDB
+ if (nzconfig != NULL)
+ cfg_obj_destroy(ns_g_addparser, &nzconfig);
+#endif /* HAVE_LMDB */
+ if (isc_buffer_usedlength(*text) > 0)
+ (void) putnull(text);
+ if (exclusive)
+ isc_task_endexclusive(server->task);
+
+ 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;
+}
+
+static isc_result_t
+generate_salt(unsigned char *salt, size_t saltlen) {
+ int i, n;
+ union {
+ unsigned char rnd[256];
+ uint32_t rnd32[64];
+ } rnd;
+ unsigned char text[512 + 1];
+ isc_region_t r;
+ isc_buffer_t buf;
+ isc_result_t result;
+
+ if (saltlen > 256U)
+ return (ISC_R_RANGE);
+
+ n = (int) (saltlen + sizeof(uint32_t) - 1) / sizeof(uint32_t);
+ for (i = 0; i < n; i++)
+ isc_random_get(&rnd.rnd32[i]);
+
+ memmove(salt, rnd.rnd, saltlen);
+
+ r.base = rnd.rnd;
+ r.length = (unsigned int) saltlen;
+
+ isc_buffer_init(&buf, text, sizeof(text));
+ result = isc_hex_totext(&r, 2, "", &buf);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ text[saltlen * 2] = 0;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "generated salt: %s", text);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_signing(ns_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;
+ 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;
+
+ 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)
+ 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;
+ CHECK(generate_salt(salt, saltlen));
+ } 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 (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));
+ (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;
+ char output[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 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 inline 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 inline isc_result_t
+putnull(isc_buffer_t **b) {
+ return (putuint8(b, 0));
+}
+
+isc_result_t
+ns_server_zonestatus(ns_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;
+
+ 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);
+ }
+
+ switch (zonetype) {
+ case dns_zone_master:
+ type = "master";
+ break;
+ case dns_zone_slave:
+ type = "slave";
+ break;
+ case dns_zone_stub:
+ type = "stub";
+ break;
+ case dns_zone_staticstub:
+ type = "staticstub";
+ break;
+ case dns_zone_redirect:
+ type = "redirect";
+ break;
+ case dns_zone_key:
+ type = "key";
+ break;
+ case dns_zone_dlz:
+ type = "dlz";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ /* Serial number */
+ serial = dns_zone_getserial(mayberaw);
+ snprintf(serbuf, sizeof(serbuf), "%u", serial);
+ if (hasraw) {
+ signed_serial = dns_zone_getserial(zone);
+ snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial);
+ }
+
+ /* Database node count */
+ nodes = dns_db_nodecount(hasraw ? rawdb : db);
+ snprintf(nodebuf, sizeof(nodebuf), "%u", nodes);
+
+ /* Security */
+ secure = dns_db_issecure(db);
+ allow = (dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW);
+ maintain = (dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN);
+
+ /* 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_slave ||
+ 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_master ||
+ (zonetype == dns_zone_slave && hasraw))
+ {
+ dns_zone_getrefreshkeytime(zone, &refreshkeytime);
+ isc_time_formathttptimestamp(&refreshkeytime, kbuf,
+ sizeof(kbuf));
+ }
+
+ /* Dynamic? */
+ if (zonetype == dns_zone_master) {
+ dynamic = dns_zone_isdynamic(mayberaw, true);
+ frozen = dynamic && !dns_zone_isdynamic(mayberaw, false);
+ }
+
+ /* Next resign event */
+ if (secure && (zonetype == dns_zone_master ||
+ (zonetype == dns_zone_slave && 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);
+}
+
+static inline 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
+ns_server_nta(ns_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];
+ 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;
+ dns_name_t *ntaname;
+ dns_ttl_t ntattl;
+ bool ttlset = false, excl = false;
+ dns_rdataclass_t rdclass = dns_rdataclass_in;
+
+ UNUSED(force);
+
+ ntaname = 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 (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 {
+ 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, text));
+ }
+ CHECK(putnull(text));
+
+ goto cleanup;
+ }
+
+ if (readonly) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_INFO,
+ "rejecting restricted control channel "
+ "NTA command");
+ CHECK(ISC_R_FAILURE);
+ }
+
+ /* Get the NTA name. */
+ 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(ntaname, &b, dns_rootname, 0, NULL));
+ }
+
+ /* Look for the view name. */
+ viewname = next_token(lex, text);
+
+ 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))
+ {
+ static bool first = true;
+
+ if (viewname != NULL && strcmp(view->name, viewname) != 0) {
+ continue;
+ }
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "added NTA '%s' (%d sec) in view '%s'",
+ namebuf, ntattl, view->name);
+ } else {
+ CHECK(dns_ntatable_delete(ntatable, ntaname));
+
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ first = false;
+
+ CHECK(putstr(text, "Negative trust anchor removed: "));
+ CHECK(putstr(text, namebuf));
+ CHECK(putstr(text, "/"));
+ CHECK(putstr(text, view->name));
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "error writing NTA file "
+ "for view '%s': %s",
+ view->name, isc_result_totext(result));
+ }
+ }
+
+ CHECK(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
+ns_server_saventa(ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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
+ns_server_loadnta(ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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_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, kd.algorithm);
+
+ 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);
+ 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
+ns_server_mkeys(ns_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 } opt = NONE;
+ bool found = false;
+ bool first = true;
+
+ /* 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 {
+ 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) {
+ /* Look for the optional view name. */
+ viewtxt = next_token(lex, text);
+ }
+
+ if (classtxt == NULL) {
+ rdclass = dns_rdataclass_in;
+ } else {
+ isc_textregion_t r;
+ r.base = classtxt;
+ r.length = strlen(classtxt);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ if (viewtxt == NULL) {
+ rdclass = dns_rdataclass_in;
+ viewtxt = classtxt;
+ result = ISC_R_SUCCESS;
+ } else {
+ snprintf(msg, sizeof(msg),
+ "unknown class '%s'", classtxt);
+ (void) putstr(text, msg);
+ goto cleanup;
+ }
+ }
+ }
+
+ 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:
+ CHECK(mkey_refresh(view, text));
+ break;
+ case STATUS:
+ if (!first)
+ CHECK(putstr(text, "\n\n"));
+ CHECK(mkey_status(view, text));
+ first = false;
+ break;
+ case SYNC:
+ CHECK(dns_zone_flush(view->managed_keys));
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (viewtxt != NULL)
+ break;
+ }
+
+ 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
+ns_server_dnstap(ns_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;
+
+ 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 = -1;
+ } 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
+ return (DNS_R_SYNTAX);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_dt_reopen(server->dtenv, backups);
+ isc_task_endexclusive(server->task);
+ return (result);
+#else
+ UNUSED(server);
+ UNUSED(lex);
+ UNUSED(text);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
diff --git a/bin/named/sortlist.c b/bin/named/sortlist.c
new file mode 100644
index 0000000..20a131c
--- /dev/null
+++ b/bin/named/sortlist.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/result.h>
+
+#include <named/globals.h>
+#include <named/server.h>
+#include <named/sortlist.h>
+
+ns_sortlisttype_t
+ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
+ const void **argp)
+{
+ unsigned int i;
+
+ if (acl == NULL)
+ goto dont_sort;
+
+ for (i = 0; i < acl->length; i++) {
+ /*
+ * 'e' refers to the current 'top level statement'
+ * in the sortlist (see ARM).
+ */
+ dns_aclelement_t *e = &acl->elements[i];
+ dns_aclelement_t *try_elt;
+ dns_aclelement_t *order_elt = NULL;
+ const dns_aclelement_t *matched_elt = NULL;
+
+ if (e->type == dns_aclelementtype_nestedacl) {
+ dns_acl_t *inner = e->nestedacl;
+
+ if (inner->length == 0)
+ try_elt = e;
+ else if (inner->length > 2)
+ goto dont_sort;
+ else if (inner->elements[0].negative)
+ goto dont_sort;
+ else {
+ try_elt = &inner->elements[0];
+ if (inner->length == 2)
+ order_elt = &inner->elements[1];
+ }
+ } else {
+ /*
+ * BIND 8 allows bare elements at the top level
+ * as an undocumented feature.
+ */
+ try_elt = e;
+ }
+
+ if (dns_aclelement_match(clientaddr, NULL, try_elt,
+ &ns_g_server->aclenv,
+ &matched_elt)) {
+ if (order_elt != NULL) {
+ if (order_elt->type ==
+ dns_aclelementtype_nestedacl) {
+ *argp = order_elt->nestedacl;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ } else if (order_elt->type ==
+ dns_aclelementtype_localhost &&
+ ns_g_server->aclenv.localhost != NULL) {
+ *argp = ns_g_server->aclenv.localhost;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ } else if (order_elt->type ==
+ dns_aclelementtype_localnets &&
+ ns_g_server->aclenv.localnets != NULL) {
+ *argp = ns_g_server->aclenv.localnets;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ } else {
+ /*
+ * BIND 8 allows a bare IP prefix as
+ * the 2nd element of a 2-element
+ * sortlist statement.
+ */
+ *argp = order_elt;
+ return (NS_SORTLISTTYPE_1ELEMENT);
+ }
+ } else {
+ INSIST(matched_elt != NULL);
+ *argp = matched_elt;
+ return (NS_SORTLISTTYPE_1ELEMENT);
+ }
+ }
+ }
+
+ /* No match; don't sort. */
+ dont_sort:
+ *argp = NULL;
+ return (NS_SORTLISTTYPE_NONE);
+}
+
+int
+ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg) {
+ const dns_acl_t *sortacl = (const dns_acl_t *) arg;
+ int match;
+
+ (void)dns_acl_match(addr, NULL, sortacl,
+ &ns_g_server->aclenv,
+ &match, NULL);
+ if (match > 0)
+ return (match);
+ else if (match < 0)
+ return (INT_MAX - (-match));
+ else
+ return (INT_MAX / 2);
+}
+
+int
+ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) {
+ const dns_aclelement_t *matchelt = (const dns_aclelement_t *) arg;
+ if (dns_aclelement_match(addr, NULL, matchelt,
+ &ns_g_server->aclenv,
+ NULL)) {
+ return (0);
+ } else {
+ return (INT_MAX);
+ }
+}
+
+void
+ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr,
+ dns_addressorderfunc_t *orderp,
+ const void **argp)
+{
+ ns_sortlisttype_t sortlisttype;
+
+ sortlisttype = ns_sortlist_setup(sortlist_acl, client_addr, argp);
+
+ switch (sortlisttype) {
+ case NS_SORTLISTTYPE_1ELEMENT:
+ *orderp = ns_sortlist_addrorder1;
+ break;
+ case NS_SORTLISTTYPE_2ELEMENT:
+ *orderp = ns_sortlist_addrorder2;
+ break;
+ case NS_SORTLISTTYPE_NONE:
+ *orderp = NULL;
+ break;
+ default:
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "unexpected return from ns_sortlist_setup(): "
+ "%d", sortlisttype);
+ break;
+ }
+}
+
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
new file mode 100644
index 0000000..b1559f8
--- /dev/null
+++ b/bin/named/statschannel.c
@@ -0,0 +1,3583 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/buffer.h>
+#include <isc/httpd.h>
+#include <isc/json.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/socket.h>
+#include <isc/stats.h>
+#include <isc/string.h>
+#include <isc/task.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 <named/log.h>
+#include <named/server.h>
+#include <named/statschannel.h>
+
+#include "bind9.xsl.h"
+
+struct ns_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 ns_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)
+#define EXTENDED_STATS
+#else
+#undef EXTENDED_STATS
+#endif
+
+#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_master, "master" },
+ { dns_zone_slave, "slave" },
+ { 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_getoptions2(zone) & DNS_ZONEOPT2_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
+
+/*%
+ * 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[dns_nsstatscounter_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];
+#if defined(EXTENDED_STATS)
+static const char *nsstats_xmldesc[dns_nsstatscounter_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];
+#else
+#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
+#endif /* EXTENDED_STATS */
+
+#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } 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[dns_nsstatscounter_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 inline 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
+
+ fdescs[counter] = fdesc;
+#if defined(EXTENDED_STATS)
+ xdescs[counter] = xdesc;
+#else
+ UNUSED(xdesc);
+ UNUSED(xdescs);
+#endif
+}
+
+static void
+init_desc(void) {
+ int i;
+
+ /* Initialize name server statistics */
+ for (i = 0; i < dns_nsstatscounter_max; i++)
+ nsstats_desc[i] = NULL;
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_nsstatscounter_max; i++)
+ nsstats_xmldesc[i] = NULL;
+#endif
+
+#define SET_NSSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_nsstatscounter_ ## counterid, \
+ dns_nsstatscounter_max, \
+ desc, nsstats_desc, xmldesc, nsstats_xmldesc); \
+ nsstats_index[i++] = dns_nsstatscounter_ ## 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(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(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(keytagopt, "Keytag option received", "KeyTagOpt");
+ INSIST(i == dns_nsstatscounter_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
+
+#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(nextitem, "waited for next item", "NextItem");
+
+ 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
+
+#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
+
+#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
+
+#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
+
+#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
+
+#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 messges written", "DNSTAPsuccess");
+ SET_DNSTAPSTATDESC(drop, "dnstap messages dropped", "DNSTAPdropped");
+ INSIST(i == dns_dnstapcounter_max);
+
+ /* Sanity check */
+ for (i = 0; i < dns_nsstatscounter_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);
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_nsstatscounter_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);
+#endif
+
+ /* 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
+ }
+ 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
+ }
+
+#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 < dns_nsstatscounter_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 < dns_nsstatscounter_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
+}
+
+/*%
+ * 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
+ xmlTextWriterPtr writer;
+ int xmlrc;
+#endif
+#ifdef HAVE_JSON
+ json_object *job, *cat, *counter;
+#endif
+
+#if !defined(EXTENDED_STATS)
+ UNUSED(category);
+#endif
+
+ 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
+ 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
+
+ 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 = (xmlTextWriterPtr) 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
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON
+ counter = json_object_new_int64(value);
+ if (counter == NULL)
+ return (ISC_R_NOMEMORY);
+ json_object_object_add(cat, desc[idx], counter);
+#endif
+ break;
+ }
+ }
+ return (ISC_R_SUCCESS);
+#ifdef HAVE_LIBXML2
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "failed at dump_counters()");
+ return (ISC_R_FAILURE);
+#endif
+}
+
+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
+ xmlTextWriterPtr writer;
+ int xmlrc;
+#endif
+#ifdef HAVE_JSON
+ json_object *zoneobj, *obj;
+#endif
+
+ 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
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON
+ zoneobj = (json_object *) dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL)
+ return;
+ json_object_object_add(zoneobj, typestr, obj);
+#endif
+ break;
+ }
+ return;
+#ifdef HAVE_LIBXML2
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "failed at rdtypestat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif
+}
+
+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;
+#ifdef HAVE_LIBXML2
+ xmlTextWriterPtr writer;
+ int xmlrc;
+#endif
+#ifdef HAVE_JSON
+ json_object *zoneobj, *obj;
+ char buf[1024];
+#endif
+
+ 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;
+ }
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXRRSET)
+ != 0)
+ nxrrset = true;
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_STALE)
+ != 0)
+ stale = true;
+
+ switch (dumparg->type) {
+ case isc_statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" PRIu64 " %s%s%s\n", val,
+ 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",
+ 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
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON
+ zoneobj = (json_object *) dumparg->arg;
+ snprintf(buf, sizeof(buf), "%s%s%s",
+ stale ? "#" : "", nxrrset ? "!" : "", typestr);
+ obj = json_object_new_int64(val);
+ if (obj == NULL)
+ return;
+ json_object_object_add(zoneobj, buf, obj);
+#endif
+ break;
+ }
+ return;
+#ifdef HAVE_LIBXML2
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "failed at rdatasetstats_dump()");
+ dumparg->result = ISC_R_FAILURE;
+#endif
+
+}
+
+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
+ xmlTextWriterPtr writer;
+ int xmlrc;
+#endif
+#ifdef HAVE_JSON
+ json_object *zoneobj, *obj;
+#endif
+
+ 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
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON
+ zoneobj = (json_object *) dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL)
+ return;
+ json_object_object_add(zoneobj, codebuf, obj);
+#endif
+ break;
+ }
+ return;
+
+#ifdef HAVE_LIBXML2
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "failed at opcodestat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif
+}
+
+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
+ xmlTextWriterPtr writer;
+ int xmlrc;
+#endif
+#ifdef HAVE_JSON
+ json_object *zoneobj, *obj;
+#endif
+
+ 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
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON
+ zoneobj = (json_object *) dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL)
+ return;
+ json_object_object_add(zoneobj, codebuf, obj);
+#endif
+ break;
+ }
+ return;
+
+#ifdef HAVE_LIBXML2
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "failed at rcodestat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif
+}
+
+#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;
+ isc_stats_t *zonestats;
+ dns_stats_t *rcvquerystats;
+ dns_zonestat_level_t statlevel;
+ uint64_t nsstat_values[dns_nsstatscounter_max];
+ int xmlrc;
+ stats_dumparg_t dumparg;
+ const char *ztype;
+
+ 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_getserial2(zone, &serial) == ISC_R_SUCCESS)
+ TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial));
+ else
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
+ TRY0(xmlTextWriterEndElement(writer)); /* serial */
+
+ zonestats = dns_zone_getrequeststats(zone);
+ rcvquerystats = dns_zone_getrcvquerystats(zone);
+ if (statlevel == dns_zonestat_full && zonestats != NULL) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "rcode"));
+
+ result = dump_counters(zonestats, isc_statsformat_xml, writer,
+ NULL, nsstats_xmldesc,
+ dns_nsstatscounter_max, nsstats_index,
+ nsstat_values, ISC_STATSDUMP_VERBOSE);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ /* counters type="rcode"*/
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+
+ if (statlevel == dns_zonestat_full && 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);
+ if(dumparg.result != ISC_R_SUCCESS)
+ goto error;
+
+ /* counters type="qtype"*/
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+
+ TRY0(xmlTextWriterEndElement(writer)); /* zone */
+
+ return (ISC_R_SUCCESS);
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR, "Failed at zone_xmlrender()");
+ return (ISC_R_FAILURE);
+}
+
+static isc_result_t
+generatexml(ns_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[dns_nsstatscounter_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
+ isc_result_t result;
+
+ isc_time_now(&now);
+ isc_time_formatISO8601ms(&ns_g_boottime, boottime, sizeof boottime);
+ isc_time_formatISO8601ms(&ns_g_configtime, configtime, sizeof configtime);
+ isc_time_formatISO8601ms(&now, nowstr, sizeof nowstr);
+
+ writer = xmlNewTextWriterDoc(&doc, 0);
+ if (writer == NULL)
+ goto error;
+ 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 "3.8"));
+
+ /* 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 ns_g_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->opcodestats, opcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ if (dumparg.result != ISC_R_SUCCESS)
+ goto error;
+
+ TRY0(xmlTextWriterEndElement(writer));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "rcode"));
+
+ dns_rcodestats_dump(server->rcodestats, rcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ if (dumparg.result != ISC_R_SUCCESS)
+ goto error;
+
+ 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->rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS)
+ goto error;
+ TRY0(xmlTextWriterEndElement(writer)); /* counters */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "nsstat"));
+
+ result = dump_counters(server->nsstats, isc_statsformat_xml,
+ writer, NULL, nsstats_xmldesc,
+ dns_nsstatscounter_max,
+ nsstats_index, nsstat_values,
+ ISC_STATSDUMP_VERBOSE);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "zonestat"));
+
+ result = dump_counters(server->zonestats, isc_statsformat_xml,
+ writer, NULL, zonestats_xmldesc,
+ dns_zonestatscounter_max,
+ zonestats_index, zonestat_values,
+ ISC_STATSDUMP_VERBOSE);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ 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"));
+ result = dump_counters(server->resolverstats,
+ isc_statsformat_xml, writer,
+ NULL, resstats_xmldesc,
+ dns_resstatscounter_max,
+ resstats_index, resstat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ 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(ns_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);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ TRY0(xmlTextWriterEndElement(writer)); /* dnstap */
+ }
+#endif
+ }
+
+ if ((flags & STATS_XML_NET) != 0) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "sockstat"));
+
+ result = dump_counters(server->sockstats, isc_statsformat_xml,
+ writer, NULL, sockstats_xmldesc,
+ isc_sockstatscounter_max,
+ sockstats_index, sockstat_values,
+ ISC_STATSDUMP_VERBOSE);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ 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"));
+
+ result = dump_counters(server->udpinstats4,
+ isc_statsformat_xml, writer,
+ NULL, udpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ udpinsizestats_index,
+ udpinsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ result = dump_counters(server->udpoutstats4,
+ isc_statsformat_xml, writer,
+ NULL, udpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ udpoutsizestats_index,
+ udpoutsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ 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"));
+
+ result = dump_counters(server->tcpinstats4,
+ isc_statsformat_xml, writer,
+ NULL, tcpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ tcpinsizestats_index,
+ tcpinsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ result = dump_counters(server->tcpoutstats4,
+ isc_statsformat_xml, writer,
+ NULL, tcpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ tcpoutsizestats_index,
+ tcpoutsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ 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"));
+
+ result = dump_counters(server->udpinstats6,
+ isc_statsformat_xml, writer,
+ NULL, udpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ udpinsizestats_index,
+ udpinsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ result = dump_counters(server->udpoutstats6,
+ isc_statsformat_xml, writer,
+ NULL, udpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ udpoutsizestats_index,
+ udpoutsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ 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"));
+
+ result = dump_counters(server->tcpinstats6,
+ isc_statsformat_xml, writer,
+ NULL, tcpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ tcpinsizestats_index,
+ tcpinsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ result = dump_counters(server->tcpoutstats6,
+ isc_statsformat_xml, writer,
+ NULL, tcpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ tcpoutsizestats_index,
+ tcpoutsizestat_values, 0);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ 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"));
+ result = dns_zt_apply(view->zonetable, true,
+ zone_xmlrender, writer);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ 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);
+ if (dumparg.result != ISC_R_SUCCESS)
+ goto error;
+ }
+ TRY0(xmlTextWriterEndElement(writer));
+
+ /* <resstats> */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "resstats"));
+ if (view->resstats != NULL) {
+ result = dump_counters(view->resstats,
+ isc_statsformat_xml, writer,
+ NULL, resstats_xmldesc,
+ dns_resstatscounter_max,
+ resstats_index, resstat_values,
+ ISC_STATSDUMP_VERBOSE);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ }
+ 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);
+ if (dumparg.result != ISC_R_SUCCESS)
+ goto error;
+ TRY0(xmlTextWriterEndElement(writer)); /* cache */
+ }
+
+ /* <adbstats> */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "adbstat"));
+ if (view->adbstats != NULL) {
+ result = dump_counters(view->adbstats,
+ isc_statsformat_xml, writer,
+ NULL, adbstats_xmldesc,
+ dns_adbstats_max,
+ adbstats_index, adbstat_values,
+ ISC_STATSDUMP_VERBOSE);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ }
+ 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_NET) != 0) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "socketmgr"));
+ TRY0(isc_socketmgr_renderxml(ns_g_socketmgr, writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* /socketmgr */
+ }
+
+ if ((flags & STATS_XML_TASKS) != 0) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
+ TRY0(isc_taskmgr_renderxml(ns_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));
+
+ xmlFreeTextWriter(writer);
+
+ xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0);
+ if (*buf == NULL)
+ goto error;
+ xmlFreeDoc(doc);
+ return (ISC_R_SUCCESS);
+
+ error:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_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, const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, 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;
+ ns_server_t *server = arg;
+ isc_result_t result;
+
+ UNUSED(url);
+ UNUSED(urlinfo);
+ UNUSED(headers);
+ UNUSED(querystring);
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rendering XML()");
+
+ return (result);
+}
+
+static isc_result_t
+render_xml_all(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_ALL, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_status(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_STATUS, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_server(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_SERVER, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_zones(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_ZONES, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_net(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_NET, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_tasks(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_TASKS, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_mem(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_MEM, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_traffic(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_xml(STATS_XML_TRAFFIC, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+#endif /* HAVE_LIBXML2 */
+
+#ifdef HAVE_JSON
+/*
+ * 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 CHECK(m) do { \
+ result = (m); \
+ if (result != ISC_R_SUCCESS) \
+ goto error; \
+} while (0)
+
+#define CHECKMEM(m) do { \
+ if (m == NULL) { \
+ result = ISC_R_NOMEMORY;\
+ goto error;\
+ } \
+} 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;
+ uint64_t nsstat_values[dns_nsstatscounter_max];
+ isc_stats_t *zonestats;
+ dns_stats_t *rcvquerystats;
+ json_object *zonearray = (json_object *) arg;
+ json_object *zoneobj = NULL;
+ dns_zonestat_level_t statlevel;
+
+ 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_getserial2(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);
+
+ zonestats = dns_zone_getrequeststats(zone);
+ rcvquerystats = dns_zone_getrcvquerystats(zone);
+ if (statlevel == dns_zonestat_full && zonestats != NULL) {
+ json_object *counters = json_object_new_object();
+ if (counters == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error;
+ }
+
+ result = dump_counters(zonestats, isc_statsformat_json,
+ counters, NULL, nsstats_xmldesc,
+ dns_nsstatscounter_max, nsstats_index,
+ nsstat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto error;
+ }
+
+ if (json_object_get_object(counters)->count != 0)
+ json_object_object_add(zoneobj, "rcodes", counters);
+ else
+ json_object_put(counters);
+ }
+
+ if (statlevel == dns_zonestat_full && 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 error;
+ }
+
+ if (json_object_get_object(counters)->count != 0)
+ json_object_object_add(zoneobj, "qtypes", counters);
+ else
+ json_object_put(counters);
+ }
+
+ json_object_array_add(zonearray, zoneobj);
+ zoneobj = NULL;
+ result = ISC_R_SUCCESS;
+
+ error:
+ if (zoneobj != NULL)
+ json_object_put(zoneobj);
+ return (result);
+}
+
+static isc_result_t
+generatejson(ns_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[dns_nsstatscounter_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
+ 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("1.2");
+ CHECKMEM(obj);
+ json_object_object_add(bindstats, "json-stats-version", obj);
+
+ isc_time_now(&now);
+ isc_time_formatISO8601ms(&ns_g_boottime,
+ boottime, sizeof(boottime));
+ isc_time_formatISO8601ms(&ns_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(ns_g_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->opcodestats,
+ opcodestat_dump, &dumparg,
+ ISC_STATSDUMP_VERBOSE);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto error;
+ }
+
+ 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->rcodestats, rcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto error;
+ }
+
+ 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->rcvquerystats,
+ rdtypestat_dump, &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto error;
+ }
+
+ 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(server->nsstats, isc_statsformat_json,
+ counters, NULL, nsstats_xmldesc,
+ dns_nsstatscounter_max,
+ nsstats_index, nsstat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto error;
+ }
+
+ 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 error;
+ }
+
+ 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 error;
+ }
+
+ 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 (ns_g_server->dtenv != NULL) {
+ isc_stats_t *dnstapstats = NULL;
+ dns_dt_getstats(ns_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 error;
+ }
+
+ if (json_object_get_object(counters)->count != 0)
+ json_object_object_add(bindstats,
+ "dnstapstats",
+ counters);
+ else
+ json_object_put(counters);
+ }
+#endif
+ }
+
+ 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) {
+ result = dns_zt_apply(view->zonetable, true,
+ zone_jsonrender, za);
+ if (result != ISC_R_SUCCESS) {
+ goto error;
+ }
+ }
+
+ 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 error;
+ }
+
+ 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 error;
+ }
+
+ 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 error;
+ }
+
+ 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 error;
+ }
+
+ 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 error;
+ }
+
+ json_object_object_add(res, "adb",
+ counters);
+ }
+ }
+
+ view = ISC_LIST_NEXT(view, link);
+ }
+ }
+
+ if ((flags & STATS_JSON_NET) != 0) {
+ /* socket stat counters */
+ json_object *sockets;
+ 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 error;
+ }
+
+ if (json_object_get_object(counters)->count != 0)
+ json_object_object_add(bindstats, "sockstats",
+ counters);
+ else
+ json_object_put(counters);
+
+ sockets = json_object_new_object();
+ CHECKMEM(sockets);
+
+ result = isc_socketmgr_renderjson(ns_g_socketmgr, sockets);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(sockets);
+ goto error;
+ }
+
+ json_object_object_add(bindstats, "socketmgr", sockets);
+ }
+
+ if ((flags & STATS_JSON_TASKS) != 0) {
+ json_object *tasks = json_object_new_object();
+ CHECKMEM(tasks);
+
+ result = isc_taskmgr_renderjson(ns_g_taskmgr, tasks);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(tasks);
+ goto error;
+ }
+
+ 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 error;
+ }
+
+ 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->udpinstats4,
+ isc_statsformat_json, udpreq4, NULL,
+ udpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ udpinsizestats_index,
+ udpinsizestat_values, 0));
+
+ CHECK(dump_counters(server->udpoutstats4,
+ isc_statsformat_json, udpresp4, NULL,
+ udpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ udpoutsizestats_index,
+ udpoutsizestat_values, 0));
+
+ CHECK(dump_counters(server->tcpinstats4,
+ isc_statsformat_json, tcpreq4, NULL,
+ tcpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ tcpinsizestats_index,
+ tcpinsizestat_values, 0));
+
+ CHECK(dump_counters(server->tcpoutstats4,
+ isc_statsformat_json, tcpresp4, NULL,
+ tcpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ tcpoutsizestats_index,
+ tcpoutsizestat_values, 0));
+
+ CHECK(dump_counters(server->udpinstats6,
+ isc_statsformat_json, udpreq6, NULL,
+ udpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ udpinsizestats_index,
+ udpinsizestat_values, 0));
+
+ CHECK(dump_counters(server->udpoutstats6,
+ isc_statsformat_json, udpresp6, NULL,
+ udpoutsizestats_xmldesc,
+ dns_sizecounter_out_max,
+ udpoutsizestats_index,
+ udpoutsizestat_values, 0));
+
+ CHECK(dump_counters(server->tcpinstats6,
+ isc_statsformat_json, tcpreq6, NULL,
+ tcpinsizestats_xmldesc,
+ dns_sizecounter_in_max,
+ tcpinsizestats_index,
+ tcpinsizestat_values, 0));
+
+ CHECK(dump_counters(server->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;
+
+ error:
+ 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,
+ const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers,
+ 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;
+ ns_server_t *server = arg;
+ const char *msg = NULL;
+ size_t msglen = 0;
+ char *p;
+
+ UNUSED(url);
+ UNUSED(urlinfo);
+ UNUSED(headers);
+ UNUSED(querystring);
+
+ 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rendering JSON()");
+
+ return (result);
+}
+
+static isc_result_t
+render_json_all(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_ALL, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_status(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_STATUS, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_server(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_SERVER, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_zones(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_ZONES, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_mem(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_MEM, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_tasks(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_TASKS, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_net(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_NET, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_traffic(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ return (render_json(STATS_JSON_TRAFFIC, url, urlinfo,
+ querystring, headers, arg,
+ retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+#endif /* HAVE_JSON */
+
+static isc_result_t
+render_xsl(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers,
+ 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;
+
+ UNUSED(url);
+ UNUSED(querystring);
+ UNUSED(args);
+
+ *freecb = NULL;
+ *freecb_args = NULL;
+ *mimetype = "text/xslt+xml";
+
+ if (urlinfo->isstatic) {
+ isc_time_t when;
+ char *p = strcasestr(headers, "If-Modified-Since: ");
+
+ if (p != NULL) {
+ time_t t1, t2;
+ p += strlen("If-Modified-Since: ");
+ result = isc_time_parsehttptimestamp(p, &when);
+ if (result != ISC_R_SUCCESS)
+ goto send;
+
+ result = isc_time_secondsastimet(&when, &t1);
+ if (result != ISC_R_SUCCESS)
+ goto send;
+
+ result = isc_time_secondsastimet(&urlinfo->loadtime,
+ &t2);
+ if (result != ISC_R_SUCCESS)
+ goto send;
+
+ if (t1 < t2)
+ goto send;
+
+ *retcode = 304;
+ *retmsg = "Not modified";
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ send:
+ *retcode = 200;
+ *retmsg = "OK";
+ isc_buffer_reinit(b, xslmsg, strlen(xslmsg));
+ isc_buffer_add(b, strlen(xslmsg));
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+shutdown_listener(ns_statschannel_t *listener) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&listener->address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_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) {
+ ns_statschannel_t *listener = arg;
+ 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, &ns_g_server->aclenv,
+ &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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "rejected statistics connection from %s", socktext);
+
+ return (false);
+}
+
+static void
+destroy_listener(void *arg) {
+ ns_statschannel_t *listener = 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);
+
+ DESTROYLOCK(&listener->lock);
+ isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
+}
+
+static isc_result_t
+add_listener(ns_server_t *server, ns_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;
+ ns_statschannel_t *listener;
+ isc_task_t *task = NULL;
+ isc_socket_t *sock = NULL;
+ const cfg_obj_t *allow;
+ dns_acl_t *new_acl = NULL;
+
+ listener = isc_mem_get(server->mctx, sizeof(*listener));
+ if (listener == NULL)
+ return (ISC_R_NOMEMORY);
+
+ listener->httpdmgr = NULL;
+ listener->address = *addr;
+ listener->acl = NULL;
+ listener->mctx = NULL;
+ ISC_LINK_INIT(listener, link);
+
+ result = isc_mutex_init(&listener->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(server->mctx, listener, sizeof(*listener));
+ return (ISC_R_FAILURE);
+ }
+
+ 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, ns_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else
+ result = dns_acl_any(listener->mctx, &new_acl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ result = isc_task_create(ns_g_taskmgr, 0, &task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_task_setname(task, "statchannel", NULL);
+
+ result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(addr),
+ isc_sockettype_tcp, &sock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_socket_setname(sock, "statchannel", NULL);
+
+#ifndef ISC_ALLOW_MAPPED
+ isc_socket_ipv6only(sock, true);
+#endif
+
+ result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_httpdmgr_create(server->mctx, sock, task, client_ok,
+ destroy_listener, listener, ns_g_timermgr,
+ &listener->httpdmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+#ifdef HAVE_LIBXML2
+ isc_httpdmgr_addurl(listener->httpdmgr, "/",
+ render_xml_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml",
+ render_xml_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3",
+ render_xml_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status",
+ render_xml_status, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server",
+ render_xml_server, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones",
+ render_xml_zones, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net",
+ render_xml_net, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks",
+ render_xml_tasks, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem",
+ render_xml_mem, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic",
+ render_xml_traffic, server);
+#endif
+#ifdef HAVE_JSON
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json",
+ render_json_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1",
+ render_json_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status",
+ render_json_status, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server",
+ render_json_server, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones",
+ render_json_zones, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks",
+ render_json_tasks, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net",
+ render_json_net, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem",
+ render_json_mem, server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic",
+ render_json_traffic, server);
+#endif
+ isc_httpdmgr_addurl2(listener->httpdmgr, "/bind9.xsl", true,
+ render_xsl, server);
+
+ *listenerp = listener;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "statistics channel listening on %s", socktext);
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ if (listener->acl != NULL)
+ dns_acl_detach(&listener->acl);
+ DESTROYLOCK(&listener->lock);
+ isc_mem_putanddetach(&listener->mctx, listener,
+ sizeof(*listener));
+ }
+ if (task != NULL)
+ isc_task_detach(&task);
+ if (sock != NULL)
+ isc_socket_detach(&sock);
+
+ return (result);
+}
+
+static void
+update_listener(ns_server_t *server, ns_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)
+{
+ ns_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, ns_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, ns_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
+ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx)
+{
+ ns_statschannel_t *listener, *listener_next;
+ ns_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "statistics-channels: XML library missing, "
+ "only JSON stats will be available");
+#endif /* !HAVE_LIBXML2 */
+#ifndef HAVE_JSON
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "statistics-channels: JSON library missing, "
+ "only XML stats will be available");
+#endif /* !HAVE_JSON */
+#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,
+ NS_STATSCHANNEL_HTTPPORT);
+
+ isc_sockaddr_format(&addr, socktext,
+ sizeof(socktext));
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_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,
+ ns_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
+ns_statschannels_shutdown(ns_server_t *server) {
+ ns_statschannel_t *listener;
+
+ while ((listener = ISC_LIST_HEAD(server->statschannels)) != NULL) {
+ ISC_LIST_UNLINK(server->statschannels, listener, link);
+ shutdown_listener(listener);
+ }
+}
+
+isc_result_t
+ns_stats_dump(ns_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[dns_nsstatscounter_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];
+
+ 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->opcodestats, opcodestat_dump, &dumparg, 0);
+
+ fprintf(fp, "++ Incoming Queries ++\n");
+ dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+
+ fprintf(fp, "++ Outgoing Rcodes ++\n");
+ dns_rcodestats_dump(server->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(server->nsstats, isc_statsformat_file, fp, NULL,
+ nsstats_desc, dns_nsstatscounter_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,
+ dns_nsstatscounter_max,
+ nsstats_index, nsstat_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..6cbf132
--- /dev/null
+++ b/bin/named/tkeyconf.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+
+#include <isc/buffer.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/mem.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+#include <dns/tkey.h>
+
+#include <dst/gssapi.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(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_SERVER, \
+ ISC_LOG_ERROR, \
+ "%s", msg)
+
+isc_result_t
+ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
+ isc_entropy_t *ectx, 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, ectx, &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));
+ if (tctx->domain == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ dns_name_init(tctx->domain, NULL);
+ RETERR(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);
+ if (tctx->gssapi_keytab == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ }
+
+ *tctxp = tctx;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ dns_tkeyctx_destroy(&tctx);
+ return (result);
+}
+
diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c
new file mode 100644
index 0000000..3426f92
--- /dev/null
+++ b/bin/named/tsigconf.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/tsig.h>
+#include <dns/result.h>
+
+#include <named/log.h>
+
+#include <named/config.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;
+ 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 (ns_config_getkeyalgorithm(algstr, &alg, &bits)
+ != ISC_R_SUCCESS) {
+ cfg_obj_log(algobj, ns_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);
+ if (secret == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ 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, ns_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
+ns_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/unix/Makefile.in b/bin/named/unix/Makefile.in
new file mode 100644
index 0000000..30075e6
--- /dev/null
+++ b/bin/named/unix/Makefile.in
@@ -0,0 +1,29 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \
+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} \
+ ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@
+CWARNINGS =
+
+OBJS = os.@O@ dlz_dlopen_driver.@O@
+
+SRCS = os.c dlz_dlopen_driver.c
+
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/bin/named/unix/dlz_dlopen_driver.c b/bin/named/unix/dlz_dlopen_driver.c
new file mode 100644
index 0000000..f4dc47c
--- /dev/null
+++ b/bin/named/unix/dlz_dlopen_driver.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/dlz_dlopen.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/dlz_dlopen_driver.h>
+
+#ifdef ISC_DLZ_DLOPEN
+static dns_sdlzimplementation_t *dlz_dlopen = NULL;
+
+
+typedef struct dlopen_data {
+ isc_mem_t *mctx;
+ char *dl_path;
+ char *dlzname;
+ void *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 == false) \
+ LOCK(&cd->lock); \
+ } while (0)
+
+#define MAYBE_UNLOCK(cd) \
+ do { \
+ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
+ cd->in_configure == false) \
+ 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 = dlsym(cd->dl_handle, symbol);
+ if (ptr == NULL && mandatory) {
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen: library '%s' is missing "
+ "required symbol '%s'", cd->dl_path, symbol);
+ }
+ return (ptr);
+}
+
+/*
+ * 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 dlopen_flags = 0;
+
+ 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);
+ }
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ cd = isc_mem_get(mctx, sizeof(*cd));
+ if (cd == NULL) {
+ isc_mem_destroy(&mctx);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(cd, 0, sizeof(*cd));
+
+ cd->mctx = mctx;
+
+ cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
+ if (cd->dl_path == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failed;
+ }
+
+ cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
+ if (cd->dlzname == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failed;
+ }
+
+ /* Initialize the lock */
+ result = isc_mutex_init(&cd->lock);
+ if (result != ISC_R_SUCCESS)
+ goto failed;
+
+ /* Open the library */
+ dlopen_flags = RTLD_NOW|RTLD_GLOBAL;
+
+#ifdef RTLD_DEEPBIND
+ /*
+ * If RTLD_DEEPBIND is available then use it. This can avoid
+ * issues with a module using a different version of a system
+ * library than one that bind9 uses. For example, bind9 may link
+ * to MIT kerberos, but the module may use Heimdal. If we don't
+ * use RTLD_DEEPBIND then we could end up with Heimdal functions
+ * calling MIT functions, which leads to bizarre results (usually
+ * a segfault).
+ */
+ dlopen_flags |= RTLD_DEEPBIND;
+#endif
+
+ cd->dl_handle = dlopen(cd->dl_path, dlopen_flags);
+ if (cd->dl_handle == NULL) {
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen failed to open library '%s' - %s",
+ cd->dl_path, dlerror());
+ 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);
+ if (cd->dl_path != NULL)
+ isc_mem_free(mctx, cd->dl_path);
+ if (cd->dlzname != NULL)
+ isc_mem_free(mctx, cd->dlzname);
+ if (dlopen_flags != 0)
+ (void) isc_mutex_destroy(&cd->lock);
+#ifdef HAVE_DLCLOSE
+ if (cd->dl_handle)
+ dlclose(cd->dl_handle);
+#endif
+ isc_mem_put(mctx, cd, sizeof(*cd));
+ isc_mem_destroy(&mctx);
+ 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;
+ isc_mem_t *mctx;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_destroy) {
+ MAYBE_LOCK(cd);
+ cd->dlz_destroy(cd->dbdata);
+ MAYBE_UNLOCK(cd);
+ }
+
+ if (cd->dl_path)
+ isc_mem_free(cd->mctx, cd->dl_path);
+ if (cd->dlzname)
+ isc_mem_free(cd->mctx, cd->dlzname);
+
+#ifdef HAVE_DLCLOSE
+ if (cd->dl_handle)
+ dlclose(cd->dl_handle);
+#endif
+
+ (void) isc_mutex_destroy(&cd->lock);
+
+ mctx = cd->mctx;
+ isc_mem_put(mctx, cd, sizeof(*cd));
+ isc_mem_destroy(&mctx);
+}
+
+/*
+ * 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
+};
+#endif
+
+/*
+ * Register driver with BIND
+ */
+isc_result_t
+dlz_dlopen_init(isc_mem_t *mctx) {
+#ifndef ISC_DLZ_DLOPEN
+ UNUSED(mctx);
+ return (ISC_R_NOTIMPLEMENTED);
+#else
+ 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(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+ return (result);
+#endif
+}
+
+
+/*
+ * Unregister the driver
+ */
+void
+dlz_dlopen_clear(void) {
+#ifdef ISC_DLZ_DLOPEN
+ dlopen_log(2, "Unregistering DLZ_dlopen driver");
+ if (dlz_dlopen != NULL)
+ dns_sdlzunregister(&dlz_dlopen);
+#endif
+}
diff --git a/bin/named/unix/include/named/os.h b/bin/named/unix/include/named/os.h
new file mode 100644
index 0000000..5415b83
--- /dev/null
+++ b/bin/named/unix/include/named/os.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NS_OS_H
+#define NS_OS_H 1
+
+/*! \file */
+
+#include <pwd.h>
+#include <stdbool.h>
+
+#include <isc/types.h>
+
+void
+ns_os_init(const char *progname);
+
+void
+ns_os_daemonize(void);
+
+void
+ns_os_opendevnull(void);
+
+void
+ns_os_closedevnull(void);
+
+void
+ns_os_chroot(const char *root);
+
+void
+ns_os_inituserinfo(const char *username);
+
+void
+ns_os_changeuser(void);
+
+uid_t
+ns_os_uid(void);
+
+void
+ns_os_adjustnofile(void);
+
+void
+ns_os_minprivs(void);
+
+FILE *
+ns_os_openfile(const char *filename, mode_t mode, bool switch_user);
+
+void
+ns_os_writepidfile(const char *filename, bool first_time);
+
+bool
+ns_os_issingleton(const char *filename);
+
+void
+ns_os_shutdown(void);
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len);
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text);
+
+void
+ns_os_tzset(void);
+
+void
+ns_os_started(void);
+
+char *
+ns_os_uname(void);
+
+#endif /* NS_OS_H */
diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c
new file mode 100644
index 0000000..809cede
--- /dev/null
+++ b/bin/named/unix/os.c
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+#include <sys/types.h> /* dev_t FreeBSD 2.1 */
+#include <sys/stat.h>
+#ifdef HAVE_UNAME
+#include <sys/utsname.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h> /* Required for initgroups() on IRIX. */
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <syslog.h>
+#ifdef HAVE_TZSET
+#include <time.h>
+#endif
+#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/strerror.h>
+#include <isc/string.h>
+
+#include <named/globals.h>
+#include <named/main.h>
+#include <named/os.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
+
+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
+
+/*
+ * If there's no <linux/capability.h>, we don't care about <sys/prctl.h>
+ */
+#ifndef HAVE_LINUX_CAPABILITY_H
+#undef HAVE_SYS_PRCTL_H
+#endif
+
+/*
+ * Linux defines:
+ * (T) HAVE_LINUXTHREADS
+ * (C) HAVE_SYS_CAPABILITY_H (or HAVE_LINUX_CAPABILITY_H)
+ * (P) HAVE_SYS_PRCTL_H
+ * The possible cases are:
+ * none: setuid() normally
+ * T: no setuid()
+ * C: setuid() normally, drop caps (keep CAP_SETUID)
+ * T+C: no setuid(), drop caps (don't keep CAP_SETUID)
+ * T+C+P: setuid() early, drop caps (keep CAP_SETUID)
+ * C+P: setuid() normally, drop caps (keep CAP_SETUID)
+ * P: not possible
+ * T+P: not possible
+ *
+ * if (C)
+ * caps = BIND_SERVICE + CHROOT + SETGID
+ * if ((T && C && P) || !T)
+ * caps += SETUID
+ * endif
+ * capset(caps)
+ * endif
+ * if (T && C && P && -u)
+ * setuid()
+ * else if (T && -u)
+ * fail
+ * --> start threads
+ * if (!T && -u)
+ * setuid()
+ * if (C && (P || !-u))
+ * caps = BIND_SERVICE
+ * capset(caps)
+ * endif
+ *
+ * It will be nice when Linux threads work properly with setuid().
+ */
+
+#ifdef HAVE_LINUXTHREADS
+static pid_t mainpid = 0;
+#endif
+
+static struct passwd *runas_pw = NULL;
+static bool done_setuid = false;
+static int dfd[2] = { -1, -1 };
+
+#ifdef HAVE_LINUX_CAPABILITY_H
+
+static bool non_root = false;
+static bool non_root_caps = false;
+
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#else
+#ifdef HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+/*%
+ * We define _LINUX_FS_H to prevent it from being included. We don't need
+ * anything from it, and the files it includes cause warnings with 2.2
+ * kernels, and compilation failures (due to conflicts between <linux/string.h>
+ * and <string.h>) on 2.3 kernels.
+ */
+#define _LINUX_FS_H
+#include <linux/capability.h>
+#include <syscall.h>
+#ifndef SYS_capset
+#ifndef __NR_capset
+#include <asm/unistd.h> /* Slackware 4.0 needs this. */
+#endif /* __NR_capset */
+#define SYS_capset __NR_capset
+#endif /* SYS_capset */
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h> /* Required for prctl(). */
+
+/*
+ * If the value of PR_SET_KEEPCAPS is not in <sys/prctl.h>, define it
+ * here. This allows setuid() to work on systems running a new enough
+ * kernel but with /usr/include/linux pointing to "standard" kernel
+ * headers.
+ */
+#ifndef PR_SET_KEEPCAPS
+#define PR_SET_KEEPCAPS 8
+#endif
+
+#endif /* HAVE_SYS_PRCTL_H */
+
+#ifdef HAVE_LIBCAP
+#define SETCAPS_FUNC "cap_set_proc "
+#else
+typedef unsigned int cap_t;
+#define SETCAPS_FUNC "syscall(capset) "
+#endif /* HAVE_LIBCAP */
+
+static void
+linux_setcaps(cap_t caps) {
+#ifndef HAVE_LIBCAP
+ struct __user_cap_header_struct caphead;
+ struct __user_cap_data_struct cap;
+#endif
+ char strbuf[ISC_STRERRORSIZE];
+
+ if ((getuid() != 0 && !non_root_caps) || non_root)
+ return;
+#ifndef HAVE_LIBCAP
+ memset(&caphead, 0, sizeof(caphead));
+ caphead.version = _LINUX_CAPABILITY_VERSION;
+ caphead.pid = 0;
+ memset(&cap, 0, sizeof(cap));
+ cap.effective = caps;
+ cap.permitted = caps;
+ cap.inheritable = 0;
+#endif
+#ifdef HAVE_LIBCAP
+ if (cap_set_proc(caps) < 0) {
+#else
+ if (syscall(SYS_capset, &caphead, &cap) < 0) {
+#endif
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal(SETCAPS_FUNC "failed: %s:"
+ " please ensure that the capset kernel"
+ " module is loaded. see insmod(8)",
+ strbuf);
+ }
+}
+
+#ifdef HAVE_LIBCAP
+#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) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \
+ } \
+ \
+ err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, CAP_SET); \
+ if (err == -1) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \
+ } \
+ } \
+ } while (0)
+#define INIT_CAP \
+ do { \
+ caps = cap_init(); \
+ if (caps == NULL) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_init failed: %s", strbuf); \
+ } \
+ curcaps = cap_get_proc(); \
+ if (curcaps == NULL) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_get_proc failed: %s", strbuf); \
+ } \
+ } while (0)
+#define FREE_CAP \
+ { \
+ cap_free(caps); \
+ cap_free(curcaps); \
+ } while (0)
+#else
+#define SET_CAP(flag) \
+ do { \
+ if (curcaps & (1 << (flag))) { \
+ caps |= (1 << (flag)); \
+ } \
+ } while (0)
+#define INIT_CAP do { caps = 0; } while (0)
+#endif /* HAVE_LIBCAP */
+
+#ifndef HAVE_LIBCAP
+/*%
+ * Store the bitmask representing the permitted capability set in 'capsp'. To
+ * match libcap-enabled behavior, capget() syscall errors are not reported,
+ * they just cause 'capsp' to be set to 0, which effectively prevents any
+ * capability from being subsequently requested.
+ */
+static void
+linux_getpermittedcaps(cap_t *capsp) {
+ struct __user_cap_header_struct caphead;
+ struct __user_cap_data_struct curcaps;
+
+ memset(&caphead, 0, sizeof(caphead));
+ caphead.version = _LINUX_CAPABILITY_VERSION;
+ caphead.pid = 0;
+ memset(&curcaps, 0, sizeof(curcaps));
+ syscall(SYS_capget, &caphead, &curcaps);
+
+ *capsp = curcaps.permitted;
+}
+#endif /* HAVE_LIBCAP */
+
+static void
+linux_initialprivs(void) {
+ cap_t curcaps;
+ cap_t caps;
+#ifdef HAVE_LIBCAP
+ cap_value_t capval;
+ char strbuf[ISC_STRERRORSIZE];
+ int err;
+#else
+ linux_getpermittedcaps(&curcaps);
+#endif
+
+ /*%
+ * 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);
+
+#if defined(HAVE_SYS_PRCTL_H) || !defined(HAVE_LINUXTHREADS)
+ /*
+ * We can setuid() only if either the kernel supports keeping
+ * capabilities after setuid() (which we don't know until we've
+ * tried) or we're not using threads. If either of these is
+ * true, we want the setuid capability.
+ */
+ SET_CAP(CAP_SETUID);
+#endif
+
+ /*
+ * 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);
+
+#ifdef HAVE_LIBCAP
+ FREE_CAP;
+#endif
+}
+
+static void
+linux_minprivs(void) {
+ cap_t curcaps;
+ cap_t caps;
+#ifdef HAVE_LIBCAP
+ cap_value_t capval;
+ char strbuf[ISC_STRERRORSIZE];
+ int err;
+#else
+ linux_getpermittedcaps(&curcaps);
+#endif
+
+ 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);
+
+#ifdef HAVE_LIBCAP
+ FREE_CAP;
+#endif
+}
+
+#ifdef HAVE_SYS_PRCTL_H
+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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("prctl() failed: %s", strbuf);
+ }
+ } else {
+ non_root_caps = true;
+ if (getuid() != 0)
+ non_root = true;
+ }
+}
+#endif
+
+#endif /* HAVE_LINUX_CAPABILITY_H */
+
+
+static void
+setup_syslog(const char *progname) {
+ int options;
+
+ options = LOG_PID;
+#ifdef LOG_NDELAY
+ options |= LOG_NDELAY;
+#endif
+ openlog(isc_file_basename(progname), options, ISC_FACILITY);
+}
+
+void
+ns_os_init(const char *progname) {
+ setup_syslog(progname);
+#ifdef HAVE_LINUX_CAPABILITY_H
+ linux_initialprivs();
+#endif
+#ifdef HAVE_LINUXTHREADS
+ mainpid = getpid();
+#endif
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+#endif
+}
+
+void
+ns_os_daemonize(void) {
+ pid_t pid;
+ char strbuf[ISC_STRERRORSIZE];
+
+ if (pipe(dfd) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("pipe(): %s", strbuf);
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_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.
+ */
+
+#ifdef HAVE_LINUXTHREADS
+ mainpid = getpid();
+#endif
+
+ if (setsid() == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_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 && !ns_g_keepstderr) {
+ (void)close(STDERR_FILENO);
+ (void)dup2(devnullfd, STDERR_FILENO);
+ }
+ }
+}
+
+void
+ns_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)
+ ns_main_earlyfatal("unable to signal parent that we "
+ "otherwise started successfully.");
+ close(dfd[1]);
+ dfd[0] = dfd[1] = -1;
+ }
+}
+
+void
+ns_os_opendevnull(void) {
+ devnullfd = open("/dev/null", O_RDWR, 0);
+}
+
+void
+ns_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((*s)&0xff))
+ return (false);
+ s++;
+ }
+ return (true);
+}
+
+void
+ns_os_chroot(const char *root) {
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef HAVE_LIBSCF
+ ns_smf_chroot = 0;
+#endif
+ if (root != NULL) {
+#ifdef HAVE_CHROOT
+ if (chroot(root) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("chroot(): %s", strbuf);
+ }
+#else
+ ns_main_earlyfatal("chroot(): disabled");
+#endif
+ if (chdir("/") < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("chdir(/): %s", strbuf);
+ }
+#ifdef HAVE_LIBSCF
+ /* Set ns_smf_chroot flag on successful chroot. */
+ ns_smf_chroot = 1;
+#endif
+ }
+}
+
+void
+ns_os_inituserinfo(const char *username) {
+ char strbuf[ISC_STRERRORSIZE];
+ 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)
+ ns_main_earlyfatal("user '%s' unknown", username);
+
+ if (getuid() == 0) {
+ if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("initgroups(): %s", strbuf);
+ }
+ }
+
+}
+
+void
+ns_os_changeuser(void) {
+ char strbuf[ISC_STRERRORSIZE];
+ if (runas_pw == NULL || done_setuid)
+ return;
+
+ done_setuid = true;
+
+#ifdef HAVE_LINUXTHREADS
+#ifdef HAVE_LINUX_CAPABILITY_H
+ if (!non_root_caps)
+ ns_main_earlyfatal("-u with Linux threads not supported: "
+ "requires kernel support for "
+ "prctl(PR_SET_KEEPCAPS)");
+#else
+ ns_main_earlyfatal("-u with Linux threads not supported: "
+ "no capabilities support or capabilities "
+ "disabled at build time");
+#endif
+#endif
+
+ if (setgid(runas_pw->pw_gid) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("setgid(): %s", strbuf);
+ }
+
+ if (setuid(runas_pw->pw_uid) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("setuid(): %s", strbuf);
+ }
+
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
+ /*
+ * 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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("prctl(PR_SET_DUMPABLE) failed: %s",
+ strbuf);
+ }
+#endif
+#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS)
+ linux_minprivs();
+#endif
+}
+
+uid_t
+ns_os_uid(void) {
+ if (runas_pw == NULL)
+ return (0);
+ return (runas_pw->pw_uid);
+}
+
+void
+ns_os_adjustnofile(void) {
+#ifdef HAVE_LINUXTHREADS
+ 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.
+ */
+ newvalue = ISC_RESOURCE_UNLIMITED;
+
+ result = isc_resource_setlimit(isc_resource_openfiles, newvalue);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlywarning("couldn't adjust limit on open files");
+#endif
+}
+
+void
+ns_os_minprivs(void) {
+#ifdef HAVE_SYS_PRCTL_H
+ linux_keepcaps();
+#endif
+
+#ifdef HAVE_LINUXTHREADS
+ ns_os_changeuser(); /* Call setuid() before threads are started */
+#endif
+
+#if defined(HAVE_LINUX_CAPABILITY_H) && defined(HAVE_LINUXTHREADS)
+ linux_minprivs();
+#endif
+}
+
+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)
+ ns_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)
+ ns_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) {
+ isc__strerror(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) {
+ isc__strerror(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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't chown '%s': %s", filename,
+ strbuf);
+ }
+ }
+ *slash = '/';
+ }
+ return (0);
+
+ error:
+ *slash = '/';
+ return (-1);
+}
+
+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)
+ gid_t oldgid, tmpg;
+#endif
+#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID)
+ uid_t olduid, tmpu;
+#endif
+#if defined(HAVE_SETEGID)
+ if (getegid() != gid && setegid(gid) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("unable to set effective "
+ "gid to %d: %s", gid, strbuf);
+ }
+ }
+#endif
+
+#if defined(HAVE_SETEUID)
+ if (geteuid() != uid && seteuid(uid) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("unable to set effective "
+ "uid to %d: %s", uid, strbuf);
+ }
+ }
+#endif
+}
+
+FILE *
+ns_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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("couldn't strdup() '%s': %s",
+ filename, strbuf);
+ return (NULL);
+ }
+ if (mkdirpath(f, ns_main_earlywarning) == -1) {
+ free(f);
+ return (NULL);
+ }
+ free(f);
+
+ if (switch_user && runas_pw != NULL) {
+#ifndef HAVE_LINUXTHREADS
+ gid_t oldgid = getgid();
+#endif
+ /* Set UID/GID to the one we'll be running with eventually */
+ setperms(runas_pw->pw_uid, runas_pw->pw_gid);
+
+ fd = safe_open(filename, mode, false);
+
+#ifndef HAVE_LINUXTHREADS
+ /* Restore UID/GID to root */
+ setperms(0, oldgid);
+#endif /* HAVE_LINUXTHREADS */
+
+ if (fd == -1) {
+#ifndef HAVE_LINUXTHREADS
+ fd = safe_open(filename, mode, false);
+ if (fd != -1) {
+ ns_main_earlywarning("Required root "
+ "permissions to open "
+ "'%s'.", filename);
+ } else {
+ ns_main_earlywarning("Could not open "
+ "'%s'.", filename);
+ }
+ ns_main_earlywarning("Please check file and "
+ "directory permissions "
+ "or reconfigure the filename.");
+#else /* HAVE_LINUXTHREADS */
+ ns_main_earlywarning("Could not open "
+ "'%s'.", filename);
+ ns_main_earlywarning("Please check file and "
+ "directory permissions "
+ "or reconfigure the filename.");
+#endif /* HAVE_LINUXTHREADS */
+ }
+ } else {
+ fd = safe_open(filename, mode, false);
+ }
+
+ if (fd < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("could not open file '%s': %s",
+ filename, strbuf);
+ return (NULL);
+ }
+
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("could not fdopen() file '%s': %s",
+ filename, strbuf);
+ }
+
+ return (fp);
+}
+
+void
+ns_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 ? ns_main_earlyfatal : ns_main_earlywarning;
+
+ cleanup_pidfile();
+
+ if (filename == NULL)
+ return;
+
+ pidfile = strdup(filename);
+ if (pidfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't strdup() '%s': %s", filename, strbuf);
+ return;
+ }
+
+ fh = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
+ first_time);
+ if (fh == NULL) {
+ cleanup_pidfile();
+ return;
+ }
+#ifdef HAVE_LINUXTHREADS
+ pid = mainpid;
+#else
+ pid = getpid();
+#endif
+ 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
+ns_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) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("couldn't allocate memory for '%s': %s",
+ filename, strbuf);
+ } else {
+ int ret = mkdirpath(lockfile, ns_main_earlywarning);
+ if (ret == -1) {
+ ns_main_earlywarning("couldn't create '%s'", filename);
+ cleanup_lockfile();
+ return (false);
+ }
+ }
+
+ /*
+ * ns_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
+ns_os_shutdown(void) {
+ closelog();
+ cleanup_pidfile();
+ cleanup_lockfile();
+}
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len) {
+ int n;
+
+ n = gethostname(buf, len);
+ return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
+}
+
+static char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
+ char *input, *ptr;
+ unsigned int n;
+ pid_t pid;
+
+ input = command;
+
+ /* Skip the command name. */
+ ptr = next_token(&input, " \t");
+ if (ptr == NULL)
+ return;
+
+ ptr = next_token(&input, " \t");
+ if (ptr == NULL)
+ return;
+
+ if (strcmp(ptr, "-p") != 0)
+ return;
+
+#ifdef HAVE_LINUXTHREADS
+ pid = mainpid;
+#else
+ pid = getpid();
+#endif
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "pid: %ld", (long)pid);
+ /* Only send a message if it is complete. */
+ if (n > 0 && n < isc_buffer_availablelength(text))
+ isc_buffer_add(text, n);
+}
+
+void
+ns_os_tzset(void) {
+#ifdef HAVE_TZSET
+ tzset();
+#endif
+}
+
+static char unamebuf[BUFSIZ];
+static 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);
+#else
+ snprintf(unamebuf, sizeof(unamebuf), "unknown architecture");
+#endif
+ unamep = unamebuf;
+}
+
+char *
+ns_os_uname(void) {
+ if (unamep == NULL)
+ getuname();
+ return (unamep);
+}
diff --git a/bin/named/update.c b/bin/named/update.c
new file mode 100644
index 0000000..973dda5
--- /dev/null
+++ b/bin/named/update.c
@@ -0,0 +1,3501 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/serial.h>
+#include <isc/stats.h>
+#include <isc/string.h>
+#include <isc/taskpool.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/private.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/soa.h>
+#include <dns/ssu.h>
+#include <dns/tsig.h>
+#include <dns/update.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/update.h>
+
+/*! \file
+ * \brief
+ * This module implements dynamic update as in RFC2136.
+ */
+
+/*
+ * XXX TODO:
+ * - document strict minimality
+ */
+
+/**************************************************************************/
+
+/*%
+ * Log level for tracing dynamic update protocol requests.
+ */
+#define LOGLEVEL_PROTOCOL ISC_LOG_INFO
+
+/*%
+ * Log level for low-level debug tracing.
+ */
+#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
+
+/*%
+ * Check an operation for failure. These macros all assume that
+ * the function using them has a 'result' variable and a 'failure'
+ * label.
+ */
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*%
+ * Fail unconditionally with result 'code', which must not
+ * be ISC_R_SUCCESS. The reason for failure presumably has
+ * been logged already.
+ *
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+
+#define FAIL(code) \
+ do { \
+ result = (code); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*%
+ * Fail unconditionally and log as a client error.
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAILC(code, msg) \
+ do { \
+ const char *_what = "failed"; \
+ result = (code); \
+ switch (result) { \
+ case DNS_R_NXDOMAIN: \
+ case DNS_R_YXDOMAIN: \
+ case DNS_R_YXRRSET: \
+ case DNS_R_NXRRSET: \
+ _what = "unsuccessful"; \
+ } \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "update %s: %s (%s)", _what, \
+ msg, isc_result_totext(result)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+#define PREREQFAILC(code, msg) \
+ do { \
+ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+ FAILC(code, msg); \
+ } while (0)
+
+#define FAILN(code, name, msg) \
+ do { \
+ const char *_what = "failed"; \
+ result = (code); \
+ switch (result) { \
+ case DNS_R_NXDOMAIN: \
+ case DNS_R_YXDOMAIN: \
+ case DNS_R_YXRRSET: \
+ case DNS_R_NXRRSET: \
+ _what = "unsuccessful"; \
+ } \
+ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
+ char _nbuf[DNS_NAME_FORMATSIZE]; \
+ dns_name_format(name, _nbuf, sizeof(_nbuf)); \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "update %s: %s: %s (%s)", _what, _nbuf, \
+ msg, isc_result_totext(result)); \
+ } \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+#define PREREQFAILN(code, name, msg) \
+ do { \
+ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+ FAILN(code, name, msg); \
+ } while (0)
+
+#define FAILNT(code, name, type, msg) \
+ do { \
+ const char *_what = "failed"; \
+ result = (code); \
+ switch (result) { \
+ case DNS_R_NXDOMAIN: \
+ case DNS_R_YXDOMAIN: \
+ case DNS_R_YXRRSET: \
+ case DNS_R_NXRRSET: \
+ _what = "unsuccessful"; \
+ } \
+ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
+ char _nbuf[DNS_NAME_FORMATSIZE]; \
+ char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
+ dns_name_format(name, _nbuf, sizeof(_nbuf)); \
+ dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "update %s: %s/%s: %s (%s)", \
+ _what, _nbuf, _tbuf, msg, \
+ isc_result_totext(result)); \
+ } \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+#define PREREQFAILNT(code, name, type, msg) \
+ do { \
+ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+ FAILNT(code, name, type, msg); \
+ } while (0)
+
+/*%
+ * Fail unconditionally and log as a server error.
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAILS(code, msg) \
+ do { \
+ result = (code); \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "error: %s: %s", \
+ msg, isc_result_totext(result)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*
+ * Return TRUE if NS_CLIENTATTR_TCP is set in the attributes other FALSE.
+ */
+#define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0)
+
+/**************************************************************************/
+
+typedef struct rr rr_t;
+
+struct rr {
+ /* dns_name_t name; */
+ uint32_t ttl;
+ dns_rdata_t rdata;
+};
+
+typedef struct update_event update_event_t;
+
+struct update_event {
+ ISC_EVENT_COMMON(update_event_t);
+ dns_zone_t *zone;
+ isc_result_t result;
+ dns_message_t *answer;
+};
+
+/*%
+ * Prepare an RR for the addition of the new RR 'ctx->update_rr',
+ * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting
+ * the RRs if it is replaced by the new RR or has a conflicting TTL.
+ * The necessary changes are appended to ctx->del_diff and ctx->add_diff;
+ * we need to do all deletions before any additions so that we don't run
+ * into transient states with conflicting TTLs.
+ */
+
+typedef struct {
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ dns_diff_t *diff;
+ dns_name_t *name;
+ dns_name_t *oldname;
+ dns_rdata_t *update_rr;
+ dns_ttl_t update_rr_ttl;
+ bool ignore_add;
+ dns_diff_t del_diff;
+ dns_diff_t add_diff;
+} add_rr_prepare_ctx_t;
+
+/**************************************************************************/
+/*
+ * Forward declarations.
+ */
+
+static void update_action(isc_task_t *task, isc_event_t *event);
+static void updatedone_action(isc_task_t *task, isc_event_t *event);
+static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone);
+static void forward_done(isc_task_t *task, isc_event_t *event);
+static isc_result_t add_rr_prepare_action(void *data, rr_t *rr);
+
+/**************************************************************************/
+
+static void
+update_log(ns_client_t *client, dns_zone_t *zone,
+ int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
+
+static void
+update_log(ns_client_t *client, dns_zone_t *zone,
+ int level, const char *fmt, ...)
+{
+ va_list ap;
+ char message[4096];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ if (client == NULL || zone == NULL)
+ return;
+
+ if (isc_log_wouldlog(ns_g_lctx, level) == false)
+ return;
+
+ dns_name_format(dns_zone_getorigin(zone), namebuf,
+ sizeof(namebuf));
+ dns_rdataclass_format(dns_zone_getclass(zone), classbuf,
+ sizeof(classbuf));
+
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
+ level, "updating zone '%s/%s': %s",
+ namebuf, classbuf, message);
+}
+
+static void
+update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
+ update_log(arg, zone, level, "%s", message);
+}
+
+/*%
+ * Increment updated-related statistics counters.
+ */
+static inline void
+inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
+ isc_stats_increment(ns_g_server->nsstats, counter);
+
+ if (zone != NULL) {
+ isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL)
+ isc_stats_increment(zonestats, counter);
+ }
+}
+
+/*%
+ * Check if we could have queried for the contents of this zone or
+ * if the zone is potentially updateable.
+ * If the zone can potentially be updated and the check failed then
+ * log a error otherwise we log a informational message.
+ */
+static isc_result_t
+checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename,
+ dns_acl_t *updateacl, dns_ssutable_t *ssutable)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ int level;
+ isc_result_t result;
+
+ result = ns_client_checkaclsilent(client, NULL, queryacl, true);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+
+ level = (updateacl == NULL && ssutable == NULL) ?
+ ISC_LOG_INFO : ISC_LOG_ERROR;
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, level,
+ "update '%s/%s' denied due to allow-query",
+ namebuf, classbuf);
+ } else if (updateacl == NULL && ssutable == NULL) {
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+
+ result = DNS_R_REFUSED;
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
+ "update '%s/%s' denied", namebuf, classbuf);
+ }
+ return (result);
+}
+
+/*%
+ * Override the default acl logging when checking whether a client
+ * can update the zone or whether we can forward the request to the
+ * master based on IP address.
+ *
+ * 'message' contains the type of operation that is being attempted.
+ * 'slave' indicates if this is a slave zone. If 'acl' is NULL then
+ * log at debug=3.
+ * If the zone has no access controls configured ('acl' == NULL &&
+ * 'has_ssutable == ISC_FALS) log the attempt at info, otherwise
+ * at error.
+ *
+ * If the request was signed log that we received it.
+ */
+static isc_result_t
+checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,
+ dns_name_t *zonename, bool slave,
+ bool has_ssutable)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ int level = ISC_LOG_ERROR;
+ const char *msg = "denied";
+ isc_result_t result;
+
+ if (slave && acl == NULL) {
+ result = DNS_R_NOTIMP;
+ level = ISC_LOG_DEBUG(3);
+ msg = "disabled";
+ } else {
+ result = ns_client_checkaclsilent(client, NULL, acl, false);
+ if (result == ISC_R_SUCCESS) {
+ level = ISC_LOG_DEBUG(3);
+ msg = "approved";
+ } else if (acl == NULL && !has_ssutable) {
+ level = ISC_LOG_INFO;
+ }
+ }
+
+ if (client->signer != NULL) {
+ dns_name_format(client->signer, namebuf, sizeof(namebuf));
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
+ "signer \"%s\" %s", namebuf, msg);
+ }
+
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s",
+ message, namebuf, classbuf, msg);
+ return (result);
+}
+
+/*%
+ * Update a single RR in version 'ver' of 'db' and log the
+ * update in 'diff'.
+ *
+ * Ensures:
+ * \li '*tuple' == NULL. Either the tuple is freed, or its
+ * ownership has been transferred to the diff.
+ */
+static isc_result_t
+do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ dns_diff_t temp_diff;
+ isc_result_t result;
+
+ /*
+ * Create a singleton diff.
+ */
+ dns_diff_init(diff->mctx, &temp_diff);
+ ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
+
+ /*
+ * Apply it to the database.
+ */
+ result = dns_diff_apply(&temp_diff, db, ver);
+ ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
+ if (result != ISC_R_SUCCESS) {
+ dns_difftuple_free(tuple);
+ return (result);
+ }
+
+ /*
+ * Merge it into the current pending journal entry.
+ */
+ dns_diff_appendminimal(diff, tuple);
+
+ /*
+ * Do not clear temp_diff.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Perform the updates in 'updates' in version 'ver' of 'db' and log the
+ * update in 'diff'.
+ *
+ * Ensures:
+ * \li 'updates' is empty.
+ */
+static isc_result_t
+do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ while (! ISC_LIST_EMPTY(updates->tuples)) {
+ dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples);
+ ISC_LIST_UNLINK(updates->tuples, t, link);
+ CHECK(do_one_tuple(&t, db, ver, diff));
+ }
+ return (ISC_R_SUCCESS);
+
+ failure:
+ dns_diff_clear(diff);
+ return (result);
+}
+
+static isc_result_t
+update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
+ dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+ dns_rdata_t *rdata)
+{
+ dns_difftuple_t *tuple = NULL;
+ isc_result_t result;
+ result = dns_difftuple_create(diff->mctx, op,
+ name, ttl, rdata, &tuple);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (do_one_tuple(&tuple, db, ver, diff));
+}
+
+/**************************************************************************/
+/*
+ * Callback-style iteration over rdatasets and rdatas.
+ *
+ * foreach_rrset() can be used to iterate over the RRsets
+ * of a name and call a callback function with each
+ * one. Similarly, foreach_rr() can be used to iterate
+ * over the individual RRs at name, optionally restricted
+ * to RRs of a given type.
+ *
+ * The callback functions are called "actions" and take
+ * two arguments: a void pointer for passing arbitrary
+ * context information, and a pointer to the current RRset
+ * or RR. By convention, their names end in "_action".
+ */
+
+/*
+ * XXXRTH We might want to make this public somewhere in libdns.
+ */
+
+/*%
+ * Function type for foreach_rrset() iterator actions.
+ */
+typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
+
+/*%
+ * Function type for foreach_rr() iterator actions.
+ */
+typedef isc_result_t rr_func(void *data, rr_t *rr);
+
+/*%
+ * Internal context struct for foreach_node_rr().
+ */
+typedef struct {
+ rr_func * rr_action;
+ void * rr_action_data;
+} foreach_node_rr_ctx_t;
+
+/*%
+ * Internal helper function for foreach_node_rr().
+ */
+static isc_result_t
+foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ foreach_node_rr_ctx_t *ctx = data;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ rr_t rr = { 0, DNS_RDATA_INIT };
+
+ dns_rdataset_current(rdataset, &rr.rdata);
+ rr.ttl = rdataset->ttl;
+ result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (result != ISC_R_NOMORE)
+ return (result);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * For each rdataset of 'name' in 'ver' of 'db', call 'action'
+ * with the rdataset and 'action_data' as arguments. If the name
+ * does not exist, do nothing.
+ *
+ * If 'action' returns an error, abort iteration and return the error.
+ */
+static isc_result_t
+foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ rrset_func *action, void *action_data)
+{
+ isc_result_t result;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *iter;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ dns_dbversion_t *oldver = NULL;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+
+ /*
+ * Only set the clientinfo 'versionp' if the new version is
+ * different from the current version
+ */
+ dns_db_currentversion(db, &oldver);
+ dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL);
+ dns_db_closeversion(db, &oldver, false);
+
+ node = NULL;
+ result = dns_db_findnodeext(db, name, false, &cm, &ci, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ iter = NULL;
+ result = dns_db_allrdatasets(db, node, ver,
+ (isc_stdtime_t) 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdatasetiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatasetiter_current(iter, &rdataset);
+
+ result = (*action)(action_data, &rdataset);
+
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iterator;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ cleanup_iterator:
+ dns_rdatasetiter_destroy(&iter);
+
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+/*%
+ * For each RR of 'name' in 'ver' of 'db', call 'action'
+ * with the RR and 'action_data' as arguments. If the name
+ * does not exist, do nothing.
+ *
+ * If 'action' returns an error, abort iteration
+ * and return the error.
+ */
+static isc_result_t
+foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ rr_func *rr_action, void *rr_action_data)
+{
+ foreach_node_rr_ctx_t ctx;
+ ctx.rr_action = rr_action;
+ ctx.rr_action_data = rr_action_data;
+ return (foreach_rrset(db, ver, name,
+ foreach_node_rr_action, &ctx));
+}
+
+
+/*%
+ * For each of the RRs specified by 'db', 'ver', 'name', 'type',
+ * (which can be dns_rdatatype_any to match any type), and 'covers', call
+ * 'action' with the RR and 'action_data' as arguments. If the name
+ * does not exist, or if no RRset of the given type exists at the name,
+ * do nothing.
+ *
+ * If 'action' returns an error, abort iteration and return the error.
+ */
+static isc_result_t
+foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
+ void *rr_action_data)
+{
+
+ isc_result_t result;
+ dns_dbnode_t *node;
+ dns_rdataset_t rdataset;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ dns_dbversion_t *oldver = NULL;
+ dns_fixedname_t fixed;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+
+ /*
+ * Only set the clientinfo 'versionp' if the new version is
+ * different from the current version
+ */
+ dns_db_currentversion(db, &oldver);
+ dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL);
+ dns_db_closeversion(db, &oldver, false);
+
+ if (type == dns_rdatatype_any)
+ return (foreach_node_rr(db, ver, name,
+ rr_action, rr_action_data));
+
+ node = NULL;
+ if (type == dns_rdatatype_nsec3 ||
+ (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
+ result = dns_db_findnsec3node(db, name, false, &node);
+ else
+ result = dns_db_findnodeext(db, name, false,
+ &cm, &ci, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, type, covers,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup_node;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ if (rr_action == add_rr_prepare_action) {
+ add_rr_prepare_ctx_t *ctx = rr_action_data;
+
+ ctx->oldname = dns_fixedname_initname(&fixed);
+ dns_name_copy(name, ctx->oldname, NULL);
+ dns_rdataset_getownercase(&rdataset, ctx->oldname);
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ rr_t rr = { 0, DNS_RDATA_INIT };
+ dns_rdataset_current(&rdataset, &rr.rdata);
+ rr.ttl = rdataset.ttl;
+ result = (*rr_action)(rr_action_data, &rr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rdataset;
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup_rdataset;
+ result = ISC_R_SUCCESS;
+
+ cleanup_rdataset:
+ dns_rdataset_disassociate(&rdataset);
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * Various tests on the database contents (for prerequisites, etc).
+ */
+
+/*%
+ * Function type for predicate functions that compare a database RR 'db_rr'
+ * against an update RR 'update_rr'.
+ */
+typedef bool rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
+
+/*%
+ * Helper function for rrset_exists().
+ */
+static isc_result_t
+rrset_exists_action(void *data, rr_t *rr) {
+ UNUSED(data);
+ UNUSED(rr);
+ return (ISC_R_EXISTS);
+}
+
+/*%
+ * Utility macro for RR existence checking functions.
+ *
+ * If the variable 'result' has the value ISC_R_EXISTS or
+ * ISC_R_SUCCESS, set *exists to true or false,
+ * respectively, and return success.
+ *
+ * If 'result' has any other value, there was a failure.
+ * Return the failure result code and do not set *exists.
+ *
+ * This would be more readable as "do { if ... } while(0)",
+ * but that form generates tons of warnings on Solaris 2.6.
+ */
+#define RETURN_EXISTENCE_FLAG \
+ return ((result == ISC_R_EXISTS) ? \
+ (*exists = true, ISC_R_SUCCESS) : \
+ ((result == ISC_R_SUCCESS) ? \
+ (*exists = false, ISC_R_SUCCESS) : \
+ result))
+
+/*%
+ * Set '*exists' to true iff an rrset of the given type exists,
+ * to false otherwise.
+ */
+static isc_result_t
+rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ bool *exists)
+{
+ isc_result_t result;
+ result = foreach_rr(db, ver, name, type, covers,
+ rrset_exists_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*%
+ * Helper function for cname_incompatible_rrset_exists.
+ */
+static isc_result_t
+cname_compatibility_action(void *data, dns_rdataset_t *rrset) {
+ UNUSED(data);
+ if (rrset->type != dns_rdatatype_cname &&
+ ! dns_rdatatype_isdnssec(rrset->type))
+ return (ISC_R_EXISTS);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Check whether there is an rrset incompatible with adding a CNAME RR,
+ * i.e., anything but another CNAME (which can be replaced) or a
+ * DNSSEC RR (which can coexist).
+ *
+ * If such an incompatible rrset exists, set '*exists' to true.
+ * Otherwise, set it to false.
+ */
+static isc_result_t
+cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *name, bool *exists) {
+ isc_result_t result;
+ result = foreach_rrset(db, ver, name,
+ cname_compatibility_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*%
+ * Helper function for rr_count().
+ */
+static isc_result_t
+count_rr_action(void *data, rr_t *rr) {
+ int *countp = data;
+ UNUSED(rr);
+ (*countp)++;
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Count the number of RRs of 'type' belonging to 'name' in 'ver' of 'db'.
+ */
+static isc_result_t
+rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers, int *countp)
+{
+ *countp = 0;
+ return (foreach_rr(db, ver, name, type, covers,
+ count_rr_action, countp));
+}
+
+/*%
+ * Context struct and helper function for name_exists().
+ */
+
+static isc_result_t
+name_exists_action(void *data, dns_rdataset_t *rrset) {
+ UNUSED(data);
+ UNUSED(rrset);
+ return (ISC_R_EXISTS);
+}
+
+/*%
+ * Set '*exists' to true iff the given name exists, to false otherwise.
+ */
+static isc_result_t
+name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ bool *exists)
+{
+ isc_result_t result;
+ result = foreach_rrset(db, ver, name,
+ name_exists_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*
+ * 'ssu_check_t' is used to pass the arguments to
+ * dns_ssutable_checkrules() to the callback function
+ * ssu_checkrule().
+ */
+typedef struct {
+ /* The ownername of the record to be updated. */
+ dns_name_t *name;
+
+ /* The signature's name if the request was signed. */
+ dns_name_t *signer;
+
+ /* The address of the client. */
+ isc_netaddr_t *addr;
+
+ /* Whether the request was sent via TCP. */
+ bool tcp;
+
+ /* The ssu table to check against. */
+ dns_ssutable_t *table;
+
+ /* the key used for TKEY requests */
+ dst_key_t *key;
+} ssu_check_t;
+
+static isc_result_t
+ssu_checkrule(void *data, dns_rdataset_t *rrset) {
+ ssu_check_t *ssuinfo = data;
+ bool result;
+
+ /*
+ * If we're deleting all records, it's ok to delete RRSIG and NSEC even
+ * if we're normally not allowed to.
+ */
+ if (rrset->type == dns_rdatatype_rrsig ||
+ rrset->type == dns_rdatatype_nsec)
+ return (ISC_R_SUCCESS);
+ result = dns_ssutable_checkrules2(ssuinfo->table, ssuinfo->signer,
+ ssuinfo->name, ssuinfo->addr,
+ ssuinfo->tcp, &ns_g_server->aclenv,
+ rrset->type, ssuinfo->key);
+ return (result == true ? ISC_R_SUCCESS : ISC_R_FAILURE);
+}
+
+static bool
+ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_ssutable_t *ssutable, dns_name_t *signer,
+ isc_netaddr_t *addr, bool tcp, dst_key_t *key)
+{
+ isc_result_t result;
+ ssu_check_t ssuinfo;
+
+ ssuinfo.name = name;
+ ssuinfo.table = ssutable;
+ ssuinfo.signer = signer;
+ ssuinfo.addr = addr;
+ ssuinfo.tcp = tcp;
+ ssuinfo.key = key;
+ result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo);
+ return (result == ISC_R_SUCCESS);
+}
+
+/**************************************************************************/
+/*
+ * Checking of "RRset exists (value dependent)" prerequisites.
+ *
+ * In the RFC2136 section 3.2.5, this is the pseudocode involving
+ * a variable called "temp", a mapping of <name, type> tuples to rrsets.
+ *
+ * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
+ * where each tuple has op==DNS_DIFFOP_EXISTS.
+ */
+
+
+/*%
+ * Append a tuple asserting the existence of the RR with
+ * 'name' and 'rdata' to 'diff'.
+ */
+static isc_result_t
+temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) {
+ isc_result_t result;
+ dns_difftuple_t *tuple = NULL;
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS,
+ name, 0, rdata, &tuple));
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+ failure:
+ return (result);
+}
+
+/*%
+ * Compare two rdatasets represented as sorted lists of tuples.
+ * All list elements must have the same owner name and type.
+ * Return ISC_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset)
+ * if not.
+ */
+static isc_result_t
+temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) {
+ for (;;) {
+ if (a == NULL || b == NULL)
+ break;
+ INSIST(a->op == DNS_DIFFOP_EXISTS &&
+ b->op == DNS_DIFFOP_EXISTS);
+ INSIST(a->rdata.type == b->rdata.type);
+ INSIST(dns_name_equal(&a->name, &b->name));
+ if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0)
+ return (DNS_R_NXRRSET);
+ a = ISC_LIST_NEXT(a, link);
+ b = ISC_LIST_NEXT(b, link);
+ }
+ if (a != NULL || b != NULL)
+ return (DNS_R_NXRRSET);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * A comparison function defining the sorting order for the entries
+ * in the "temp" data structure. The major sort key is the owner name,
+ * followed by the type and rdata.
+ */
+static int
+temp_order(const void *av, const void *bv) {
+ dns_difftuple_t const * const *ap = av;
+ dns_difftuple_t const * const *bp = bv;
+ dns_difftuple_t const *a = *ap;
+ dns_difftuple_t const *b = *bp;
+ int r;
+ r = dns_name_compare(&a->name, &b->name);
+ if (r != 0)
+ return (r);
+ r = (b->rdata.type - a->rdata.type);
+ if (r != 0)
+ return (r);
+ r = dns_rdata_casecompare(&a->rdata, &b->rdata);
+ return (r);
+}
+
+/*%
+ * Check the "RRset exists (value dependent)" prerequisite information
+ * in 'temp' against the contents of the database 'db'.
+ *
+ * Return ISC_R_SUCCESS if the prerequisites are satisfied,
+ * rcode(dns_rcode_nxrrset) if not.
+ *
+ * 'temp' must be pre-sorted.
+ */
+
+static isc_result_t
+temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db,
+ dns_dbversion_t *ver, dns_name_t *tmpname, dns_rdatatype_t *typep)
+{
+ isc_result_t result;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ dns_difftuple_t *t;
+ dns_diff_t trash;
+
+ dns_diff_init(mctx, &trash);
+
+ /*
+ * For each name and type in the prerequisites,
+ * construct a sorted rdata list of the corresponding
+ * database contents, and compare the lists.
+ */
+ t = ISC_LIST_HEAD(temp->tuples);
+ while (t != NULL) {
+ name = &t->name;
+ (void)dns_name_copy(name, tmpname, NULL);
+ *typep = t->rdata.type;
+
+ /* A new unique name begins here. */
+ node = NULL;
+ result = dns_db_findnode(db, name, false, &node);
+ if (result == ISC_R_NOTFOUND) {
+ dns_diff_clear(&trash);
+ return (DNS_R_NXRRSET);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_diff_clear(&trash);
+ return (result);
+ }
+
+ /* A new unique type begins here. */
+ while (t != NULL && dns_name_equal(&t->name, name)) {
+ dns_rdatatype_t type, covers;
+ dns_rdataset_t rdataset;
+ dns_diff_t d_rrs; /* Database RRs with
+ this name and type */
+ dns_diff_t u_rrs; /* Update RRs with
+ this name and type */
+
+ *typep = type = t->rdata.type;
+ if (type == dns_rdatatype_rrsig ||
+ type == dns_rdatatype_sig)
+ covers = dns_rdata_covers(&t->rdata);
+ else if (type == dns_rdatatype_any) {
+ dns_db_detachnode(db, &node);
+ dns_diff_clear(&trash);
+ return (DNS_R_NXRRSET);
+ } else
+ covers = 0;
+
+ /*
+ * Collect all database RRs for this name and type
+ * onto d_rrs and sort them.
+ */
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, type,
+ covers, (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &node);
+ dns_diff_clear(&trash);
+ return (DNS_R_NXRRSET);
+ }
+
+ dns_diff_init(mctx, &d_rrs);
+ dns_diff_init(mctx, &u_rrs);
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ result = temp_append(&d_rrs, name, &rdata);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ result = dns_diff_sort(&d_rrs, temp_order);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Collect all update RRs for this name and type
+ * onto u_rrs. No need to sort them here -
+ * they are already sorted.
+ */
+ while (t != NULL &&
+ dns_name_equal(&t->name, name) &&
+ t->rdata.type == type)
+ {
+ dns_difftuple_t *next =
+ ISC_LIST_NEXT(t, link);
+ ISC_LIST_UNLINK(temp->tuples, t, link);
+ ISC_LIST_APPEND(u_rrs.tuples, t, link);
+ t = next;
+ }
+
+ /* Compare the two sorted lists. */
+ result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples),
+ ISC_LIST_HEAD(d_rrs.tuples));
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * We are done with the tuples, but we can't free
+ * them yet because "name" still points into one
+ * of them. Move them on a temporary list.
+ */
+ ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link);
+ ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link);
+ dns_rdataset_disassociate(&rdataset);
+
+ continue;
+
+ failure:
+ dns_diff_clear(&d_rrs);
+ dns_diff_clear(&u_rrs);
+ dns_diff_clear(&trash);
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (result);
+ }
+
+ dns_db_detachnode(db, &node);
+ }
+
+ dns_diff_clear(&trash);
+ return (ISC_R_SUCCESS);
+}
+
+/**************************************************************************/
+/*
+ * Conditional deletion of RRs.
+ */
+
+/*%
+ * Context structure for delete_if().
+ */
+
+typedef struct {
+ rr_predicate *predicate;
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ dns_diff_t *diff;
+ dns_name_t *name;
+ dns_rdata_t *update_rr;
+} conditional_delete_ctx_t;
+
+/*%
+ * Predicate functions for delete_if().
+ */
+
+/*%
+ * Return true iff 'db_rr' is neither a SOA nor an NS RR nor
+ * an RRSIG nor an NSEC3PARAM nor a NSEC.
+ */
+static bool
+type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ return ((db_rr->type != dns_rdatatype_soa &&
+ db_rr->type != dns_rdatatype_ns &&
+ db_rr->type != dns_rdatatype_nsec3param &&
+ db_rr->type != dns_rdatatype_rrsig &&
+ db_rr->type != dns_rdatatype_nsec) ?
+ true : false);
+}
+
+/*%
+ * Return true iff 'db_rr' is neither a RRSIG nor a NSEC.
+ */
+static bool
+type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ return ((db_rr->type != dns_rdatatype_rrsig &&
+ db_rr->type != dns_rdatatype_nsec) ?
+ true : false);
+}
+
+/*%
+ * Return true always.
+ */
+static bool
+true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ UNUSED(db_rr);
+ return (true);
+}
+
+/*%
+ * Return true iff the two RRs have identical rdata.
+ */
+static bool
+rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ /*
+ * XXXRTH This is not a problem, but we should consider creating
+ * dns_rdata_equal() (that used dns_name_equal()), since it
+ * would be faster. Not a priority.
+ */
+ return (dns_rdata_casecompare(update_rr, db_rr) == 0 ?
+ true : false);
+}
+
+/*%
+ * Return true iff 'update_rr' should replace 'db_rr' according
+ * to the special RFC2136 rules for CNAME, SOA, and WKS records.
+ *
+ * RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs
+ * make little sense, so we replace those, too.
+ *
+ * Additionally replace RRSIG that have been generated by the same key
+ * for the same type. This simplifies refreshing a offline KSK by not
+ * requiring that the old RRSIG be deleted. It also simplifies key
+ * rollover by only requiring that the new RRSIG be added.
+ */
+static bool
+replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ dns_rdata_rrsig_t updatesig, dbsig;
+ isc_result_t result;
+
+ if (db_rr->type != update_rr->type)
+ return (false);
+ if (db_rr->type == dns_rdatatype_cname)
+ return (true);
+ if (db_rr->type == dns_rdatatype_dname)
+ return (true);
+ if (db_rr->type == dns_rdatatype_soa)
+ return (true);
+ if (db_rr->type == dns_rdatatype_nsec)
+ return (true);
+ if (db_rr->type == dns_rdatatype_rrsig) {
+ /*
+ * Replace existing RRSIG with the same keyid,
+ * covered and algorithm.
+ */
+ result = dns_rdata_tostruct(db_rr, &dbsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_rdata_tostruct(update_rr, &updatesig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (dbsig.keyid == updatesig.keyid &&
+ dbsig.covered == updatesig.covered &&
+ dbsig.algorithm == updatesig.algorithm)
+ return (true);
+ }
+ if (db_rr->type == dns_rdatatype_wks) {
+ /*
+ * Compare the address and protocol fields only. These
+ * form the first five bytes of the RR data. Do a
+ * raw binary comparison; unpacking the WKS RRs using
+ * dns_rdata_tostruct() might be cleaner in some ways.
+ */
+ INSIST(db_rr->length >= 5 && update_rr->length >= 5);
+ return (memcmp(db_rr->data, update_rr->data, 5) == 0 ?
+ true : false);
+ }
+
+ if (db_rr->type == dns_rdatatype_nsec3param) {
+ if (db_rr->length != update_rr->length)
+ return (false);
+ INSIST(db_rr->length >= 4 && update_rr->length >= 4);
+ /*
+ * Replace NSEC3PARAM records that only differ by the
+ * flags field.
+ */
+ if (db_rr->data[0] == update_rr->data[0] &&
+ memcmp(db_rr->data+2, update_rr->data+2,
+ update_rr->length - 2) == 0)
+ return (true);
+ }
+ return (false);
+}
+
+/*%
+ * Internal helper function for delete_if().
+ */
+static isc_result_t
+delete_if_action(void *data, rr_t *rr) {
+ conditional_delete_ctx_t *ctx = data;
+ if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
+ isc_result_t result;
+ result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
+ DNS_DIFFOP_DEL, ctx->name,
+ rr->ttl, &rr->rdata);
+ return (result);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+}
+
+/*%
+ * Conditionally delete RRs. Apply 'predicate' to the RRs
+ * specified by 'db', 'ver', 'name', and 'type' (which can
+ * be dns_rdatatype_any to match any type). Delete those
+ * RRs for which the predicate returns true, and log the
+ * deletions in 'diff'.
+ */
+static isc_result_t
+delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
+ dns_rdata_t *update_rr, dns_diff_t *diff)
+{
+ conditional_delete_ctx_t ctx;
+ ctx.predicate = predicate;
+ ctx.db = db;
+ ctx.ver = ver;
+ ctx.diff = diff;
+ ctx.name = name;
+ ctx.update_rr = update_rr;
+ return (foreach_rr(db, ver, name, type, covers,
+ delete_if_action, &ctx));
+}
+
+/**************************************************************************/
+
+static isc_result_t
+add_rr_prepare_action(void *data, rr_t *rr) {
+ isc_result_t result = ISC_R_SUCCESS;
+ add_rr_prepare_ctx_t *ctx = data;
+ dns_difftuple_t *tuple = NULL;
+ bool equal, case_equal, ttl_equal;
+
+ /*
+ * Are the new and old cases equal?
+ */
+ case_equal = dns_name_caseequal(ctx->name, ctx->oldname);
+
+ /*
+ * Are the ttl's equal?
+ */
+ ttl_equal = rr->ttl == ctx->update_rr_ttl;
+
+ /*
+ * If the update RR is a "duplicate" of a existing RR,
+ * the update should be silently ignored.
+ */
+ equal = !dns_rdata_casecompare(&rr->rdata, ctx->update_rr);
+ if (equal && case_equal && ttl_equal) {
+ ctx->ignore_add = true;
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If this RR is "equal" to the update RR, it should
+ * be deleted before the update RR is added.
+ */
+ if (replaces_p(ctx->update_rr, &rr->rdata)) {
+ CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
+ ctx->oldname, rr->ttl, &rr->rdata,
+ &tuple));
+ dns_diff_append(&ctx->del_diff, &tuple);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If this RR differs in TTL or case from the update RR,
+ * its TTL and case must be adjusted.
+ */
+ if (!ttl_equal || !case_equal) {
+ CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
+ ctx->oldname, rr->ttl, &rr->rdata,
+ &tuple));
+ dns_diff_append(&ctx->del_diff, &tuple);
+ if (!equal) {
+ CHECK(dns_difftuple_create(ctx->add_diff.mctx,
+ DNS_DIFFOP_ADD, ctx->name,
+ ctx->update_rr_ttl,
+ &rr->rdata, &tuple));
+ dns_diff_append(&ctx->add_diff, &tuple);
+ }
+ }
+ failure:
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * Miscellaneous subroutines.
+ */
+
+/*%
+ * Extract a single update RR from 'section' of dynamic update message
+ * 'msg', with consistency checking.
+ *
+ * Stores the owner name, rdata, and TTL of the update RR at 'name',
+ * 'rdata', and 'ttl', respectively.
+ */
+static void
+get_current_rr(dns_message_t *msg, dns_section_t section,
+ dns_rdataclass_t zoneclass, dns_name_t **name,
+ dns_rdata_t *rdata, dns_rdatatype_t *covers,
+ dns_ttl_t *ttl, dns_rdataclass_t *update_class)
+{
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+ dns_message_currentname(msg, section, name);
+ rdataset = ISC_LIST_HEAD((*name)->list);
+ INSIST(rdataset != NULL);
+ INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
+ *covers = rdataset->covers;
+ *ttl = rdataset->ttl;
+ result = dns_rdataset_first(rdataset);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, rdata);
+ INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
+ *update_class = rdata->rdclass;
+ rdata->rdclass = zoneclass;
+}
+
+/*%
+ * Increment the SOA serial number of database 'db', version 'ver'.
+ * Replace the SOA record in the database, and log the
+ * change in 'diff'.
+ */
+
+ /*
+ * XXXRTH Failures in this routine will be worth logging, when
+ * we have a logging system. Failure to find the zonename
+ * or the SOA rdataset warrant at least an UNEXPECTED_ERROR().
+ */
+
+static isc_result_t
+update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
+ isc_mem_t *mctx, dns_updatemethod_t method)
+{
+ dns_difftuple_t *deltuple = NULL;
+ dns_difftuple_t *addtuple = NULL;
+ uint32_t serial;
+ isc_result_t result;
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
+ CHECK(dns_difftuple_copy(deltuple, &addtuple));
+ addtuple->op = DNS_DIFFOP_ADD;
+
+ serial = dns_soa_getserial(&addtuple->rdata);
+ serial = dns_update_soaserial(serial, method);
+ dns_soa_setserial(serial, &addtuple->rdata);
+ CHECK(do_one_tuple(&deltuple, db, ver, diff));
+ CHECK(do_one_tuple(&addtuple, db, ver, diff));
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (addtuple != NULL)
+ dns_difftuple_free(&addtuple);
+ if (deltuple != NULL)
+ dns_difftuple_free(&deltuple);
+ return (result);
+}
+
+/*%
+ * Check that the new SOA record at 'update_rdata' does not
+ * illegally cause the SOA serial number to decrease or stay
+ * unchanged relative to the existing SOA in 'db'.
+ *
+ * Sets '*ok' to true if the update is legal, false if not.
+ *
+ * William King points out that RFC2136 is inconsistent about
+ * the case where the serial number stays unchanged:
+ *
+ * section 3.4.2.2 requires a server to ignore a SOA update request
+ * if the serial number on the update SOA is less_than_or_equal to
+ * the zone SOA serial.
+ *
+ * section 3.6 requires a server to ignore a SOA update request if
+ * the serial is less_than the zone SOA serial.
+ *
+ * Paul says 3.4.2.2 is correct.
+ *
+ */
+static isc_result_t
+check_soa_increment(dns_db_t *db, dns_dbversion_t *ver,
+ dns_rdata_t *update_rdata, bool *ok)
+{
+ uint32_t db_serial;
+ uint32_t update_serial;
+ isc_result_t result;
+
+ update_serial = dns_soa_getserial(update_rdata);
+
+ result = dns_db_getsoaserial(db, ver, &db_serial);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (DNS_SERIAL_GE(db_serial, update_serial)) {
+ *ok = false;
+ } else {
+ *ok = true;
+ }
+
+ return (ISC_R_SUCCESS);
+
+}
+
+/**************************************************************************/
+/*%
+ * The actual update code in all its glory. We try to follow
+ * the RFC2136 pseudocode as closely as possible.
+ */
+
+static isc_result_t
+send_update_event(ns_client_t *client, dns_zone_t *zone) {
+ isc_result_t result = ISC_R_SUCCESS;
+ update_event_t *event = NULL;
+ isc_task_t *zonetask = NULL;
+ ns_client_t *evclient;
+
+ event = (update_event_t *)
+ isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
+ update_action, NULL, sizeof(*event));
+ if (event == NULL)
+ FAIL(ISC_R_NOMEMORY);
+ event->zone = zone;
+ event->result = ISC_R_SUCCESS;
+
+ evclient = NULL;
+ ns_client_attach(client, &evclient);
+ INSIST(client->nupdates == 0);
+ client->nupdates++;
+ event->ev_arg = evclient;
+
+ dns_zone_gettask(zone, &zonetask);
+ isc_task_send(zonetask, ISC_EVENT_PTR(&event));
+
+ failure:
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+ return (result);
+}
+
+static void
+respond(ns_client_t *client, isc_result_t result) {
+ isc_result_t msg_result;
+
+ msg_result = dns_message_reply(client->message, true);
+ if (msg_result != ISC_R_SUCCESS)
+ goto msg_failure;
+ client->message->rcode = dns_result_torcode(result);
+
+ ns_client_send(client);
+ return;
+
+ msg_failure:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
+ ISC_LOG_ERROR,
+ "could not create update response message: %s",
+ isc_result_totext(msg_result));
+ ns_client_next(client, msg_result);
+}
+
+void
+ns_update_start(ns_client_t *client, isc_result_t sigresult) {
+ dns_message_t *request = client->message;
+ isc_result_t result;
+ dns_name_t *zonename;
+ dns_rdataset_t *zone_rdataset;
+ dns_zone_t *zone = NULL, *raw = NULL;
+
+ /*
+ * Interpret the zone section.
+ */
+ result = dns_message_firstname(request, DNS_SECTION_ZONE);
+ if (result != ISC_R_SUCCESS)
+ FAILC(DNS_R_FORMERR, "update zone section empty");
+
+ /*
+ * The zone section must contain exactly one "question", and
+ * it must be of type SOA.
+ */
+ zonename = NULL;
+ dns_message_currentname(request, DNS_SECTION_ZONE, &zonename);
+ zone_rdataset = ISC_LIST_HEAD(zonename->list);
+ if (zone_rdataset->type != dns_rdatatype_soa)
+ FAILC(DNS_R_FORMERR,
+ "update zone section contains non-SOA");
+ if (ISC_LIST_NEXT(zone_rdataset, link) != NULL)
+ FAILC(DNS_R_FORMERR,
+ "update zone section contains multiple RRs");
+
+ /* The zone section must have exactly one name. */
+ result = dns_message_nextname(request, DNS_SECTION_ZONE);
+ if (result != ISC_R_NOMORE)
+ FAILC(DNS_R_FORMERR,
+ "update zone section contains multiple RRs");
+
+ result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
+ &zone);
+ if (result != ISC_R_SUCCESS)
+ FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
+
+ /*
+ * If there is a raw (unsigned) zone associated with this
+ * zone then it processes the UPDATE request.
+ */
+ dns_zone_getraw(zone, &raw);
+ if (raw != NULL) {
+ dns_zone_detach(&zone);
+ dns_zone_attach(raw, &zone);
+ dns_zone_detach(&raw);
+ }
+
+ switch(dns_zone_gettype(zone)) {
+ case dns_zone_master:
+ case dns_zone_dlz:
+ /*
+ * We can now fail due to a bad signature as we now know
+ * that we are the master.
+ */
+ if (sigresult != ISC_R_SUCCESS)
+ FAIL(sigresult);
+ CHECK(send_update_event(client, zone));
+ break;
+ case dns_zone_slave:
+ CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone),
+ "update forwarding", zonename, true,
+ false));
+ CHECK(send_forward_event(client, zone));
+ break;
+ default:
+ FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
+ }
+ return;
+
+ failure:
+ if (result == DNS_R_REFUSED) {
+ INSIST(dns_zone_gettype(zone) == dns_zone_slave);
+ inc_stats(zone, dns_nsstatscounter_updaterej);
+ }
+ /*
+ * We failed without having sent an update event to the zone.
+ * We are still in the client task context, so we can
+ * simply give an error response without switching tasks.
+ */
+ respond(client, result);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+}
+
+/*%
+ * DS records are not allowed to exist without corresponding NS records,
+ * RFC 3658, 2.2 Protocol Change,
+ * "DS RRsets MUST NOT appear at non-delegation points or at a zone's apex".
+ */
+
+static isc_result_t
+remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) {
+ isc_result_t result;
+ bool ns_exists;
+ dns_difftuple_t *tupple;
+ dns_diff_t temp_diff;
+
+ dns_diff_init(diff->mctx, &temp_diff);
+
+ for (tupple = ISC_LIST_HEAD(diff->tuples);
+ tupple != NULL;
+ tupple = ISC_LIST_NEXT(tupple, link)) {
+ if (!((tupple->op == DNS_DIFFOP_DEL &&
+ tupple->rdata.type == dns_rdatatype_ns) ||
+ (tupple->op == DNS_DIFFOP_ADD &&
+ tupple->rdata.type == dns_rdatatype_ds)))
+ continue;
+ CHECK(rrset_exists(db, newver, &tupple->name,
+ dns_rdatatype_ns, 0, &ns_exists));
+ if (ns_exists &&
+ !dns_name_equal(&tupple->name, dns_db_origin(db)))
+ continue;
+ CHECK(delete_if(true_p, db, newver, &tupple->name,
+ dns_rdatatype_ds, 0, NULL, &temp_diff));
+ }
+ result = ISC_R_SUCCESS;
+
+ failure:
+ for (tupple = ISC_LIST_HEAD(temp_diff.tuples);
+ tupple != NULL;
+ tupple = ISC_LIST_HEAD(temp_diff.tuples)) {
+ ISC_LIST_UNLINK(temp_diff.tuples, tupple, link);
+ dns_diff_appendminimal(diff, &tupple);
+ }
+ return (result);
+}
+
+/*
+ * This implements the post load integrity checks for mx records.
+ */
+static isc_result_t
+check_mx(ns_client_t *client, dns_zone_t *zone,
+ dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff)
+{
+ char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char altbuf[DNS_NAME_FORMATSIZE];
+ dns_difftuple_t *t;
+ dns_fixedname_t fixed;
+ dns_name_t *foundname;
+ dns_rdata_mx_t mx;
+ dns_rdata_t rdata;
+ bool ok = true;
+ bool isaddress;
+ isc_result_t result;
+ struct in6_addr addr6;
+ struct in_addr addr;
+ unsigned int options;
+
+ foundname = dns_fixedname_initname(&fixed);
+ dns_rdata_init(&rdata);
+ options = dns_zone_getoptions(zone);
+
+ for (t = ISC_LIST_HEAD(diff->tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link)) {
+ if (t->op != DNS_DIFFOP_ADD ||
+ t->rdata.type != dns_rdatatype_mx)
+ continue;
+
+ result = dns_rdata_tostruct(&t->rdata, &mx, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ /*
+ * Check if we will error out if we attempt to reload the
+ * zone.
+ */
+ dns_name_format(&mx.mx, namebuf, sizeof(namebuf));
+ dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf));
+ isaddress = false;
+ if ((options & DNS_ZONEOPT_CHECKMX) != 0 &&
+ strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) {
+ if (tmp[strlen(tmp) - 1] == '.')
+ tmp[strlen(tmp) - 1] = '\0';
+ if (inet_aton(tmp, &addr) == 1 ||
+ inet_pton(AF_INET6, tmp, &addr6) == 1)
+ isaddress = true;
+ }
+
+ if (isaddress && (options & DNS_ZONEOPT_CHECKMXFAIL) != 0) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX: '%s': %s",
+ ownerbuf, namebuf,
+ dns_result_totext(DNS_R_MXISADDRESS));
+ ok = false;
+ } else if (isaddress) {
+ update_log(client, zone, ISC_LOG_WARNING,
+ "%s/MX: warning: '%s': %s",
+ ownerbuf, namebuf,
+ dns_result_totext(DNS_R_MXISADDRESS));
+ }
+
+ /*
+ * Check zone integrity checks.
+ */
+ if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0)
+ continue;
+ result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a,
+ 0, 0, NULL, foundname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ continue;
+
+ if (result == DNS_R_NXRRSET) {
+ result = dns_db_find(db, &mx.mx, newver,
+ dns_rdatatype_aaaa,
+ 0, 0, NULL, foundname,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ continue;
+ }
+
+ if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX '%s' has no address records "
+ "(A or AAAA)", ownerbuf, namebuf);
+ ok = false;
+ } else if (result == DNS_R_CNAME) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX '%s' is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ ok = false;
+ } else if (result == DNS_R_DNAME) {
+ dns_name_format(foundname, altbuf, sizeof altbuf);
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX '%s' is below a DNAME '%s' (illegal)",
+ ownerbuf, namebuf, altbuf);
+ ok = false;
+ }
+ }
+ return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED);
+}
+
+static isc_result_t
+rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ const dns_rdata_t *rdata, bool *flag)
+{
+ dns_rdataset_t rdataset;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ if (rdata->type == dns_rdatatype_nsec3)
+ CHECK(dns_db_findnsec3node(db, name, false, &node));
+ else
+ CHECK(dns_db_findnode(db, name, false, &node));
+ result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ *flag = false;
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t myrdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &myrdata);
+ if (!dns_rdata_casecompare(&myrdata, rdata))
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ *flag = true;
+ } else if (result == ISC_R_NOMORE) {
+ *flag = false;
+ result = ISC_R_SUCCESS;
+ }
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_result_t
+get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype,
+ unsigned int *iterationsp)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ unsigned int iterations = 0;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto try_private;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (nsec3param.iterations > iterations)
+ iterations = nsec3param.iterations;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ dns_rdataset_disassociate(&rdataset);
+
+ try_private:
+ if (privatetype == 0)
+ goto success;
+
+ result = dns_db_findrdataset(db, node, ver, privatetype,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t private = DNS_RDATA_INIT;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (nsec3param.iterations > iterations)
+ iterations = nsec3param.iterations;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ success:
+ *iterationsp = iterations;
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+/*
+ * Prevent the zone entering a inconsistent state where
+ * NSEC only DNSKEYs are present with NSEC3 chains.
+ */
+static isc_result_t
+check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ dns_difftuple_t *tuple;
+ bool nseconly = false, nsec3 = false;
+ isc_result_t result;
+ unsigned int iterations = 0, max;
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
+
+ /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ if (tuple->op != DNS_DIFFOP_ADD)
+ continue;
+
+ if (tuple->rdata.type == dns_rdatatype_dnskey) {
+ uint8_t alg;
+ alg = tuple->rdata.data[3];
+ if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
+ alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
+ nseconly = true;
+ break;
+ }
+ } else if (tuple->rdata.type == dns_rdatatype_nsec3param) {
+ nsec3 = true;
+ break;
+ }
+ }
+
+ /* Check existing DB for NSEC-only DNSKEY */
+ if (!nseconly) {
+ result = dns_nsec_nseconly(db, ver, &nseconly);
+
+ /*
+ * An NSEC3PARAM update can proceed without a DNSKEY (it
+ * will trigger a delayed change), so we can ignore
+ * ISC_R_NOTFOUND here.
+ */
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+
+ CHECK(result);
+ }
+
+ /* Check existing DB for NSEC3 */
+ if (!nsec3)
+ CHECK(dns_nsec3_activex(db, ver, false,
+ privatetype, &nsec3));
+
+ /* Refuse to allow NSEC3 with NSEC-only keys */
+ if (nseconly && nsec3) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "NSEC only DNSKEYs and NSEC3 chains not allowed");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+
+ /* Verify NSEC3 params */
+ CHECK(get_iterations(db, ver, privatetype, &iterations));
+ CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max));
+ if (max != 0 && iterations > max) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "too many NSEC3 iterations (%u) for "
+ "weakest DNSKEY (%u)", iterations, max);
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+
+ failure:
+ return (result);
+}
+
+/*
+ * Delay NSEC3PARAM changes as they need to be applied to the whole zone.
+ */
+static isc_result_t
+add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_difftuple_t *tuple, *newtuple = NULL, *next;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
+ dns_diff_t temp_diff;
+ dns_diffop_t op;
+ bool flag;
+ dns_name_t *name = dns_zone_getorigin(zone);
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
+ uint32_t ttl = 0;
+ bool ttl_good = false;
+
+ update_log(client, zone, ISC_LOG_DEBUG(3),
+ "checking for NSEC3PARAM changes");
+
+ dns_diff_init(diff->mctx, &temp_diff);
+
+ /*
+ * Extract NSEC3PARAM tuples from list.
+ */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = next) {
+
+ next = ISC_LIST_NEXT(tuple, link);
+
+ if (tuple->rdata.type != dns_rdatatype_nsec3param ||
+ !dns_name_equal(name, &tuple->name))
+ continue;
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
+ }
+
+ /*
+ * Extract TTL changes pairs, we don't need to convert these to
+ * delayed changes.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ if (tuple->op == DNS_DIFFOP_ADD) {
+ if (!ttl_good) {
+ /*
+ * Any adds here will contain the final
+ * NSEC3PARAM RRset TTL.
+ */
+ ttl = tuple->ttl;
+ ttl_good = true;
+ }
+ /*
+ * Walk the temp_diff list looking for the
+ * corresponding delete.
+ */
+ next = ISC_LIST_HEAD(temp_diff.tuples);
+ while (next != NULL) {
+ unsigned char *next_data = next->rdata.data;
+ unsigned char *tuple_data = tuple->rdata.data;
+ if (next->op == DNS_DIFFOP_DEL &&
+ next->rdata.length == tuple->rdata.length &&
+ !memcmp(next_data, tuple_data,
+ next->rdata.length)) {
+ ISC_LIST_UNLINK(temp_diff.tuples, next,
+ link);
+ ISC_LIST_APPEND(diff->tuples, next,
+ link);
+ break;
+ }
+ next = ISC_LIST_NEXT(next, link);
+ }
+ /*
+ * If we have not found a pair move onto the next
+ * tuple.
+ */
+ if (next == NULL) {
+ next = ISC_LIST_NEXT(tuple, link);
+ continue;
+ }
+ /*
+ * Find the next tuple to be processed before
+ * unlinking then complete moving the pair to 'diff'.
+ */
+ next = ISC_LIST_NEXT(tuple, link);
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+ } else
+ next = ISC_LIST_NEXT(tuple, link);
+ }
+
+ /*
+ * Preserve any ongoing changes from a BIND 9.6.x upgrade.
+ *
+ * Any NSEC3PARAM records with flags other than OPTOUT named
+ * in managing and should not be touched so revert such changes
+ * taking into account any TTL change of the NSEC3PARAM RRset.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ next = ISC_LIST_NEXT(tuple, link);
+ if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) {
+ /*
+ * If we havn't had any adds then the tuple->ttl must
+ * be the original ttl and should be used for any
+ * future changes.
+ */
+ if (!ttl_good) {
+ ttl = tuple->ttl;
+ ttl_good = true;
+ }
+ op = (tuple->op == DNS_DIFFOP_DEL) ?
+ DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
+ CHECK(dns_difftuple_create(diff->mctx, op, name,
+ ttl, &tuple->rdata,
+ &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ dns_diff_appendminimal(diff, &tuple);
+ }
+ }
+
+ /*
+ * We now have just the actual changes to the NSEC3PARAM RRset.
+ * Convert the adds to delayed adds and the deletions into delayed
+ * deletions.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ /*
+ * If we havn't had any adds then the tuple->ttl must be the
+ * original ttl and should be used for any future changes.
+ */
+ if (!ttl_good) {
+ ttl = tuple->ttl;
+ ttl_good = true;
+ }
+ if (tuple->op == DNS_DIFFOP_ADD) {
+ bool nseconly = false;
+
+ /*
+ * Look for any deletes which match this ADD ignoring
+ * flags. We don't need to explictly remove them as
+ * they will be removed a side effect of processing
+ * the add.
+ */
+ next = ISC_LIST_HEAD(temp_diff.tuples);
+ while (next != NULL) {
+ unsigned char *next_data = next->rdata.data;
+ unsigned char *tuple_data = tuple->rdata.data;
+ if (next->op != DNS_DIFFOP_DEL ||
+ next->rdata.length != tuple->rdata.length ||
+ next_data[0] != tuple_data[0] ||
+ next_data[2] != tuple_data[2] ||
+ next_data[3] != tuple_data[3] ||
+ memcmp(next_data + 4, tuple_data + 4,
+ tuple->rdata.length - 4)) {
+ next = ISC_LIST_NEXT(next, link);
+ continue;
+ }
+ ISC_LIST_UNLINK(temp_diff.tuples, next, link);
+ ISC_LIST_APPEND(diff->tuples, next, link);
+ next = ISC_LIST_HEAD(temp_diff.tuples);
+ }
+
+ /*
+ * Create a private-type record to signal that
+ * we want a delayed NSEC3 chain add/delete
+ */
+ dns_nsec3param_toprivate(&tuple->rdata, &rdata,
+ privatetype, buf, sizeof(buf));
+ buf[2] |= DNS_NSEC3FLAG_CREATE;
+
+ /*
+ * If the zone is not currently capable of
+ * supporting an NSEC3 chain, then we set the
+ * INITIAL flag to indicate that these parameters
+ * are to be used later.
+ */
+ result = dns_nsec_nseconly(db, ver, &nseconly);
+ if (result == ISC_R_NOTFOUND || nseconly)
+ buf[2] |= DNS_NSEC3FLAG_INITIAL;
+
+ /*
+ * See if this CREATE request already exists.
+ */
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+
+ if (!flag) {
+ CHECK(dns_difftuple_create(diff->mctx,
+ DNS_DIFFOP_ADD,
+ name, 0, &rdata,
+ &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ }
+
+ /*
+ * Remove any existing CREATE request to add an
+ * otherwise indentical chain with a reversed
+ * OPTOUT state.
+ */
+ buf[2] ^= DNS_NSEC3FLAG_OPTOUT;
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+
+ if (flag) {
+ CHECK(dns_difftuple_create(diff->mctx,
+ DNS_DIFFOP_DEL,
+ name, 0, &rdata,
+ &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ }
+
+ /*
+ * Find the next tuple to be processed and remove the
+ * temporary add record.
+ */
+ next = ISC_LIST_NEXT(tuple, link);
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
+ name, ttl, &tuple->rdata,
+ &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ dns_diff_appendminimal(diff, &tuple);
+ dns_rdata_reset(&rdata);
+ } else
+ next = ISC_LIST_NEXT(tuple, link);
+ }
+
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+
+ INSIST(ttl_good);
+
+ next = ISC_LIST_NEXT(tuple, link);
+ /*
+ * See if we already have a REMOVE request in progress.
+ */
+ dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype,
+ buf, sizeof(buf));
+
+ buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
+
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (!flag) {
+ buf[2] &= ~DNS_NSEC3FLAG_NONSEC;
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ }
+
+ if (!flag) {
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ name, 0, &rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ }
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
+ ttl, &tuple->rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ dns_diff_appendminimal(diff, &tuple);
+ dns_rdata_reset(&rdata);
+ }
+
+ result = ISC_R_SUCCESS;
+ failure:
+ dns_diff_clear(&temp_diff);
+ return (result);
+}
+
+static isc_result_t
+rollback_private(dns_db_t *db, dns_rdatatype_t privatetype,
+ dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ dns_diff_t temp_diff;
+ dns_diffop_t op;
+ dns_difftuple_t *tuple, *newtuple = NULL, *next;
+ dns_name_t *name = dns_db_origin(db);
+ isc_mem_t *mctx = diff->mctx;
+ isc_result_t result;
+
+ if (privatetype == 0)
+ return (ISC_R_SUCCESS);
+
+ dns_diff_init(mctx, &temp_diff);
+
+ /*
+ * Extract the changes to be rolled back.
+ */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL; tuple = next) {
+
+ next = ISC_LIST_NEXT(tuple, link);
+
+ if (tuple->rdata.type != privatetype ||
+ !dns_name_equal(name, &tuple->name))
+ continue;
+
+ /*
+ * Allow records which indicate that a zone has been
+ * signed with a DNSKEY to be removed.
+ */
+ if (tuple->op == DNS_DIFFOP_DEL &&
+ tuple->rdata.length == 5 &&
+ tuple->rdata.data[0] != 0 &&
+ tuple->rdata.data[4] != 0)
+ continue;
+
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ ISC_LIST_PREPEND(temp_diff.tuples, tuple, link);
+ }
+
+ /*
+ * Rollback the changes.
+ */
+ while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) {
+ op = (tuple->op == DNS_DIFFOP_DEL) ?
+ DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
+ CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl,
+ &tuple->rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff));
+ }
+ result = ISC_R_SUCCESS;
+
+ failure:
+ dns_diff_clear(&temp_diff);
+ return (result);
+}
+
+/*
+ * Add records to cause the delayed signing of the zone by added DNSKEY
+ * to remove the RRSIG records generated by a deleted DNSKEY.
+ */
+static isc_result_t
+add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
+ dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ dns_difftuple_t *tuple, *newtuple = NULL, *next;
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ bool flag;
+ isc_region_t r;
+ isc_result_t result = ISC_R_SUCCESS;
+ uint16_t keyid;
+ unsigned char buf[5];
+ dns_name_t *name = dns_db_origin(db);
+ dns_diff_t temp_diff;
+
+ dns_diff_init(diff->mctx, &temp_diff);
+
+ /*
+ * Extract the DNSKEY tuples from the list.
+ */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL; tuple = next) {
+
+ next = ISC_LIST_NEXT(tuple, link);
+
+ if (tuple->rdata.type != dns_rdatatype_dnskey)
+ continue;
+
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
+ }
+
+ /*
+ * Extract TTL changes pairs, we don't need signing records for these.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ if (tuple->op == DNS_DIFFOP_ADD) {
+ /*
+ * Walk the temp_diff list looking for the
+ * corresponding delete.
+ */
+ next = ISC_LIST_HEAD(temp_diff.tuples);
+ while (next != NULL) {
+ unsigned char *next_data = next->rdata.data;
+ unsigned char *tuple_data = tuple->rdata.data;
+ if (next->op == DNS_DIFFOP_DEL &&
+ dns_name_equal(&tuple->name, &next->name) &&
+ next->rdata.length == tuple->rdata.length &&
+ !memcmp(next_data, tuple_data,
+ next->rdata.length)) {
+ ISC_LIST_UNLINK(temp_diff.tuples, next,
+ link);
+ ISC_LIST_APPEND(diff->tuples, next,
+ link);
+ break;
+ }
+ next = ISC_LIST_NEXT(next, link);
+ }
+ /*
+ * If we have not found a pair move onto the next
+ * tuple.
+ */
+ if (next == NULL) {
+ next = ISC_LIST_NEXT(tuple, link);
+ continue;
+ }
+ /*
+ * Find the next tuple to be processed before
+ * unlinking then complete moving the pair to 'diff'.
+ */
+ next = ISC_LIST_NEXT(tuple, link);
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+ } else
+ next = ISC_LIST_NEXT(tuple, link);
+ }
+
+ /*
+ * Process the remaining DNSKEY entries.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_HEAD(temp_diff.tuples)) {
+
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+
+ result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if ((dnskey.flags &
+ (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
+ != DNS_KEYOWNER_ZONE)
+ continue;
+
+ dns_rdata_toregion(&tuple->rdata, &r);
+
+ keyid = dst_region_computeid(&r, dnskey.algorithm);
+
+ buf[0] = dnskey.algorithm;
+ buf[1] = (keyid & 0xff00) >> 8;
+ buf[2] = (keyid & 0xff);
+ buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
+ buf[4] = 0;
+ rdata.data = buf;
+ rdata.length = sizeof(buf);
+ rdata.type = privatetype;
+ rdata.rdclass = tuple->rdata.rdclass;
+
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (flag)
+ continue;
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ name, 0, &rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ INSIST(newtuple == NULL);
+ /*
+ * Remove any record which says this operation has already
+ * completed.
+ */
+ buf[4] = 1;
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (flag) {
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
+ name, 0, &rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ INSIST(newtuple == NULL);
+ }
+ }
+
+ failure:
+ dns_diff_clear(&temp_diff);
+ return (result);
+}
+
+static bool
+isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) {
+ isc_result_t result;
+ bool build_nsec, build_nsec3;
+
+ if (dns_db_issecure(db))
+ return (true);
+
+ result = dns_private_chains(db, ver, privatetype,
+ &build_nsec, &build_nsec3);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ return (build_nsec || build_nsec3);
+}
+
+static void
+update_action(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ dns_zone_t *zone = uev->zone;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *oldver = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff; /* Pending updates. */
+ dns_diff_t temp; /* Pending RR existence assertions. */
+ bool soa_serial_changed = false;
+ isc_mem_t *mctx = client->mctx;
+ dns_rdatatype_t covers;
+ dns_message_t *request = client->message;
+ dns_rdataclass_t zoneclass;
+ dns_name_t *zonename;
+ dns_ssutable_t *ssutable = NULL;
+ dns_fixedname_t tmpnamefixed;
+ dns_name_t *tmpname = NULL;
+ unsigned int options, options2;
+ dns_difftuple_t *tuple;
+ dns_rdata_dnskey_t dnskey;
+ bool had_dnskey;
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
+ dns_ttl_t maxttl = 0;
+ uint32_t maxrecords;
+ uint64_t records;
+
+ INSIST(event->ev_type == DNS_EVENT_UPDATE);
+
+ dns_diff_init(mctx, &diff);
+ dns_diff_init(mctx, &temp);
+
+ CHECK(dns_zone_getdb(zone, &db));
+ zonename = dns_db_origin(db);
+ zoneclass = dns_db_class(db);
+ dns_zone_getssutable(zone, &ssutable);
+
+ /*
+ * Update message processing can leak record existance information
+ * so check that we are allowed to query this zone. Additionally
+ * if we would refuse all updates for this zone we bail out here.
+ */
+ CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename,
+ dns_zone_getupdateacl(zone), ssutable));
+
+ /*
+ * Get old and new versions now that queryacl has been checked.
+ */
+ dns_db_currentversion(db, &oldver);
+ CHECK(dns_db_newversion(db, &ver));
+
+ /*
+ * Check prerequisites.
+ */
+
+ for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+ bool flag;
+
+ get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,
+ &name, &rdata, &covers, &ttl, &update_class);
+
+ if (ttl != 0)
+ PREREQFAILC(DNS_R_FORMERR,
+ "prerequisite TTL is not zero");
+
+ if (! dns_name_issubdomain(name, zonename))
+ PREREQFAILN(DNS_R_NOTZONE, name,
+ "prerequisite name is out of zone");
+
+ if (update_class == dns_rdataclass_any) {
+ if (rdata.length != 0)
+ PREREQFAILC(DNS_R_FORMERR,
+ "class ANY prerequisite "
+ "RDATA is not empty");
+ if (rdata.type == dns_rdatatype_any) {
+ CHECK(name_exists(db, ver, name, &flag));
+ if (! flag) {
+ PREREQFAILN(DNS_R_NXDOMAIN, name,
+ "'name in use' "
+ "prerequisite not "
+ "satisfied");
+ }
+ } else {
+ CHECK(rrset_exists(db, ver, name,
+ rdata.type, covers, &flag));
+ if (! flag) {
+ /* RRset does not exist. */
+ PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type,
+ "'rrset exists (value independent)' "
+ "prerequisite not satisfied");
+ }
+ }
+ } else if (update_class == dns_rdataclass_none) {
+ if (rdata.length != 0)
+ PREREQFAILC(DNS_R_FORMERR,
+ "class NONE prerequisite "
+ "RDATA is not empty");
+ if (rdata.type == dns_rdatatype_any) {
+ CHECK(name_exists(db, ver, name, &flag));
+ if (flag) {
+ PREREQFAILN(DNS_R_YXDOMAIN, name,
+ "'name not in use' "
+ "prerequisite not "
+ "satisfied");
+ }
+ } else {
+ CHECK(rrset_exists(db, ver, name,
+ rdata.type, covers, &flag));
+ if (flag) {
+ /* RRset exists. */
+ PREREQFAILNT(DNS_R_YXRRSET, name,
+ rdata.type,
+ "'rrset does not exist' "
+ "prerequisite not "
+ "satisfied");
+ }
+ }
+ } else if (update_class == zoneclass) {
+ /* "temp<rr.name, rr.type> += rr;" */
+ result = temp_append(&temp, name, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "temp entry creation failed: %s",
+ dns_result_totext(result));
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ } else {
+ PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite");
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ FAIL(result);
+
+ /*
+ * Perform the final check of the "rrset exists (value dependent)"
+ * prerequisites.
+ */
+ if (ISC_LIST_HEAD(temp.tuples) != NULL) {
+ dns_rdatatype_t type;
+
+ /*
+ * Sort the prerequisite records by owner name,
+ * type, and rdata.
+ */
+ result = dns_diff_sort(&temp, temp_order);
+ if (result != ISC_R_SUCCESS)
+ FAILC(result, "'RRset exists (value dependent)' "
+ "prerequisite not satisfied");
+
+ tmpname = dns_fixedname_initname(&tmpnamefixed);
+ result = temp_check(mctx, &temp, db, ver, tmpname, &type);
+ if (result != ISC_R_SUCCESS)
+ FAILNT(result, tmpname, type,
+ "'RRset exists (value dependent)' "
+ "prerequisite not satisfied");
+ }
+
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "prerequisites are OK");
+
+ /*
+ * Check Requestor's Permissions. It seems a bit silly to do this
+ * only after prerequisite testing, but that is what RFC2136 says.
+ */
+ if (ssutable == NULL)
+ CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone),
+ "update", zonename, false, false));
+ else if (client->signer == NULL && !TCPCLIENT(client))
+ CHECK(checkupdateacl(client, NULL, "update", zonename,
+ false, true));
+
+ if (dns_zone_getupdatedisabled(zone))
+ FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled "
+ "because the zone is frozen. Use "
+ "'rndc thaw' to re-enable updates.");
+
+ /*
+ * Perform the Update Section Prescan.
+ */
+
+ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_UPDATE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
+ &name, &rdata, &covers, &ttl, &update_class);
+
+ if (! dns_name_issubdomain(name, zonename))
+ FAILC(DNS_R_NOTZONE,
+ "update RR is outside zone");
+ if (update_class == zoneclass) {
+ /*
+ * Check for meta-RRs. The RFC2136 pseudocode says
+ * check for ANY|AXFR|MAILA|MAILB, but the text adds
+ * "or any other QUERY metatype"
+ */
+ if (dns_rdatatype_ismeta(rdata.type)) {
+ FAILC(DNS_R_FORMERR,
+ "meta-RR in update");
+ }
+ result = dns_zone_checknames(zone, name, &rdata);
+ if (result != ISC_R_SUCCESS)
+ FAIL(DNS_R_REFUSED);
+ } else if (update_class == dns_rdataclass_any) {
+ if (ttl != 0 || rdata.length != 0 ||
+ (dns_rdatatype_ismeta(rdata.type) &&
+ rdata.type != dns_rdatatype_any))
+ FAILC(DNS_R_FORMERR,
+ "meta-RR in update");
+ } else if (update_class == dns_rdataclass_none) {
+ if (ttl != 0 ||
+ dns_rdatatype_ismeta(rdata.type))
+ FAILC(DNS_R_FORMERR,
+ "meta-RR in update");
+ } else {
+ update_log(client, zone, ISC_LOG_WARNING,
+ "update RR has incorrect class %d",
+ update_class);
+ FAIL(DNS_R_FORMERR);
+ }
+
+ /*
+ * draft-ietf-dnsind-simple-secure-update-01 says
+ * "Unlike traditional dynamic update, the client
+ * is forbidden from updating NSEC records."
+ */
+ if (rdata.type == dns_rdatatype_nsec3) {
+ FAILC(DNS_R_REFUSED,
+ "explicit NSEC3 updates are not allowed "
+ "in secure zones");
+ } else if (rdata.type == dns_rdatatype_nsec) {
+ FAILC(DNS_R_REFUSED,
+ "explicit NSEC updates are not allowed "
+ "in secure zones");
+ } else if (rdata.type == dns_rdatatype_rrsig &&
+ !dns_name_equal(name, zonename)) {
+ FAILC(DNS_R_REFUSED,
+ "explicit RRSIG updates are currently "
+ "not supported in secure zones except "
+ "at the apex");
+ }
+
+ if (ssutable != NULL) {
+ isc_netaddr_t netaddr;
+ dst_key_t *tsigkey = NULL;
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+ if (client->message->tsigkey != NULL)
+ tsigkey = client->message->tsigkey->key;
+
+ if (rdata.type != dns_rdatatype_any) {
+ if (!dns_ssutable_checkrules2
+ (ssutable, client->signer, name, &netaddr,
+ TCPCLIENT(client),
+ &ns_g_server->aclenv,
+ rdata.type, tsigkey))
+ {
+ FAILC(DNS_R_REFUSED,
+ "rejected by secure update");
+ }
+ } else {
+ if (!ssu_checkall(db, ver, name, ssutable,
+ client->signer,
+ &netaddr,
+ TCPCLIENT(client),
+ tsigkey))
+ {
+ FAILC(DNS_R_REFUSED,
+ "rejected by secure update");
+ }
+ }
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ FAIL(result);
+
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "update section prescan OK");
+
+ /*
+ * Process the Update Section.
+ */
+
+ options = dns_zone_getoptions(zone);
+ options2 = dns_zone_getoptions2(zone);
+ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_UPDATE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+ bool flag;
+
+ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
+ &name, &rdata, &covers, &ttl, &update_class);
+
+ if (update_class == zoneclass) {
+
+ /*
+ * RFC1123 doesn't allow MF and MD in master zones.
+ */
+ if (rdata.type == dns_rdatatype_md ||
+ rdata.type == dns_rdatatype_mf) {
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_rdatatype_format(rdata.type, typebuf,
+ sizeof(typebuf));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "attempt to add %s ignored",
+ typebuf);
+ continue;
+ }
+ if ((rdata.type == dns_rdatatype_ns ||
+ rdata.type == dns_rdatatype_dname) &&
+ dns_name_iswildcard(name)) {
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_rdatatype_format(rdata.type, typebuf,
+ sizeof(typebuf));
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add wildcard %s record "
+ "ignored", typebuf);
+ continue;
+ }
+ if (rdata.type == dns_rdatatype_cname) {
+ CHECK(cname_incompatible_rrset_exists(db, ver,
+ name,
+ &flag));
+ if (flag) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add CNAME "
+ "alongside non-CNAME "
+ "ignored");
+ continue;
+ }
+ } else {
+ CHECK(rrset_exists(db, ver, name,
+ dns_rdatatype_cname, 0,
+ &flag));
+ if (flag &&
+ ! dns_rdatatype_isdnssec(rdata.type))
+ {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add non-CNAME "
+ "alongside CNAME ignored");
+ continue;
+ }
+ }
+ if (rdata.type == dns_rdatatype_soa) {
+ bool ok;
+ CHECK(rrset_exists(db, ver, name,
+ dns_rdatatype_soa, 0,
+ &flag));
+ if (! flag) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to create 2nd "
+ "SOA ignored");
+ continue;
+ }
+ CHECK(check_soa_increment(db, ver, &rdata,
+ &ok));
+ if (! ok) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "SOA update failed to "
+ "increment serial, "
+ "ignoring it");
+ continue;
+ }
+ soa_serial_changed = true;
+ }
+
+ if (rdata.type == privatetype) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "attempt to add a private type "
+ "(%u) record rejected internal "
+ "use only", privatetype);
+ continue;
+ }
+
+ if (rdata.type == dns_rdatatype_nsec3param) {
+ /*
+ * Ignore attempts to add NSEC3PARAM records
+ * with any flags other than OPTOUT.
+ */
+ if ((rdata.data[1] &
+ ~DNS_NSEC3FLAG_OPTOUT) != 0)
+ {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add NSEC3PARAM "
+ "record with non OPTOUT "
+ "flag");
+ continue;
+ }
+ }
+
+ if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 &&
+ dns_name_internalwildcard(name)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "warning: ownername '%s' contains "
+ "a non-terminal wildcard", namestr);
+ }
+
+ if ((options2 & DNS_ZONEOPT2_CHECKTTL) != 0) {
+ maxttl = dns_zone_getmaxttl(zone);
+ if (ttl > maxttl) {
+ ttl = maxttl;
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "reducing TTL to the "
+ "configured max-zone-ttl %d",
+ maxttl);
+ }
+ }
+
+ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ char rdstr[2048];
+ isc_buffer_t buf;
+ int len = 0;
+ const char *truncated = "";
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_rdatatype_format(rdata.type, typestr,
+ sizeof(typestr));
+ isc_buffer_init(&buf, rdstr, sizeof(rdstr));
+ result = dns_rdata_totext(&rdata, NULL, &buf);
+ if (result == ISC_R_NOSPACE) {
+ len = (int)isc_buffer_usedlength(&buf);
+ truncated = " [TRUNCATED]";
+ } else if (result != ISC_R_SUCCESS) {
+ snprintf(rdstr, sizeof(rdstr), "[dns_"
+ "rdata_totext failed: %s]",
+ dns_result_totext(result));
+ len = strlen(rdstr);
+ } else
+ len = (int)isc_buffer_usedlength(&buf);
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "adding an RR at '%s' %s %.*s%s",
+ namestr, typestr, len, rdstr,
+ truncated);
+ }
+
+ /* Prepare the affected RRset for the addition. */
+ {
+ add_rr_prepare_ctx_t ctx;
+ ctx.db = db;
+ ctx.ver = ver;
+ ctx.diff = &diff;
+ ctx.name = name;
+ ctx.oldname = name;
+ ctx.update_rr = &rdata;
+ ctx.update_rr_ttl = ttl;
+ ctx.ignore_add = false;
+ dns_diff_init(mctx, &ctx.del_diff);
+ dns_diff_init(mctx, &ctx.add_diff);
+ CHECK(foreach_rr(db, ver, name, rdata.type,
+ covers, add_rr_prepare_action,
+ &ctx));
+
+ if (ctx.ignore_add) {
+ dns_diff_clear(&ctx.del_diff);
+ dns_diff_clear(&ctx.add_diff);
+ } else {
+ result = do_diff(&ctx.del_diff, db, ver,
+ &diff);
+ if (result == ISC_R_SUCCESS) {
+ result = do_diff(&ctx.add_diff,
+ db, ver,
+ &diff);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_diff_clear(&ctx.del_diff);
+ dns_diff_clear(&ctx.add_diff);
+ goto failure;
+ }
+ CHECK(update_one_rr(db, ver, &diff,
+ DNS_DIFFOP_ADD,
+ name, ttl, &rdata));
+ }
+ }
+ } else if (update_class == dns_rdataclass_any) {
+ if (rdata.type == dns_rdatatype_any) {
+ if (isc_log_wouldlog(ns_g_lctx,
+ LOGLEVEL_PROTOCOL))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "delete all rrsets from "
+ "name '%s'", namestr);
+ }
+ if (dns_name_equal(name, zonename)) {
+ CHECK(delete_if(type_not_soa_nor_ns_p,
+ db, ver, name,
+ dns_rdatatype_any, 0,
+ &rdata, &diff));
+ } else {
+ CHECK(delete_if(type_not_dnssec,
+ db, ver, name,
+ dns_rdatatype_any, 0,
+ &rdata, &diff));
+ }
+ } else if (dns_name_equal(name, zonename) &&
+ (rdata.type == dns_rdatatype_soa ||
+ rdata.type == dns_rdatatype_ns)) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "attempt to delete all SOA "
+ "or NS records ignored");
+ continue;
+ } else {
+ if (isc_log_wouldlog(ns_g_lctx,
+ LOGLEVEL_PROTOCOL))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ dns_rdatatype_format(rdata.type,
+ typestr,
+ sizeof(typestr));
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "deleting rrset at '%s' %s",
+ namestr, typestr);
+ }
+ CHECK(delete_if(true_p, db, ver, name,
+ rdata.type, covers, &rdata,
+ &diff));
+ }
+ } else if (update_class == dns_rdataclass_none) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+
+ /*
+ * The (name == zonename) condition appears in
+ * RFC2136 3.4.2.4 but is missing from the pseudocode.
+ */
+ if (dns_name_equal(name, zonename)) {
+ if (rdata.type == dns_rdatatype_soa) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to delete SOA "
+ "ignored");
+ continue;
+ }
+ if (rdata.type == dns_rdatatype_ns) {
+ int count;
+ CHECK(rr_count(db, ver, name,
+ dns_rdatatype_ns,
+ 0, &count));
+ if (count == 1) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to "
+ "delete last "
+ "NS ignored");
+ continue;
+ }
+ }
+ }
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_rdatatype_format(rdata.type, typestr,
+ sizeof(typestr));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "deleting an RR at %s %s", namestr, typestr);
+ CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type,
+ covers, &rdata, &diff));
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ FAIL(result);
+
+ /*
+ * Check that any changes to DNSKEY/NSEC3PARAM records make sense.
+ * If they don't then back out all changes to DNSKEY/NSEC3PARAM
+ * records.
+ */
+ if (! ISC_LIST_EMPTY(diff.tuples))
+ CHECK(check_dnssec(client, zone, db, ver, &diff));
+
+ if (! ISC_LIST_EMPTY(diff.tuples)) {
+ unsigned int errors = 0;
+ CHECK(dns_zone_nscheck(zone, db, ver, &errors));
+ if (errors != 0) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update rejected: post update name server "
+ "sanity check failed");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+ }
+ if (! ISC_LIST_EMPTY(diff.tuples)) {
+ result = dns_zone_cdscheck(zone, db, ver);
+ if (result == DNS_R_BADCDS || result == DNS_R_BADCDNSKEY) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update rejected: bad %s RRset",
+ result == DNS_R_BADCDS ? "CDS" : "CDNSKEY");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ }
+
+ /*
+ * If any changes were made, increment the SOA serial number,
+ * update RRSIGs and NSECs (if zone is secure), and write the update
+ * to the journal.
+ */
+ if (! ISC_LIST_EMPTY(diff.tuples)) {
+ char *journalfile;
+ dns_journal_t *journal;
+ bool has_dnskey;
+
+ /*
+ * Increment the SOA serial, but only if it was not
+ * changed as a result of an update operation.
+ */
+ if (! soa_serial_changed) {
+ CHECK(update_soa_serial(db, ver, &diff, mctx,
+ dns_zone_getserialupdatemethod(zone)));
+ }
+
+ CHECK(check_mx(client, zone, db, ver, &diff));
+
+ CHECK(remove_orphaned_ds(db, ver, &diff));
+
+ CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey,
+ 0, &has_dnskey));
+
+#define ALLOW_SECURE_TO_INSECURE(zone) \
+ ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0)
+
+ CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey,
+ 0, &had_dnskey));
+ if (!ALLOW_SECURE_TO_INSECURE(zone)) {
+ if (had_dnskey && !has_dnskey) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update rejected: all DNSKEY "
+ "records removed and "
+ "'dnssec-secure-to-insecure' "
+ "not set");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+ }
+
+ CHECK(rollback_private(db, privatetype, ver, &diff));
+
+ CHECK(add_signing_records(db, privatetype, ver, &diff));
+
+ CHECK(add_nsec3param_records(client, zone, db, ver, &diff));
+
+ if (had_dnskey && !has_dnskey) {
+ /*
+ * We are transitioning from secure to insecure.
+ * Cause all NSEC3 chains to be deleted. When the
+ * the last signature for the DNSKEY records are
+ * remove any NSEC chain present will also be removed.
+ */
+ CHECK(dns_nsec3param_deletechains(db, ver, zone,
+ true, &diff));
+ } else if (has_dnskey && isdnssec(db, ver, privatetype)) {
+ uint32_t interval;
+ dns_update_log_t log;
+
+ interval = dns_zone_getsigvalidityinterval(zone);
+ log.func = update_log_cb;
+ log.arg = client;
+ result = dns_update_signatures(&log, zone, db, oldver,
+ ver, &diff, interval);
+
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone,
+ ISC_LOG_ERROR,
+ "RRSIG/NSEC/NSEC3 update failed: %s",
+ isc_result_totext(result));
+ goto failure;
+ }
+ }
+
+ maxrecords = dns_zone_getmaxrecords(zone);
+ if (maxrecords != 0U) {
+ result = dns_db_getsize(db, ver, &records, NULL);
+ if (result == ISC_R_SUCCESS && records > maxrecords) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "records in zone (%"
+ PRIu64
+ ") exceeds max-records (%u)",
+ records, maxrecords);
+ result = DNS_R_TOOMANYRECORDS;
+ goto failure;
+ }
+ }
+
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL) {
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "writing journal %s", journalfile);
+
+ journal = NULL;
+ result = dns_journal_open(mctx, journalfile,
+ DNS_JOURNAL_CREATE, &journal);
+ if (result != ISC_R_SUCCESS)
+ FAILS(result, "journal open failed");
+
+ result = dns_journal_write_transaction(journal, &diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_journal_destroy(&journal);
+ FAILS(result, "journal write failed");
+ }
+
+ dns_journal_destroy(&journal);
+ }
+
+ /*
+ * XXXRTH Just a note that this committing code will have
+ * to change to handle databases that need two-phase
+ * commit, but this isn't a priority.
+ */
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "committing update transaction");
+
+ dns_db_closeversion(db, &ver, true);
+
+ /*
+ * Mark the zone as dirty so that it will be written to disk.
+ */
+ dns_zone_markdirty(zone);
+
+ /*
+ * Notify slaves of the change we just made.
+ */
+ dns_zone_notify(zone);
+
+ /*
+ * Cause the zone to be signed with the key that we
+ * have just added or have the corresponding signatures
+ * deleted.
+ *
+ * Note: we are already committed to this course of action.
+ */
+ for (tuple = ISC_LIST_HEAD(diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ isc_region_t r;
+ dns_secalg_t algorithm;
+ uint16_t keyid;
+
+ if (tuple->rdata.type != dns_rdatatype_dnskey)
+ continue;
+
+ dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
+ if ((dnskey.flags &
+ (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
+ != DNS_KEYOWNER_ZONE)
+ continue;
+
+ dns_rdata_toregion(&tuple->rdata, &r);
+ algorithm = dnskey.algorithm;
+ keyid = dst_region_computeid(&r, algorithm);
+
+ result = dns_zone_signwithkey(zone, algorithm, keyid,
+ (tuple->op == DNS_DIFFOP_DEL));
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "dns_zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ }
+
+ /*
+ * Cause the zone to add/delete NSEC3 chains for the
+ * deferred NSEC3PARAM changes.
+ *
+ * Note: we are already committed to this course of action.
+ */
+ for (tuple = ISC_LIST_HEAD(diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3param_t nsec3param;
+
+ if (tuple->rdata.type != privatetype ||
+ tuple->op != DNS_DIFFOP_ADD)
+ continue;
+
+ if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ if (nsec3param.flags == 0)
+ continue;
+
+ result = dns_zone_addnsec3chain(zone, &nsec3param);
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "dns_zone_addnsec3chain failed: %s",
+ dns_result_totext(result));
+ }
+ }
+ } else {
+ update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
+ dns_db_closeversion(db, &ver, true);
+ }
+ result = ISC_R_SUCCESS;
+ goto common;
+
+ failure:
+ /*
+ * The reason for failure should have been logged at this point.
+ */
+ if (ver != NULL) {
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "rolling back");
+ dns_db_closeversion(db, &ver, false);
+ }
+
+ common:
+ dns_diff_clear(&temp);
+ dns_diff_clear(&diff);
+
+ if (oldver != NULL)
+ dns_db_closeversion(db, &oldver, false);
+
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ if (ssutable != NULL)
+ dns_ssutable_detach(&ssutable);
+
+ isc_task_detach(&task);
+ uev->result = result;
+ if (zone != NULL)
+ INSIST(uev->zone == zone); /* we use this later */
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = updatedone_action;
+ isc_task_send(client->task, &event);
+
+ INSIST(ver == NULL);
+ INSIST(event == NULL);
+}
+
+static void
+updatedone_action(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ ns_client_t *client = (ns_client_t *) event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == DNS_EVENT_UPDATEDONE);
+ INSIST(task == client->task);
+
+ INSIST(client->nupdates > 0);
+ switch (uev->result) {
+ case ISC_R_SUCCESS:
+ inc_stats(uev->zone, dns_nsstatscounter_updatedone);
+ break;
+ case DNS_R_REFUSED:
+ inc_stats(uev->zone, dns_nsstatscounter_updaterej);
+ break;
+ default:
+ inc_stats(uev->zone, dns_nsstatscounter_updatefail);
+ break;
+ }
+ if (uev->zone != NULL)
+ dns_zone_detach(&uev->zone);
+ client->nupdates--;
+ respond(client, uev->result);
+ isc_event_free(&event);
+ ns_client_detach(&client);
+}
+
+/*%
+ * Update forwarding support.
+ */
+
+static void
+forward_fail(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(client->nupdates > 0);
+ client->nupdates--;
+ respond(client, DNS_R_SERVFAIL);
+ isc_event_free(&event);
+ ns_client_detach(&client);
+}
+
+
+static void
+forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
+ update_event_t *uev = arg;
+ ns_client_t *client = uev->ev_arg;
+ dns_zone_t *zone = uev->zone;
+
+ if (result != ISC_R_SUCCESS) {
+ INSIST(answer == NULL);
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = forward_fail;
+ inc_stats(zone, dns_nsstatscounter_updatefwdfail);
+ } else {
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = forward_done;
+ uev->answer = answer;
+ inc_stats(zone, dns_nsstatscounter_updaterespfwd);
+ }
+ isc_task_send(client->task, ISC_EVENT_PTR(&uev));
+ dns_zone_detach(&zone);
+}
+
+static void
+forward_done(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(client->nupdates > 0);
+ client->nupdates--;
+ ns_client_sendraw(client, uev->answer);
+ dns_message_destroy(&uev->answer);
+ isc_event_free(&event);
+ ns_client_detach(&client);
+}
+
+static void
+forward_action(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ dns_zone_t *zone = uev->zone;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+ isc_result_t result;
+
+ result = dns_zone_forwardupdate(zone, client->message,
+ forward_callback, event);
+ if (result != ISC_R_SUCCESS) {
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = forward_fail;
+ isc_task_send(client->task, &event);
+ inc_stats(zone, dns_nsstatscounter_updatefwdfail);
+ dns_zone_detach(&zone);
+ } else
+ inc_stats(zone, dns_nsstatscounter_updatereqfwd);
+ isc_task_detach(&task);
+}
+
+static isc_result_t
+send_forward_event(ns_client_t *client, dns_zone_t *zone) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ isc_result_t result = ISC_R_SUCCESS;
+ update_event_t *event = NULL;
+ isc_task_t *zonetask = NULL;
+ ns_client_t *evclient;
+
+ /*
+ * This may take some time so replace this client.
+ */
+ if (!client->mortal && (client->attributes & NS_CLIENTATTR_TCP) == 0)
+ CHECK(ns_client_replace(client));
+
+ event = (update_event_t *)
+ isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
+ forward_action, NULL, sizeof(*event));
+ if (event == NULL)
+ FAIL(ISC_R_NOMEMORY);
+ event->zone = zone;
+ event->result = ISC_R_SUCCESS;
+
+ evclient = NULL;
+ ns_client_attach(client, &evclient);
+ INSIST(client->nupdates == 0);
+ client->nupdates++;
+ event->ev_arg = evclient;
+
+ dns_name_format(dns_zone_getorigin(zone), namebuf,
+ sizeof(namebuf));
+ dns_rdataclass_format(dns_zone_getclass(zone), classbuf,
+ sizeof(classbuf));
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
+ LOGLEVEL_PROTOCOL, "forwarding update for zone '%s/%s'",
+ namebuf, classbuf);
+
+ dns_zone_gettask(zone, &zonetask);
+ isc_task_send(zonetask, ISC_EVENT_PTR(&event));
+
+ failure:
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+ return (result);
+}
diff --git a/bin/named/win32/dlz_dlopen_driver.c b/bin/named/win32/dlz_dlopen_driver.c
new file mode 100644
index 0000000..bb0eedd
--- /dev/null
+++ b/bin/named/win32/dlz_dlopen_driver.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <windows.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/dlz_dlopen.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/dlz_dlopen_driver.h>
+
+#ifdef ISC_DLZ_DLOPEN
+static dns_sdlzimplementation_t *dlz_dlopen = NULL;
+
+
+typedef struct dlopen_data {
+ isc_mem_t *mctx;
+ char *dl_path;
+ char *dlzname;
+ HMODULE 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 == false) \
+ LOCK(&cd->lock); \
+ } while (0)
+
+#define MAYBE_UNLOCK(cd) \
+ do { \
+ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
+ cd->in_configure == false) \
+ 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 = GetProcAddress(cd->dl_handle, symbol);
+ if (ptr == NULL && mandatory) {
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen: library '%s' is missing "
+ "required symbol '%s'", cd->dl_path, symbol);
+ }
+ return (ptr);
+}
+
+/*
+ * 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;
+ bool triedload = false;
+
+ 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(0, 0, &mctx);
+
+ cd = isc_mem_get(mctx, sizeof(*cd));
+ if (cd == NULL) {
+ isc_mem_destroy(&mctx);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(cd, 0, sizeof(*cd));
+
+ cd->mctx = mctx;
+
+ cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
+ if (cd->dl_path == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failed;
+ }
+
+ cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
+ if (cd->dlzname == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failed;
+ }
+
+ triedload = true;
+
+ /* Initialize the lock */
+ result = isc_mutex_init(&cd->lock);
+ if (result != ISC_R_SUCCESS)
+ goto failed;
+
+ /* Open the library */
+ cd->dl_handle = LoadLibraryA(cd->dl_path);
+ if (cd->dl_handle == NULL) {
+ unsigned int error = GetLastError();
+
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen failed to open library '%s' - %u",
+ cd->dl_path, error);
+ result = ISC_R_FAILURE;
+ goto cleanup_lock;
+ }
+
+ /* 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 cleanup_lock;
+ }
+
+ 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);
+
+ /* 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 cleanup_lock;
+ }
+
+ /*
+ * 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 cleanup_lock;
+
+ *dbdata = cd;
+
+ return (ISC_R_SUCCESS);
+
+cleanup_lock:
+ DESTROYLOCK(&cd->lock);
+failed:
+ dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
+ if (cd->dl_path)
+ isc_mem_free(mctx, cd->dl_path);
+ if (cd->dlzname)
+ isc_mem_free(mctx, cd->dlzname);
+ if (triedload)
+ (void) isc_mutex_destroy(&cd->lock);
+ if (cd->dl_handle)
+ FreeLibrary(cd->dl_handle);
+ isc_mem_put(mctx, cd, sizeof(*cd));
+ isc_mem_destroy(&mctx);
+ 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;
+ isc_mem_t *mctx;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_destroy) {
+ MAYBE_LOCK(cd);
+ cd->dlz_destroy(cd->dbdata);
+ MAYBE_UNLOCK(cd);
+ }
+
+ if (cd->dl_path)
+ isc_mem_free(cd->mctx, cd->dl_path);
+ if (cd->dlzname)
+ isc_mem_free(cd->mctx, cd->dlzname);
+
+ if (cd->dl_handle)
+ FreeLibrary(cd->dl_handle);
+
+ DESTROYLOCK(&cd->lock);
+
+ mctx = cd->mctx;
+ isc_mem_put(mctx, cd, sizeof(*cd));
+ isc_mem_destroy(&mctx);
+}
+
+/*
+ * 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
+};
+#endif
+
+/*
+ * Register driver with BIND
+ */
+isc_result_t
+dlz_dlopen_init(isc_mem_t *mctx) {
+#ifndef ISC_DLZ_DLOPEN
+ UNUSED(mctx);
+ return (ISC_R_NOTIMPLEMENTED);
+#else
+ 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(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+ return (result);
+#endif
+}
+
+
+/*
+ * Unregister the driver
+ */
+void
+dlz_dlopen_clear(void) {
+#ifdef ISC_DLZ_DLOPEN
+ dlopen_log(2, "Unregistering DLZ_dlopen driver");
+ if (dlz_dlopen != NULL)
+ dns_sdlzunregister(&dlz_dlopen);
+#endif
+}
diff --git a/bin/named/win32/include/named/ntservice.h b/bin/named/win32/include/named/ntservice.h
new file mode 100644
index 0000000..38732fb
--- /dev/null
+++ b/bin/named/win32/include/named/ntservice.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef NTSERVICE_H
+#define NTSERVICE_H
+
+#include <winsvc.h>
+
+#define BIND_DISPLAY_NAME "ISC BIND"
+#define BIND_SERVICE_NAME "named"
+
+void
+ntservice_init();
+void UpdateSCM(DWORD);
+void ServiceControl(DWORD dwCtrlCode);
+void
+ntservice_shutdown();
+BOOL ntservice_isservice();
+#endif
diff --git a/bin/named/win32/include/named/os.h b/bin/named/win32/include/named/os.h
new file mode 100644
index 0000000..cac89a4
--- /dev/null
+++ b/bin/named/win32/include/named/os.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef NS_OS_H
+#define NS_OS_H 1
+
+#include <stdbool.h>
+
+#include <isc/types.h>
+
+void
+ns_os_init(const char *progname);
+
+void
+ns_os_daemonize(void);
+
+void
+ns_os_opendevnull(void);
+
+void
+ns_os_closedevnull(void);
+
+void
+ns_os_chroot(const char *root);
+
+void
+ns_os_inituserinfo(const char *username);
+
+void
+ns_os_changeuser(void);
+
+unsigned int
+ns_os_uid(void);
+
+void
+ns_os_adjustnofile(void);
+
+void
+ns_os_minprivs(void);
+
+FILE *
+ns_os_openfile(const char *filename, int mode, bool switch_user);
+
+void
+ns_os_writepidfile(const char *filename, bool first_time);
+
+bool
+ns_os_issingleton(const char *filename);
+
+void
+ns_os_shutdown(void);
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len);
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text);
+
+void
+ns_os_tzset(void);
+
+void
+ns_os_started(void);
+
+char *
+ns_os_uname(void);
+
+#endif /* NS_OS_H */
diff --git a/bin/named/win32/named.dsp.in b/bin/named/win32/named.dsp.in
new file mode 100644
index 0000000..354b88b
--- /dev/null
+++ b/bin/named/win32/named.dsp.in
@@ -0,0 +1,341 @@
+# Microsoft Developer Studio Project File - Name="named" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=named - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "named.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "named.mak" CFG="named - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "named - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "named - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 @OPENSSL_INC@ @GSSAPI_INC@ @GEOIP_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"old Visual Studio\"" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/lwres/win32/Release/liblwres.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named.exe"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od @OPENSSL_INC@ @GSSAPI_INC@ @GEOIP_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"old Visual Studio\"" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/lwres/win32/Debug/liblwres.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../Build/Debug/named.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "named - @PLATFORM@ Release"
+# Name "named - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\builtin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\config.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\control.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\controlconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dlz_dlopen_driver.c
+# End Source File
+@IF GEOIP
+# Begin Source File
+
+SOURCE=..\geoip.c
+# End Source File
+@END GEOIP
+# Begin Source File
+
+SOURCE=..\interfacemgr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\listenlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\logconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdclient.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwderror.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdgabn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdgnba.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdgrbn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdnoop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwresd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwsearch.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\notify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntservice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\query.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\server.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sortlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\statschannel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tkeyconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tsigconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\update.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\xfrout.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zoneconf.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\named\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\globals.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\interfacemgr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\listenlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\logconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwdclient.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwresd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwsearch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\main.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\notify.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\named\ntservice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\omapi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\named\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\query.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\seccomp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\server.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\sortlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\statschannel.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\tkeyconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\tsigconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\update.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\xfrout.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\zoneconf.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/named/win32/named.dsw b/bin/named/win32/named.dsw
new file mode 100644
index 0000000..c2913ef
--- /dev/null
+++ b/bin/named/win32/named.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "named"=".\named.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/named/win32/named.mak.in b/bin/named/win32/named.mak.in
new file mode 100644
index 0000000..9e73888
--- /dev/null
+++ b/bin/named/win32/named.mak.in
@@ -0,0 +1,1233 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on named.dsp
+!IF "$(CFG)" == ""
+CFG=named - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to named - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "named - @PLATFORM@ Release" && "$(CFG)" != "named - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "named.mak" CFG="named - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "named - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "named - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\named.exe"
+
+!ELSE
+
+ALL : "libisccfg - @PLATFORM@ Release" "libisccc - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\named.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN" "libisccc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\builtin.obj"
+ -@erase "$(INTDIR)\client.obj"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\control.obj"
+ -@erase "$(INTDIR)\controlconf.obj"
+ -@erase "$(INTDIR)\dlz_dlopen_driver.obj"
+@IF GEOIP
+ -@erase "$(INTDIR)\geoip.obj"
+@END GEOIP
+ -@erase "$(INTDIR)\interfacemgr.obj"
+ -@erase "$(INTDIR)\listenlist.obj"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\logconf.obj"
+ -@erase "$(INTDIR)\lwaddr.obj"
+ -@erase "$(INTDIR)\lwdclient.obj"
+ -@erase "$(INTDIR)\lwderror.obj"
+ -@erase "$(INTDIR)\lwdgabn.obj"
+ -@erase "$(INTDIR)\lwdgnba.obj"
+ -@erase "$(INTDIR)\lwdgrbn.obj"
+ -@erase "$(INTDIR)\lwdnoop.obj"
+ -@erase "$(INTDIR)\lwresd.obj"
+ -@erase "$(INTDIR)\lwsearch.obj"
+ -@erase "$(INTDIR)\main.obj"
+ -@erase "$(INTDIR)\notify.obj"
+ -@erase "$(INTDIR)\ntservice.obj"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\query.obj"
+ -@erase "$(INTDIR)\server.obj"
+ -@erase "$(INTDIR)\sortlist.obj"
+ -@erase "$(INTDIR)\statschannel.obj"
+ -@erase "$(INTDIR)\tkeyconf.obj"
+ -@erase "$(INTDIR)\tsigconf.obj"
+ -@erase "$(INTDIR)\update.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\xfrout.obj"
+ -@erase "$(INTDIR)\zoneconf.obj"
+ -@erase "..\..\..\Build\Release\named.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 @OPENSSL_INC@ @GSSAPI_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"nmake\"" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\named.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\named.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/lwres/win32/Release/liblwres.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib $(LIBXML) @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named.pdb" @MACHINE@ /out:"../../../Build/Release/named.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\client.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\control.obj" \
+ "$(INTDIR)\controlconf.obj" \
+ "$(INTDIR)\dlz_dlopen_driver.obj" \
+@IF GEOIP
+ "$(INTDIR)\geoip.obj" \
+@END GEOIP
+ "$(INTDIR)\interfacemgr.obj" \
+ "$(INTDIR)\listenlist.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\logconf.obj" \
+ "$(INTDIR)\lwaddr.obj" \
+ "$(INTDIR)\lwdclient.obj" \
+ "$(INTDIR)\lwderror.obj" \
+ "$(INTDIR)\lwdgabn.obj" \
+ "$(INTDIR)\lwdgnba.obj" \
+ "$(INTDIR)\lwdgrbn.obj" \
+ "$(INTDIR)\lwdnoop.obj" \
+ "$(INTDIR)\lwresd.obj" \
+ "$(INTDIR)\lwsearch.obj" \
+ "$(INTDIR)\main.obj" \
+ "$(INTDIR)\notify.obj" \
+ "$(INTDIR)\ntservice.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\query.obj" \
+ "$(INTDIR)\server.obj" \
+ "$(INTDIR)\sortlist.obj" \
+ "$(INTDIR)\statschannel.obj" \
+ "$(INTDIR)\tkeyconf.obj" \
+ "$(INTDIR)\tsigconf.obj" \
+ "$(INTDIR)\update.obj" \
+ "$(INTDIR)\xfrout.obj" \
+ "$(INTDIR)\zoneconf.obj" \
+ "$(INTDIR)\builtin.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib" \
+ "..\..\..\lib\isccc\win32\Release\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib"
+
+"..\..\..\Build\Release\named.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\named.exe" "$(OUTDIR)\named.bsc"
+
+!ELSE
+
+ALL : "libisccfg - @PLATFORM@ Debug" "libisccc - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\named.exe" "$(OUTDIR)\named.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN" "libisccc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\builtin.obj"
+ -@erase "$(INTDIR)\builtin.sbr"
+ -@erase "$(INTDIR)\client.obj"
+ -@erase "$(INTDIR)\client.sbr"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\config.sbr"
+ -@erase "$(INTDIR)\control.obj"
+ -@erase "$(INTDIR)\control.sbr"
+ -@erase "$(INTDIR)\controlconf.obj"
+ -@erase "$(INTDIR)\controlconf.sbr"
+ -@erase "$(INTDIR)\dlz_dlopen_driver.obj"
+ -@erase "$(INTDIR)\dlz_dlopen_driver.sbr"
+@IF GEOIP
+ -@erase "$(INTDIR)\geoip.obj"
+ -@erase "$(INTDIR)\geoip.sbr"
+@END GEOIP
+ -@erase "$(INTDIR)\interfacemgr.obj"
+ -@erase "$(INTDIR)\interfacemgr.sbr"
+ -@erase "$(INTDIR)\listenlist.obj"
+ -@erase "$(INTDIR)\listenlist.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\logconf.obj"
+ -@erase "$(INTDIR)\logconf.sbr"
+ -@erase "$(INTDIR)\lwaddr.obj"
+ -@erase "$(INTDIR)\lwaddr.sbr"
+ -@erase "$(INTDIR)\lwdclient.obj"
+ -@erase "$(INTDIR)\lwdclient.sbr"
+ -@erase "$(INTDIR)\lwderror.obj"
+ -@erase "$(INTDIR)\lwderror.sbr"
+ -@erase "$(INTDIR)\lwdgabn.obj"
+ -@erase "$(INTDIR)\lwdgabn.sbr"
+ -@erase "$(INTDIR)\lwdgnba.obj"
+ -@erase "$(INTDIR)\lwdgnba.sbr"
+ -@erase "$(INTDIR)\lwdgrbn.obj"
+ -@erase "$(INTDIR)\lwdgrbn.sbr"
+ -@erase "$(INTDIR)\lwdnoop.obj"
+ -@erase "$(INTDIR)\lwdnoop.sbr"
+ -@erase "$(INTDIR)\lwresd.obj"
+ -@erase "$(INTDIR)\lwresd.sbr"
+ -@erase "$(INTDIR)\lwsearch.obj"
+ -@erase "$(INTDIR)\lwsearch.sbr"
+ -@erase "$(INTDIR)\main.obj"
+ -@erase "$(INTDIR)\main.sbr"
+ -@erase "$(INTDIR)\notify.obj"
+ -@erase "$(INTDIR)\notify.sbr"
+ -@erase "$(INTDIR)\ntservice.obj"
+ -@erase "$(INTDIR)\ntservice.sbr"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\query.obj"
+ -@erase "$(INTDIR)\query.sbr"
+ -@erase "$(INTDIR)\server.obj"
+ -@erase "$(INTDIR)\server.sbr"
+ -@erase "$(INTDIR)\sortlist.obj"
+ -@erase "$(INTDIR)\sortlist.sbr"
+ -@erase "$(INTDIR)\statschannel.obj"
+ -@erase "$(INTDIR)\statschannel.sbr"
+ -@erase "$(INTDIR)\tkeyconf.obj"
+ -@erase "$(INTDIR)\tkeyconf.sbr"
+ -@erase "$(INTDIR)\tsigconf.obj"
+ -@erase "$(INTDIR)\tsigconf.sbr"
+ -@erase "$(INTDIR)\update.obj"
+ -@erase "$(INTDIR)\update.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\xfrout.obj"
+ -@erase "$(INTDIR)\xfrout.sbr"
+ -@erase "$(INTDIR)\zoneconf.obj"
+ -@erase "$(INTDIR)\zoneconf.sbr"
+ -@erase "$(OUTDIR)\named.bsc"
+ -@erase "$(OUTDIR)\named.map"
+ -@erase "$(OUTDIR)\named.pdb"
+ -@erase "..\..\..\Build\Debug\named.exe"
+ -@erase "..\..\..\Build\Debug\named.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od @OPENSSL_INC@ @GSSAPI_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"nmake\"" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\named.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\client.sbr" \
+ "$(INTDIR)\config.sbr" \
+ "$(INTDIR)\control.sbr" \
+ "$(INTDIR)\controlconf.sbr" \
+ "$(INTDIR)\dlz_dlopen_driver.sbr" \
+@IF GEOIP
+ "$(INTDIR)\geoip.sbr" \
+@END GEOIP
+ "$(INTDIR)\interfacemgr.sbr" \
+ "$(INTDIR)\listenlist.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\logconf.sbr" \
+ "$(INTDIR)\lwaddr.sbr" \
+ "$(INTDIR)\lwdclient.sbr" \
+ "$(INTDIR)\lwderror.sbr" \
+ "$(INTDIR)\lwdgabn.sbr" \
+ "$(INTDIR)\lwdgnba.sbr" \
+ "$(INTDIR)\lwdgrbn.sbr" \
+ "$(INTDIR)\lwdnoop.sbr" \
+ "$(INTDIR)\lwresd.sbr" \
+ "$(INTDIR)\lwsearch.sbr" \
+ "$(INTDIR)\main.sbr" \
+ "$(INTDIR)\notify.sbr" \
+ "$(INTDIR)\ntservice.sbr" \
+ "$(INTDIR)\os.sbr" \
+ "$(INTDIR)\query.sbr" \
+ "$(INTDIR)\server.sbr" \
+ "$(INTDIR)\sortlist.sbr" \
+ "$(INTDIR)\statschannel.sbr" \
+ "$(INTDIR)\tkeyconf.sbr" \
+ "$(INTDIR)\tsigconf.sbr" \
+ "$(INTDIR)\update.sbr" \
+ "$(INTDIR)\xfrout.sbr" \
+ "$(INTDIR)\zoneconf.sbr" \
+ "$(INTDIR)\builtin.sbr"
+
+"$(OUTDIR)\named.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/lwres/win32/Debug/liblwres.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib $(LIBXML) @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named.pdb" /map:"$(INTDIR)\named.map" /debug @MACHINE@ /out:"../../../Build/Debug/named.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\client.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\control.obj" \
+ "$(INTDIR)\controlconf.obj" \
+ "$(INTDIR)\dlz_dlopen_driver.obj" \
+@IF GEOIP
+ "$(INTDIR)\geoip.obj" \
+@END GEOIP
+ "$(INTDIR)\interfacemgr.obj" \
+ "$(INTDIR)\listenlist.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\logconf.obj" \
+ "$(INTDIR)\lwaddr.obj" \
+ "$(INTDIR)\lwdclient.obj" \
+ "$(INTDIR)\lwderror.obj" \
+ "$(INTDIR)\lwdgabn.obj" \
+ "$(INTDIR)\lwdgnba.obj" \
+ "$(INTDIR)\lwdgrbn.obj" \
+ "$(INTDIR)\lwdnoop.obj" \
+ "$(INTDIR)\lwresd.obj" \
+ "$(INTDIR)\lwsearch.obj" \
+ "$(INTDIR)\main.obj" \
+ "$(INTDIR)\notify.obj" \
+ "$(INTDIR)\ntservice.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\query.obj" \
+ "$(INTDIR)\server.obj" \
+ "$(INTDIR)\sortlist.obj" \
+ "$(INTDIR)\statschannel.obj" \
+ "$(INTDIR)\tkeyconf.obj" \
+ "$(INTDIR)\tsigconf.obj" \
+ "$(INTDIR)\update.obj" \
+ "$(INTDIR)\xfrout.obj" \
+ "$(INTDIR)\zoneconf.obj" \
+ "$(INTDIR)\builtin.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib" \
+ "..\..\..\lib\isccc\win32\Debug\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib"
+
+"..\..\..\Build\Debug\named.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("named.dep")
+!INCLUDE "named.dep"
+!ELSE
+!MESSAGE Warning: cannot find "named.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release" || "$(CFG)" == "named - @PLATFORM@ Debug"
+SOURCE=..\builtin.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\builtin.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\builtin.obj" "$(INTDIR)\builtin.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\client.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\client.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\client.obj" "$(INTDIR)\client.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\config.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\config.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\config.obj" "$(INTDIR)\config.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\control.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\control.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\control.obj" "$(INTDIR)\control.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\controlconf.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\controlconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\controlconf.obj" "$(INTDIR)\controlconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\dlz_dlopen_driver.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dlz_dlopen_driver.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dlz_dlopen_driver.obj" "$(INTDIR)\dlz_dlopen_driver.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+@IF GEOIP
+SOURCE=..\geoip.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\geoip.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\geoip.obj" "$(INTDIR)\geoip.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+@END GEOIP
+
+SOURCE=..\interfacemgr.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\interfacemgr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\interfacemgr.obj" "$(INTDIR)\interfacemgr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\listenlist.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\listenlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\listenlist.obj" "$(INTDIR)\listenlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\logconf.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\logconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\logconf.obj" "$(INTDIR)\logconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwaddr.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwaddr.obj" "$(INTDIR)\lwaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdclient.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwdclient.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwdclient.obj" "$(INTDIR)\lwdclient.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwderror.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwderror.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwderror.obj" "$(INTDIR)\lwderror.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdgabn.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwdgabn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwdgabn.obj" "$(INTDIR)\lwdgabn.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdgnba.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwdgnba.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwdgnba.obj" "$(INTDIR)\lwdgnba.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdgrbn.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwdgrbn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwdgrbn.obj" "$(INTDIR)\lwdgrbn.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdnoop.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwdnoop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwdnoop.obj" "$(INTDIR)\lwdnoop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwresd.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwresd.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwresd.obj" "$(INTDIR)\lwresd.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwsearch.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwsearch.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwsearch.obj" "$(INTDIR)\lwsearch.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\main.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\main.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\main.obj" "$(INTDIR)\main.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\notify.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\notify.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\notify.obj" "$(INTDIR)\notify.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\ntservice.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ntservice.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ntservice.obj" "$(INTDIR)\ntservice.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\query.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\query.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\query.obj" "$(INTDIR)\query.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\server.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\server.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\server.obj" "$(INTDIR)\server.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sortlist.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\sortlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\sortlist.obj" "$(INTDIR)\sortlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\statschannel.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\statschannel.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\statschannel.obj" "$(INTDIR)\statschannel.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tkeyconf.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\tkeyconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\tkeyconf.obj" "$(INTDIR)\tkeyconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tsigconf.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\tsigconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\tsigconf.obj" "$(INTDIR)\tsigconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\update.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\update.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\update.obj" "$(INTDIR)\update.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\xfrout.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\xfrout.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\xfrout.obj" "$(INTDIR)\xfrout.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\zoneconf.c
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+
+"$(INTDIR)\zoneconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\zoneconf.obj" "$(INTDIR)\zoneconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\named\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\named\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\named\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\named\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\named\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+"libisccc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release"
+ cd "..\..\..\bin\named\win32"
+
+"libisccc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+"libisccc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libisccc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - @PLATFORM@ Release"
+
+"libisccfg - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release"
+ cd "..\..\..\bin\named\win32"
+
+"libisccfg - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug"
+
+"libisccfg - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libisccfg - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/named/win32/named.vcxproj.filters.in b/bin/named/win32/named.vcxproj.filters.in
new file mode 100644
index 0000000..8cc6a7b
--- /dev/null
+++ b/bin/named/win32/named.vcxproj.filters.in
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dlz_dlopen_driver.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ntservice.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="os.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\builtin.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\client.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\config.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\control.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\controlconf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@IF GEOIP
+ <ClCompile Include="..\geoip.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@END GEOIP
+ <ClCompile Include="..\interfacemgr.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\listenlist.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\log.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\logconf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwaddr.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwdclient.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwderror.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwdgabn.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwdgnba.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwdgrbn.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwdnoop.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwresd.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lwsearch.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\notify.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\query.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\server.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\sortlist.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\statschannel.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tkeyconf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tsigconf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\update.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\xfrout.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\zoneconf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="include\named\ntservice.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\named\os.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\builtin.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\client.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\control.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@IF GEOIP
+ <ClInclude Include="..\include\named\geoip.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@END GEOIP
+ <ClInclude Include="..\include\named\globals.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\interfacemgr.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\listenlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\log.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\logconf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\lwaddr.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\lwdclient.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\lwresd.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\lwsearch.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\main.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\notify.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\query.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\seccomp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\server.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\sortlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\statschannel.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\tkeyconf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\tsigconf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\types.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\update.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\xfrout.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\named\zoneconf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/named/win32/named.vcxproj.in b/bin/named/win32/named.vcxproj.in
new file mode 100644
index 0000000..f2d70cc
--- /dev/null
+++ b/bin/named/win32/named.vcxproj.in
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{723C65DA-A96C-4BA3-A34E-44F11CA346F9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>named</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@@USE_GSSAPI@BUILDER="Visual Studio";_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;liblwres.lib;libisccfg.lib;libbind9.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@@USE_GSSAPI@BUILDER="Visual Studio";NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;liblwres.lib;libisccfg.lib;libbind9.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\builtin.c" />
+ <ClCompile Include="..\client.c" />
+ <ClCompile Include="..\config.c" />
+ <ClCompile Include="..\control.c" />
+ <ClCompile Include="..\controlconf.c" />
+@IF GEOIP
+ <ClCompile Include="..\geoip.c" />
+@END GEOIP
+ <ClCompile Include="..\interfacemgr.c" />
+ <ClCompile Include="..\listenlist.c" />
+ <ClCompile Include="..\log.c" />
+ <ClCompile Include="..\logconf.c" />
+ <ClCompile Include="..\lwaddr.c" />
+ <ClCompile Include="..\lwdclient.c" />
+ <ClCompile Include="..\lwderror.c" />
+ <ClCompile Include="..\lwdgabn.c" />
+ <ClCompile Include="..\lwdgnba.c" />
+ <ClCompile Include="..\lwdgrbn.c" />
+ <ClCompile Include="..\lwdnoop.c" />
+ <ClCompile Include="..\lwresd.c" />
+ <ClCompile Include="..\lwsearch.c" />
+ <ClCompile Include="..\main.c" />
+ <ClCompile Include="..\notify.c" />
+ <ClCompile Include="..\query.c" />
+ <ClCompile Include="..\server.c" />
+ <ClCompile Include="..\sortlist.c" />
+ <ClCompile Include="..\statschannel.c" />
+ <ClCompile Include="..\tkeyconf.c" />
+ <ClCompile Include="..\tsigconf.c" />
+ <ClCompile Include="..\update.c" />
+ <ClCompile Include="..\xfrout.c" />
+ <ClCompile Include="..\zoneconf.c" />
+ <ClCompile Include="dlz_dlopen_driver.c" />
+ <ClCompile Include="ntservice.c" />
+ <ClCompile Include="os.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\named\builtin.h" />
+ <ClInclude Include="..\include\named\client.h" />
+ <ClInclude Include="..\include\named\config.h" />
+ <ClInclude Include="..\include\named\control.h" />
+@IF GEOIP
+ <ClInclude Include="..\include\named\geoip.h" />
+@END GEOIP
+ <ClInclude Include="..\include\named\globals.h" />
+ <ClInclude Include="..\include\named\interfacemgr.h" />
+ <ClInclude Include="..\include\named\listenlist.h" />
+ <ClInclude Include="..\include\named\log.h" />
+ <ClInclude Include="..\include\named\logconf.h" />
+ <ClInclude Include="..\include\named\lwaddr.h" />
+ <ClInclude Include="..\include\named\lwdclient.h" />
+ <ClInclude Include="..\include\named\lwresd.h" />
+ <ClInclude Include="..\include\named\lwsearch.h" />
+ <ClInclude Include="..\include\named\main.h" />
+ <ClInclude Include="..\include\named\notify.h" />
+ <ClInclude Include="..\include\named\query.h" />
+ <ClInclude Include="..\include\named\seccomp.h" />
+ <ClInclude Include="..\include\named\server.h" />
+ <ClInclude Include="..\include\named\sortlist.h" />
+ <ClInclude Include="..\include\named\statschannel.h" />
+ <ClInclude Include="..\include\named\tkeyconf.h" />
+ <ClInclude Include="..\include\named\tsigconf.h" />
+ <ClInclude Include="..\include\named\types.h" />
+ <ClInclude Include="..\include\named\update.h" />
+ <ClInclude Include="..\include\named\xfrout.h" />
+ <ClInclude Include="..\include\named\zoneconf.h" />
+ <ClInclude Include="include\named\ntservice.h" />
+ <ClInclude Include="include\named\os.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/named/win32/named.vcxproj.user b/bin/named/win32/named.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/named/win32/named.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/named/win32/ntservice.c b/bin/named/win32/ntservice.c
new file mode 100644
index 0000000..23a5dc4
--- /dev/null
+++ b/bin/named/win32/ntservice.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+#include <stdio.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/log.h>
+#include <isc/print.h>
+#include <isc/string.h>
+
+#include <named/globals.h>
+#include <named/ntservice.h>
+#include <named/main.h>
+#include <named/server.h>
+
+/* Handle to SCM for updating service status */
+static SERVICE_STATUS_HANDLE hServiceStatus = 0;
+static BOOL foreground = FALSE;
+static char ConsoleTitle[128];
+
+/*
+ * Forward declarations
+ */
+void ServiceControl(DWORD dwCtrlCode);
+int bindmain(int, char *[]); /* From main.c */
+
+/*
+ * Initialize the Service by registering it.
+ */
+void
+ntservice_init(void) {
+ if (!foreground) {
+ /* Register handler with the SCM */
+ hServiceStatus = RegisterServiceCtrlHandler(BIND_SERVICE_NAME,
+ (LPHANDLER_FUNCTION)ServiceControl);
+ if (!hServiceStatus) {
+ ns_main_earlyfatal(
+ "could not register service control handler");
+ }
+ UpdateSCM(SERVICE_RUNNING);
+ } else {
+ strlcpy(ConsoleTitle, "BIND Version ", sizeof(ConsoleTitle));
+ strlcat(ConsoleTitle, VERSION, sizeof(ConsoleTitle));
+ SetConsoleTitle(ConsoleTitle);
+ }
+}
+
+void
+ntservice_shutdown(void) {
+ UpdateSCM(SERVICE_STOPPED);
+}
+/*
+ * Routine to check if this is a service or a foreground program
+ */
+BOOL
+ntservice_isservice(void) {
+ return(!foreground);
+}
+/*
+ * ServiceControl(): Handles requests from the SCM and passes them on
+ * to named.
+ */
+void
+ServiceControl(DWORD dwCtrlCode) {
+ /* Handle the requested control code */
+ switch(dwCtrlCode) {
+ case SERVICE_CONTROL_INTERROGATE:
+ UpdateSCM(0);
+ break;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ ns_server_flushonshutdown(ns_g_server, true);
+ isc_app_shutdown();
+ UpdateSCM(SERVICE_STOPPED);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Tell the Service Control Manager the state of the service.
+ */
+void UpdateSCM(DWORD state) {
+ SERVICE_STATUS ss;
+ static DWORD dwState = SERVICE_STOPPED;
+
+ if (hServiceStatus) {
+ if (state)
+ dwState = state;
+
+ memset(&ss, 0, sizeof(SERVICE_STATUS));
+ ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
+ ss.dwCurrentState = dwState;
+ ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+ SERVICE_ACCEPT_SHUTDOWN;
+ ss.dwCheckPoint = 0;
+ ss.dwServiceSpecificExitCode = 0;
+ ss.dwWin32ExitCode = NO_ERROR;
+ ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 10000 : 1000;
+
+ if (!SetServiceStatus(hServiceStatus, &ss)) {
+ ss.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus(hServiceStatus, &ss);
+ }
+ }
+}
+
+/* unhook main */
+
+#undef main
+
+/*
+ * This is the entry point for the executable
+ * We can now call bindmain() explicitly or via StartServiceCtrlDispatcher()
+ * as we need to.
+ */
+int main(int argc, char *argv[])
+{
+ int rc, ch;
+
+ /* Command line users should put -f in the options. */
+ isc_commandline_errprint = false;
+ while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) {
+ switch (ch) {
+ case 'f':
+ case 'g':
+ case 'v':
+ case 'V':
+ foreground = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ if (foreground) {
+ /* run in console window */
+ exit(bindmain(argc, argv));
+ } else {
+ /* Start up as service */
+ char *SERVICE_NAME = BIND_SERVICE_NAME;
+
+ SERVICE_TABLE_ENTRY dispatchTable[] = {
+ { TEXT(SERVICE_NAME),
+ (LPSERVICE_MAIN_FUNCTION)bindmain },
+ { NULL, NULL }
+ };
+
+ rc = StartServiceCtrlDispatcher(dispatchTable);
+ if (!rc) {
+ fprintf(stderr,
+ "Use -f to run from the command line.\n");
+ /* will be 1063 when launched as a console app */
+ exit(GetLastError());
+ }
+ }
+ exit(0);
+}
diff --git a/bin/named/win32/os.c b/bin/named/win32/os.c
new file mode 100644
index 0000000..f89c50d
--- /dev/null
+++ b/bin/named/win32/os.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <io.h>
+#include <process.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/ntpaths.h>
+#include <isc/util.h>
+#include <isc/win32os.h>
+
+#include <named/main.h>
+#include <named/log.h>
+#include <named/os.h>
+#include <named/globals.h>
+#include <named/ntservice.h>
+
+
+static char *lockfile = NULL;
+static char *pidfile = NULL;
+static int devnullfd = -1;
+static int lockfilefd = -1;
+
+static BOOL Initialized = FALSE;
+
+static char *version_error =
+ "named requires Windows 2000 Service Pack 2 or later to run correctly";
+
+void
+ns_paths_init(void) {
+ if (!Initialized)
+ isc_ntpaths_init();
+
+ lwresd_g_conffile = isc_ntpaths_get(LWRES_CONF_PATH);
+ lwresd_g_resolvconffile = isc_ntpaths_get(RESOLV_CONF_PATH);
+ ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
+ ns_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH);
+ lwresd_g_defaultpidfile = isc_ntpaths_get(LWRESD_PID_PATH);
+ ns_g_defaultlockfile = isc_ntpaths_get(NAMED_LOCK_PATH);
+ ns_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH);
+ ns_g_defaultsessionkeyfile = isc_ntpaths_get(SESSION_KEY_PATH);
+ ns_g_defaultdnstap = NULL;
+
+ Initialized = TRUE;
+}
+
+/*
+ * Due to Knowledge base article Q263823 we need to make sure that
+ * Windows 2000 systems have Service Pack 2 or later installed and
+ * warn when it isn't.
+ */
+static void
+version_check(const char *progname) {
+
+ if ((isc_win32os_versioncheck(4, 0, 0, 0) >= 0) &&
+ (isc_win32os_versioncheck(5, 0, 0, 0) < 0))
+ return; /* No problem with Version 4.0 */
+ if (isc_win32os_versioncheck(5, 0, 2, 0) < 0)
+ if (ntservice_isservice())
+ NTReportError(progname, version_error);
+ else
+ fprintf(stderr, "%s\n", version_error);
+}
+
+static void
+setup_syslog(const char *progname) {
+ int options;
+
+ options = LOG_PID;
+#ifdef LOG_NDELAY
+ options |= LOG_NDELAY;
+#endif
+
+ openlog(progname, options, LOG_DAEMON);
+}
+
+void
+ns_os_init(const char *progname) {
+ ns_paths_init();
+ setup_syslog(progname);
+ /*
+ * XXXMPA. We may need to split ntservice_init() in two and
+ * just mark as running in ns_os_started(). If we do that
+ * this is where the first part of ntservice_init() should be
+ * called from.
+ *
+ * XXX970 Remove comment if no problems by 9.7.0.
+ *
+ * ntservice_init();
+ */
+ version_check(progname);
+}
+
+void
+ns_os_daemonize(void) {
+ /*
+ * Try to set stdin, stdout, and stderr to /dev/null, but press
+ * on even if it fails.
+ */
+ if (devnullfd != -1) {
+ if (devnullfd != _fileno(stdin)) {
+ close(_fileno(stdin));
+ (void)_dup2(devnullfd, _fileno(stdin));
+ }
+ if (devnullfd != _fileno(stdout)) {
+ close(_fileno(stdout));
+ (void)_dup2(devnullfd, _fileno(stdout));
+ }
+ if (devnullfd != _fileno(stderr)) {
+ close(_fileno(stderr));
+ (void)_dup2(devnullfd, _fileno(stderr));
+ }
+ }
+}
+
+void
+ns_os_opendevnull(void) {
+ devnullfd = open("NUL", O_RDWR, 0);
+}
+
+void
+ns_os_closedevnull(void) {
+ if (devnullfd != _fileno(stdin) &&
+ devnullfd != _fileno(stdout) &&
+ devnullfd != _fileno(stderr)) {
+ close(devnullfd);
+ devnullfd = -1;
+ }
+}
+
+void
+ns_os_chroot(const char *root) {
+ if (root != NULL)
+ ns_main_earlyfatal("chroot(): isn't supported by Win32 API");
+}
+
+void
+ns_os_inituserinfo(const char *username) {
+}
+
+void
+ns_os_changeuser(void) {
+}
+
+unsigned int
+ns_os_uid(void) {
+ return (0);
+}
+
+void
+ns_os_adjustnofile(void) {
+}
+
+void
+ns_os_minprivs(void) {
+}
+
+static int
+safe_open(const char *filename, int 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)
+ return (-1);
+
+ if (append)
+ fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode);
+ else {
+ (void)unlink(filename);
+ fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
+ }
+ return (fd);
+}
+
+static void
+cleanup_pidfile(void) {
+ if (pidfile != NULL) {
+ (void)unlink(pidfile);
+ free(pidfile);
+ }
+ pidfile = NULL;
+}
+
+static void
+cleanup_lockfile(void) {
+ if (lockfilefd != -1) {
+ close(lockfilefd);
+ lockfilefd = -1;
+ }
+
+ if (lockfile != NULL) {
+ int n = unlink(lockfile);
+ if (n == -1 && errno != ENOENT)
+ ns_main_earlywarning("unlink '%s': failed", lockfile);
+ free(lockfile);
+ lockfile = NULL;
+ }
+}
+
+FILE *
+ns_os_openfile(const char *filename, int mode, bool switch_user) {
+ char strbuf[ISC_STRERRORSIZE];
+ FILE *fp;
+ int fd;
+
+ UNUSED(switch_user);
+ fd = safe_open(filename, mode, false);
+ if (fd < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("could not open file '%s': %s",
+ filename, strbuf);
+ return (NULL);
+ }
+
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("could not fdopen() file '%s': %s",
+ filename, strbuf);
+ close(fd);
+ }
+
+ return (fp);
+}
+
+void
+ns_os_writepidfile(const char *filename, bool first_time) {
+ FILE *pidlockfile;
+ pid_t pid;
+ char strbuf[ISC_STRERRORSIZE];
+ void (*report)(const char *, ...);
+
+ /*
+ * The caller must ensure any required synchronization.
+ */
+
+ report = first_time ? ns_main_earlyfatal : ns_main_earlywarning;
+
+ cleanup_pidfile();
+
+ if (filename == NULL)
+ return;
+
+ pidfile = strdup(filename);
+ if (pidfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't strdup() '%s': %s", filename, strbuf);
+ return;
+ }
+
+ pidlockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
+ false);
+ if (pidlockfile == NULL) {
+ free(pidfile);
+ pidfile = NULL;
+ return;
+ }
+
+ pid = getpid();
+
+ if (fprintf(pidlockfile, "%ld\n", (long)pid) < 0) {
+ (*report)("fprintf() to pid file '%s' failed", filename);
+ (void)fclose(pidlockfile);
+ cleanup_pidfile();
+ return;
+ }
+ if (fflush(pidlockfile) == EOF) {
+ (*report)("fflush() to pid file '%s' failed", filename);
+ (void)fclose(pidlockfile);
+ cleanup_pidfile();
+ return;
+ }
+ (void)fclose(pidlockfile);
+}
+
+bool
+ns_os_issingleton(const char *filename) {
+ char strbuf[ISC_STRERRORSIZE];
+ OVERLAPPED o;
+
+ if (lockfilefd != -1)
+ return (true);
+
+ if (strcasecmp(filename, "none") == 0)
+ return (true);
+
+ lockfile = strdup(filename);
+ if (lockfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("couldn't allocate memory for '%s': %s",
+ filename, strbuf);
+ }
+
+ /*
+ * ns_os_openfile() uses safeopen() which removes any existing
+ * files. We can't use that here.
+ */
+ lockfilefd = open(filename, O_WRONLY | O_CREAT,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (lockfilefd == -1) {
+ cleanup_lockfile();
+ return (false);
+ }
+
+ memset(&o, 0, sizeof(o));
+ /* Expect ERROR_LOCK_VIOLATION if already locked */
+ if (!LockFileEx((HANDLE) _get_osfhandle(lockfilefd),
+ LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
+ 0, 0, 1, &o)) {
+ cleanup_lockfile();
+ return (false);
+ }
+
+ return (true);
+}
+
+
+void
+ns_os_shutdown(void) {
+ closelog();
+ cleanup_pidfile();
+
+ if (lockfilefd != -1) {
+ (void) UnlockFile((HANDLE) _get_osfhandle(lockfilefd),
+ 0, 0, 0, 1);
+ close(lockfilefd);
+ lockfilefd = -1;
+ }
+ ntservice_shutdown(); /* This MUST be the last thing done */
+}
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len) {
+ int n;
+
+ n = gethostname(buf, (int)len);
+ return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
+}
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
+ UNUSED(command);
+ UNUSED(text);
+}
+
+void
+ns_os_tzset(void) {
+#ifdef HAVE_TZSET
+ tzset();
+#endif
+}
+
+void
+ns_os_started(void) {
+ ntservice_init();
+}
+
+static char unamebuf[BUFSIZ];
+static char *unamep = NULL;
+
+static void
+getuname(void) {
+ DWORD fvilen;
+ char *fvi;
+ VS_FIXEDFILEINFO *ffi;
+ UINT ffilen;
+ SYSTEM_INFO sysinfo;
+ char *arch;
+
+ fvi = NULL;
+ fvilen = GetFileVersionInfoSize("kernel32.dll", 0);
+ if (fvilen == 0) {
+ goto err;
+ }
+ fvi = (char *)malloc(fvilen);
+ if (fvi == NULL) {
+ goto err;
+ }
+ memset(fvi, 0, fvilen);
+ if (GetFileVersionInfo("kernel32.dll", 0, fvilen, fvi) == 0) {
+ goto err;
+ }
+ ffi = NULL;
+ ffilen = 0;
+ if ((VerQueryValue(fvi, "\\", &ffi, &ffilen) == 0) ||
+ (ffi == NULL) || (ffilen == 0)) {
+ goto err;
+ }
+ memset(&sysinfo, 0, sizeof(sysinfo));
+ GetSystemInfo(&sysinfo);
+ switch (sysinfo.wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ arch = "x86";
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ arch = "arm";
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ arch = "ia64";
+ break;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ arch = "x64";
+ break;
+ default:
+ arch = "unknown architecture";
+ break;
+ }
+
+ snprintf(unamebuf, sizeof(unamebuf),
+ "Windows %d %d build %d %d for %s\n",
+ (ffi->dwProductVersionMS >> 16) & 0xffff,
+ ffi->dwProductVersionMS & 0xffff,
+ (ffi->dwProductVersionLS >> 16) & 0xffff,
+ ffi->dwProductVersionLS & 0xffff,
+ arch);
+
+ err:
+ if (fvi != NULL) {
+ free(fvi);
+ }
+ unamep = unamebuf;
+}
+
+/*
+ * GetVersionEx() returns 6.2 (aka Windows 8.1) since it was obsoleted
+ * so we had to switch to the recommended way to get the Windows version.
+ */
+char *
+ns_os_uname(void) {
+ if (unamep == NULL)
+ getuname();
+ return (unamep);
+}
diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c
new file mode 100644
index 0000000..2da7e70
--- /dev/null
+++ b/bin/named/xfrout.c
@@ -0,0 +1,1714 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id$ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/formatcheck.h>
+#include <isc/mem.h>
+#include <isc/timer.h>
+#include <isc/print.h>
+#include <isc/stats.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dlz.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/message.h>
+#include <dns/peer.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/rriterator.h>
+#include <dns/soa.h>
+#include <dns/stats.h>
+#include <dns/timer.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/xfrout.h>
+
+/*! \file
+ * \brief
+ * Outgoing AXFR and IXFR.
+ */
+
+/*
+ * TODO:
+ * - IXFR over UDP
+ */
+
+#define XFROUT_COMMON_LOGARGS \
+ ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
+
+#define XFROUT_PROTOCOL_LOGARGS \
+ XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
+
+#define XFROUT_DEBUG_LOGARGS(n) \
+ XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
+
+#define XFROUT_RR_LOGARGS \
+ XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
+
+#define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
+
+/*%
+ * Fail unconditionally and log as a client error.
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAILC(code, msg) \
+ do { \
+ result = (code); \
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
+ NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
+ "bad zone transfer request: %s (%s)", \
+ msg, isc_result_totext(code)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define FAILQ(code, msg, question, rdclass) \
+ do { \
+ char _buf1[DNS_NAME_FORMATSIZE]; \
+ char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
+ result = (code); \
+ dns_name_format(question, _buf1, sizeof(_buf1)); \
+ dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
+ NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
+ "bad zone transfer request: '%s/%s': %s (%s)", \
+ _buf1, _buf2, msg, isc_result_totext(code)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/**************************************************************************/
+
+static inline void
+inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
+ isc_stats_increment(ns_g_server->nsstats, counter);
+ if (zone != NULL) {
+ isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL)
+ isc_stats_increment(zonestats, counter);
+ }
+}
+
+/**************************************************************************/
+
+/*% Log an RR (for debugging) */
+
+static void
+log_rr(dns_name_t *name, dns_rdata_t *rdata, uint32_t ttl) {
+ isc_result_t result;
+ isc_buffer_t buf;
+ char mem[2000];
+ dns_rdatalist_t rdl;
+ dns_rdataset_t rds;
+ dns_rdata_t rd = DNS_RDATA_INIT;
+
+ dns_rdatalist_init(&rdl);
+ rdl.type = rdata->type;
+ rdl.rdclass = rdata->rdclass;
+ rdl.ttl = ttl;
+ if (rdata->type == dns_rdatatype_sig ||
+ rdata->type == dns_rdatatype_rrsig)
+ rdl.covers = dns_rdata_covers(rdata);
+ else
+ rdl.covers = dns_rdatatype_none;
+ dns_rdataset_init(&rds);
+ dns_rdata_init(&rd);
+ dns_rdata_clone(rdata, &rd);
+ ISC_LIST_APPEND(rdl.rdata, &rd, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
+
+ isc_buffer_init(&buf, mem, sizeof(mem));
+ result = dns_rdataset_totext(&rds, name,
+ false, false, &buf);
+
+ /*
+ * We could use xfrout_log(), but that would produce
+ * very long lines with a repetitive prefix.
+ */
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Get rid of final newline.
+ */
+ INSIST(buf.used >= 1 &&
+ ((char *) buf.base)[buf.used - 1] == '\n');
+ buf.used--;
+
+ isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
+ (int)isc_buffer_usedlength(&buf),
+ (char *)isc_buffer_base(&buf));
+ } else {
+ isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
+ }
+}
+
+/**************************************************************************/
+/*
+ * An 'rrstream_t' is a polymorphic iterator that returns
+ * a stream of resource records. There are multiple implementations,
+ * e.g. for generating AXFR and IXFR records streams.
+ */
+
+typedef struct rrstream_methods rrstream_methods_t;
+
+typedef struct rrstream {
+ isc_mem_t *mctx;
+ rrstream_methods_t *methods;
+} rrstream_t;
+
+struct rrstream_methods {
+ isc_result_t (*first)(rrstream_t *);
+ isc_result_t (*next)(rrstream_t *);
+ void (*current)(rrstream_t *,
+ dns_name_t **,
+ uint32_t *,
+ dns_rdata_t **);
+ void (*pause)(rrstream_t *);
+ void (*destroy)(rrstream_t **);
+};
+
+static void
+rrstream_noop_pause(rrstream_t *rs) {
+ UNUSED(rs);
+}
+
+/**************************************************************************/
+/*
+ * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
+ * an IXFR-like RR stream from a journal file.
+ *
+ * The SOA at the beginning of each sequence of additions
+ * or deletions are included in the stream, but the extra
+ * SOAs at the beginning and end of the entire transfer are
+ * not included.
+ */
+
+typedef struct ixfr_rrstream {
+ rrstream_t common;
+ dns_journal_t *journal;
+} ixfr_rrstream_t;
+
+/* Forward declarations. */
+static void
+ixfr_rrstream_destroy(rrstream_t **sp);
+
+static rrstream_methods_t ixfr_rrstream_methods;
+
+/*
+ * Returns: anything dns_journal_open() or dns_journal_iter_init()
+ * may return.
+ */
+
+static isc_result_t
+ixfr_rrstream_create(isc_mem_t *mctx,
+ const char *journal_filename,
+ uint32_t begin_serial,
+ uint32_t end_serial,
+ rrstream_t **sp)
+{
+ ixfr_rrstream_t *s;
+ isc_result_t result;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = NULL;
+ isc_mem_attach(mctx, &s->common.mctx);
+ s->common.methods = &ixfr_rrstream_methods;
+ s->journal = NULL;
+
+ CHECK(dns_journal_open(mctx, journal_filename,
+ DNS_JOURNAL_READ, &s->journal));
+ CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
+
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
+ return (result);
+}
+
+static isc_result_t
+ixfr_rrstream_first(rrstream_t *rs) {
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
+ return (dns_journal_first_rr(s->journal));
+}
+
+static isc_result_t
+ixfr_rrstream_next(rrstream_t *rs) {
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
+ return (dns_journal_next_rr(s->journal));
+}
+
+static void
+ixfr_rrstream_current(rrstream_t *rs,
+ dns_name_t **name, uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
+ dns_journal_current_rr(s->journal, name, ttl, rdata);
+}
+
+static void
+ixfr_rrstream_destroy(rrstream_t **rsp) {
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
+ if (s->journal != 0)
+ dns_journal_destroy(&s->journal);
+ isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t ixfr_rrstream_methods = {
+ ixfr_rrstream_first,
+ ixfr_rrstream_next,
+ ixfr_rrstream_current,
+ rrstream_noop_pause,
+ ixfr_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
+ * an AXFR-like RR stream from a database.
+ *
+ * The SOAs at the beginning and end of the transfer are
+ * not included in the stream.
+ */
+
+typedef struct axfr_rrstream {
+ rrstream_t common;
+ dns_rriterator_t it;
+ bool it_valid;
+} axfr_rrstream_t;
+
+/*
+ * Forward declarations.
+ */
+static void
+axfr_rrstream_destroy(rrstream_t **rsp);
+
+static rrstream_methods_t axfr_rrstream_methods;
+
+static isc_result_t
+axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
+ rrstream_t **sp)
+{
+ axfr_rrstream_t *s;
+ isc_result_t result;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = NULL;
+ isc_mem_attach(mctx, &s->common.mctx);
+ s->common.methods = &axfr_rrstream_methods;
+ s->it_valid = false;
+
+ CHECK(dns_rriterator_init(&s->it, db, ver, 0));
+ s->it_valid = true;
+
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ axfr_rrstream_destroy((rrstream_t **) (void *)&s);
+ return (result);
+}
+
+static isc_result_t
+axfr_rrstream_first(rrstream_t *rs) {
+ axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+ isc_result_t result;
+ result = dns_rriterator_first(&s->it);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /* Skip SOA records. */
+ for (;;) {
+ dns_name_t *name_dummy = NULL;
+ uint32_t ttl_dummy;
+ dns_rdata_t *rdata = NULL;
+ dns_rriterator_current(&s->it, &name_dummy,
+ &ttl_dummy, NULL, &rdata);
+ if (rdata->type != dns_rdatatype_soa)
+ break;
+ result = dns_rriterator_next(&s->it);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ return (result);
+}
+
+static isc_result_t
+axfr_rrstream_next(rrstream_t *rs) {
+ axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+ isc_result_t result;
+
+ /* Skip SOA records. */
+ for (;;) {
+ dns_name_t *name_dummy = NULL;
+ uint32_t ttl_dummy;
+ dns_rdata_t *rdata = NULL;
+ result = dns_rriterator_next(&s->it);
+ if (result != ISC_R_SUCCESS)
+ break;
+ dns_rriterator_current(&s->it, &name_dummy,
+ &ttl_dummy, NULL, &rdata);
+ if (rdata->type != dns_rdatatype_soa)
+ break;
+ }
+ return (result);
+}
+
+static void
+axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+ dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
+}
+
+static void
+axfr_rrstream_pause(rrstream_t *rs) {
+ axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+ dns_rriterator_pause(&s->it);
+}
+
+static void
+axfr_rrstream_destroy(rrstream_t **rsp) {
+ axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
+ if (s->it_valid)
+ dns_rriterator_destroy(&s->it);
+ isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t axfr_rrstream_methods = {
+ axfr_rrstream_first,
+ axfr_rrstream_next,
+ axfr_rrstream_current,
+ axfr_rrstream_pause,
+ axfr_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
+ * a single SOA record.
+ */
+
+typedef struct soa_rrstream {
+ rrstream_t common;
+ dns_difftuple_t *soa_tuple;
+} soa_rrstream_t;
+
+/*
+ * Forward declarations.
+ */
+static void
+soa_rrstream_destroy(rrstream_t **rsp);
+
+static rrstream_methods_t soa_rrstream_methods;
+
+static isc_result_t
+soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
+ rrstream_t **sp)
+{
+ soa_rrstream_t *s;
+ isc_result_t result;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = NULL;
+ isc_mem_attach(mctx, &s->common.mctx);
+ s->common.methods = &soa_rrstream_methods;
+ s->soa_tuple = NULL;
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
+ &s->soa_tuple));
+
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ soa_rrstream_destroy((rrstream_t **) (void *)&s);
+ return (result);
+}
+
+static isc_result_t
+soa_rrstream_first(rrstream_t *rs) {
+ UNUSED(rs);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+soa_rrstream_next(rrstream_t *rs) {
+ UNUSED(rs);
+ return (ISC_R_NOMORE);
+}
+
+static void
+soa_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ soa_rrstream_t *s = (soa_rrstream_t *) rs;
+ *name = &s->soa_tuple->name;
+ *ttl = s->soa_tuple->ttl;
+ *rdata = &s->soa_tuple->rdata;
+}
+
+static void
+soa_rrstream_destroy(rrstream_t **rsp) {
+ soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
+ if (s->soa_tuple != NULL)
+ dns_difftuple_free(&s->soa_tuple);
+ isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t soa_rrstream_methods = {
+ soa_rrstream_first,
+ soa_rrstream_next,
+ soa_rrstream_current,
+ rrstream_noop_pause,
+ soa_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * A 'compound_rrstream_t' objects owns a soa_rrstream
+ * and another rrstream, the "data stream". It returns
+ * a concatenated stream consisting of the soa_rrstream, then
+ * the data stream, then the soa_rrstream again.
+ *
+ * The component streams are owned by the compound_rrstream_t
+ * and are destroyed with it.
+ */
+
+typedef struct compound_rrstream {
+ rrstream_t common;
+ rrstream_t *components[3];
+ int state;
+ isc_result_t result;
+} compound_rrstream_t;
+
+/*
+ * Forward declarations.
+ */
+static void
+compound_rrstream_destroy(rrstream_t **rsp);
+
+static isc_result_t
+compound_rrstream_next(rrstream_t *rs);
+
+static rrstream_methods_t compound_rrstream_methods;
+
+/*
+ * Requires:
+ * soa_stream != NULL && *soa_stream != NULL
+ * data_stream != NULL && *data_stream != NULL
+ * sp != NULL && *sp == NULL
+ *
+ * Ensures:
+ * *soa_stream == NULL
+ * *data_stream == NULL
+ * *sp points to a valid compound_rrstream_t
+ * The soa and data streams will be destroyed
+ * when the compound_rrstream_t is destroyed.
+ */
+static isc_result_t
+compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
+ rrstream_t **data_stream, rrstream_t **sp)
+{
+ compound_rrstream_t *s;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = NULL;
+ isc_mem_attach(mctx, &s->common.mctx);
+ s->common.methods = &compound_rrstream_methods;
+ s->components[0] = *soa_stream;
+ s->components[1] = *data_stream;
+ s->components[2] = *soa_stream;
+ s->state = -1;
+ s->result = ISC_R_FAILURE;
+
+ *soa_stream = NULL;
+ *data_stream = NULL;
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+compound_rrstream_first(rrstream_t *rs) {
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ s->state = 0;
+ do {
+ rrstream_t *curstream = s->components[s->state];
+ s->result = curstream->methods->first(curstream);
+ } while (s->result == ISC_R_NOMORE && s->state < 2);
+ return (s->result);
+}
+
+static isc_result_t
+compound_rrstream_next(rrstream_t *rs) {
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ rrstream_t *curstream = s->components[s->state];
+ s->result = curstream->methods->next(curstream);
+ while (s->result == ISC_R_NOMORE) {
+ /*
+ * Make sure locks held by the current stream
+ * are released before we switch streams.
+ */
+ curstream->methods->pause(curstream);
+ if (s->state == 2)
+ return (ISC_R_NOMORE);
+ s->state++;
+ curstream = s->components[s->state];
+ s->result = curstream->methods->first(curstream);
+ }
+ return (s->result);
+}
+
+static void
+compound_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ rrstream_t *curstream;
+ INSIST(0 <= s->state && s->state < 3);
+ INSIST(s->result == ISC_R_SUCCESS);
+ curstream = s->components[s->state];
+ curstream->methods->current(curstream, name, ttl, rdata);
+}
+
+static void
+compound_rrstream_pause(rrstream_t *rs)
+{
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ rrstream_t *curstream;
+ INSIST(0 <= s->state && s->state < 3);
+ curstream = s->components[s->state];
+ curstream->methods->pause(curstream);
+}
+
+static void
+compound_rrstream_destroy(rrstream_t **rsp) {
+ compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
+ s->components[0]->methods->destroy(&s->components[0]);
+ s->components[1]->methods->destroy(&s->components[1]);
+ s->components[2] = NULL; /* Copy of components[0]. */
+ isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t compound_rrstream_methods = {
+ compound_rrstream_first,
+ compound_rrstream_next,
+ compound_rrstream_current,
+ compound_rrstream_pause,
+ compound_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
+ * in progress.
+ */
+
+typedef struct {
+ isc_mem_t *mctx;
+ ns_client_t *client;
+ unsigned int id; /* ID of request */
+ dns_name_t *qname; /* Question name of request */
+ dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
+ dns_rdataclass_t qclass;
+ dns_zone_t *zone; /* (necessary for stats) */
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ isc_quota_t *quota;
+ rrstream_t *stream; /* The XFR RR stream */
+ bool end_of_stream; /* EOS has been reached */
+ isc_buffer_t buf; /* Buffer for message owner
+ names and rdatas */
+ isc_buffer_t txlenbuf; /* Transmit length buffer */
+ isc_buffer_t txbuf; /* Transmit message buffer */
+ void *txmem;
+ unsigned int txmemlen;
+ unsigned int nmsg; /* Number of messages sent */
+ dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
+ isc_buffer_t *lasttsig; /* the last TSIG */
+ bool verified_tsig; /* verified request MAC */
+ bool many_answers;
+ int sends; /* Send in progress */
+ bool shuttingdown;
+ const char *mnemonic; /* Style of transfer */
+} xfrout_ctx_t;
+
+static isc_result_t
+xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
+ unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
+ dns_rdataclass_t qclass, dns_zone_t *zone,
+ dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
+ rrstream_t *stream, dns_tsigkey_t *tsigkey,
+ isc_buffer_t *lasttsig,
+ bool verified_tsig,
+ unsigned int maxtime,
+ unsigned int idletime,
+ bool many_answers,
+ xfrout_ctx_t **xfrp);
+
+static void
+sendstream(xfrout_ctx_t *xfr);
+
+static void
+xfrout_senddone(isc_task_t *task, isc_event_t *event);
+
+static void
+xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
+
+static void
+xfrout_maybe_destroy(xfrout_ctx_t *xfr);
+
+static void
+xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
+
+static void
+xfrout_client_shutdown(void *arg, isc_result_t result);
+
+static void
+xfrout_log1(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
+
+static void
+xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+/**************************************************************************/
+
+void
+ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
+ isc_result_t result;
+ dns_name_t *question_name;
+ dns_rdataset_t *question_rdataset;
+ dns_zone_t *zone = NULL, *raw = NULL, *mayberaw;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_rdataclass_t question_class;
+ rrstream_t *soa_stream = NULL;
+ rrstream_t *data_stream = NULL;
+ rrstream_t *stream = NULL;
+ dns_difftuple_t *current_soa_tuple = NULL;
+ dns_name_t *soa_name;
+ dns_rdataset_t *soa_rdataset;
+ dns_rdata_t soa_rdata = DNS_RDATA_INIT;
+ bool have_soa = false;
+ const char *mnemonic = NULL;
+ isc_mem_t *mctx = client->mctx;
+ dns_message_t *request = client->message;
+ xfrout_ctx_t *xfr = NULL;
+ isc_quota_t *quota = NULL;
+ dns_transfer_format_t format = client->view->transfer_format;
+ isc_netaddr_t na;
+ dns_peer_t *peer = NULL;
+ isc_buffer_t *tsigbuf = NULL;
+ char *journalfile;
+ char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
+ char keyname[DNS_NAME_FORMATSIZE];
+ bool is_poll = false;
+ bool is_dlz = false;
+ bool is_ixfr = false;
+ uint32_t begin_serial = 0, current_serial;
+
+ switch (reqtype) {
+ case dns_rdatatype_axfr:
+ mnemonic = "AXFR";
+ break;
+ case dns_rdatatype_ixfr:
+ mnemonic = "IXFR";
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+
+ ns_client_log(client,
+ DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
+ ISC_LOG_DEBUG(6), "%s request", mnemonic);
+ /*
+ * Apply quota.
+ */
+ result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
+ "%s request denied: %s", mnemonic,
+ isc_result_totext(result));
+ goto failure;
+ }
+
+ /*
+ * Interpret the question section.
+ */
+ result = dns_message_firstname(request, DNS_SECTION_QUESTION);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /*
+ * The question section must contain exactly one question, and
+ * it must be for AXFR/IXFR as appropriate.
+ */
+ question_name = NULL;
+ dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
+ question_rdataset = ISC_LIST_HEAD(question_name->list);
+ question_class = question_rdataset->rdclass;
+ INSIST(question_rdataset->type == reqtype);
+ if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
+ FAILC(DNS_R_FORMERR, "multiple questions");
+ result = dns_message_nextname(request, DNS_SECTION_QUESTION);
+ if (result != ISC_R_NOMORE)
+ FAILC(DNS_R_FORMERR, "multiple questions");
+
+ result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
+ &zone);
+
+ if (result != ISC_R_SUCCESS || dns_zone_gettype(zone) == dns_zone_dlz) {
+ /*
+ * The normal zone table does not have a match, or this is
+ * marked in the zone table as a DLZ zone. Check the DLZ
+ * databases for a match.
+ */
+ if (! ISC_LIST_EMPTY(client->view->dlz_searched)) {
+ result = dns_dlzallowzonexfr(client->view,
+ question_name,
+ &client->peeraddr,
+ &db);
+
+ if (result == ISC_R_NOPERM) {
+ char _buf1[DNS_NAME_FORMATSIZE];
+ char _buf2[DNS_RDATACLASS_FORMATSIZE];
+
+ result = DNS_R_REFUSED;
+ dns_name_format(question_name, _buf1,
+ sizeof(_buf1));
+ dns_rdataclass_format(question_class,
+ _buf2, sizeof(_buf2));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_XFER_OUT,
+ ISC_LOG_ERROR,
+ "zone transfer '%s/%s' denied",
+ _buf1, _buf2);
+ goto failure;
+ }
+ if (result != ISC_R_SUCCESS)
+ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
+ question_name, question_class);
+ is_dlz = true;
+ } else {
+ /*
+ * not DLZ and not in normal zone table, we are
+ * not authoritative
+ */
+ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
+ question_name, question_class);
+ }
+ } else {
+ /* zone table has a match */
+ switch(dns_zone_gettype(zone)) {
+ /* Master and slave zones are OK for transfer. */
+ case dns_zone_master:
+ case dns_zone_slave:
+ case dns_zone_dlz:
+ break;
+ default:
+ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
+ question_name, question_class);
+ }
+ CHECK(dns_zone_getdb(zone, &db));
+ dns_db_currentversion(db, &ver);
+ }
+
+ xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
+ "%s question section OK", mnemonic);
+
+ /*
+ * Check the authority section. Look for a SOA record with
+ * the same name and class as the question.
+ */
+ for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
+ {
+ soa_name = NULL;
+ dns_message_currentname(request, DNS_SECTION_AUTHORITY,
+ &soa_name);
+
+ /*
+ * Ignore data whose owner name is not the zone apex.
+ */
+ if (! dns_name_equal(soa_name, question_name))
+ continue;
+
+ for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
+ soa_rdataset != NULL;
+ soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
+ {
+ /*
+ * Ignore non-SOA data.
+ */
+ if (soa_rdataset->type != dns_rdatatype_soa)
+ continue;
+ if (soa_rdataset->rdclass != question_class)
+ continue;
+
+ CHECK(dns_rdataset_first(soa_rdataset));
+ dns_rdataset_current(soa_rdataset, &soa_rdata);
+ result = dns_rdataset_next(soa_rdataset);
+ if (result == ISC_R_SUCCESS)
+ FAILC(DNS_R_FORMERR,
+ "IXFR authority section "
+ "has multiple SOAs");
+ have_soa = true;
+ goto got_soa;
+ }
+ }
+ got_soa:
+ if (result != ISC_R_NOMORE)
+ CHECK(result);
+
+ xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
+ "%s authority section OK", mnemonic);
+
+ /*
+ * If not a DLZ zone, decide whether to allow this transfer.
+ */
+ if (!is_dlz) {
+ ns_client_aclmsg("zone transfer", question_name, reqtype,
+ client->view->rdclass, msg, sizeof(msg));
+ CHECK(ns_client_checkacl(client, NULL, msg,
+ dns_zone_getxfracl(zone),
+ true, ISC_LOG_ERROR));
+ }
+
+ /*
+ * AXFR over UDP is not possible.
+ */
+ if (reqtype == dns_rdatatype_axfr &&
+ (client->attributes & NS_CLIENTATTR_TCP) == 0)
+ FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
+
+ /*
+ * Look up the requesting server in the peer table.
+ */
+ isc_netaddr_fromsockaddr(&na, &client->peeraddr);
+ (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
+
+ /*
+ * Decide on the transfer format (one-answer or many-answers).
+ */
+ if (peer != NULL)
+ (void)dns_peer_gettransferformat(peer, &format);
+
+ /*
+ * Get a dynamically allocated copy of the current SOA.
+ */
+ if (is_dlz)
+ dns_db_currentversion(db, &ver);
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
+ &current_soa_tuple));
+
+ current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
+ if (reqtype == dns_rdatatype_ixfr) {
+ bool provide_ixfr;
+
+ /*
+ * Outgoing IXFR may have been disabled for this peer
+ * or globally.
+ */
+ provide_ixfr = client->view->provideixfr;
+ if (peer != NULL)
+ (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
+ if (provide_ixfr == false)
+ goto axfr_fallback;
+
+ if (! have_soa)
+ FAILC(DNS_R_FORMERR,
+ "IXFR request missing SOA");
+
+ begin_serial = dns_soa_getserial(&soa_rdata);
+
+ /*
+ * RFC1995 says "If an IXFR query with the same or
+ * newer version number than that of the server
+ * is received, it is replied to with a single SOA
+ * record of the server's current version, just as
+ * in AXFR". The claim about AXFR is incorrect,
+ * but other than that, we do as the RFC says.
+ *
+ * Sending a single SOA record is also how we refuse
+ * IXFR over UDP (currently, we always do).
+ */
+ if (DNS_SERIAL_GE(begin_serial, current_serial) ||
+ (client->attributes & NS_CLIENTATTR_TCP) == 0)
+ {
+ CHECK(soa_rrstream_create(mctx, db, ver, &stream));
+ is_poll = true;
+ goto have_stream;
+ }
+ journalfile = is_dlz ? NULL : dns_zone_getjournal(zone);
+ if (journalfile != NULL)
+ result = ixfr_rrstream_create(mctx,
+ journalfile,
+ begin_serial,
+ current_serial,
+ &data_stream);
+ else
+ result = ISC_R_NOTFOUND;
+ if (result == ISC_R_NOTFOUND ||
+ result == ISC_R_RANGE) {
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_DEBUG(4),
+ "IXFR version not in journal, "
+ "falling back to AXFR");
+ mnemonic = "AXFR-style IXFR";
+ goto axfr_fallback;
+ }
+ CHECK(result);
+ is_ixfr = true;
+ } else {
+ axfr_fallback:
+ CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream));
+ }
+
+ /*
+ * Bracket the data stream with SOAs.
+ */
+ CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
+ CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
+ &stream));
+ soa_stream = NULL;
+ data_stream = NULL;
+
+ have_stream:
+ CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
+ /*
+ * Create the xfrout context object. This transfers the ownership
+ * of "stream", "db", "ver", and "quota" to the xfrout context object.
+ */
+
+
+
+ if (is_dlz)
+ CHECK(xfrout_ctx_create(mctx, client, request->id,
+ question_name, reqtype, question_class,
+ zone, db, ver, quota, stream,
+ dns_message_gettsigkey(request),
+ tsigbuf,
+ request->verified_sig,
+ 3600,
+ 3600,
+ (format == dns_many_answers) ?
+ true : false,
+ &xfr));
+ else
+ CHECK(xfrout_ctx_create(mctx, client, request->id,
+ question_name, reqtype, question_class,
+ zone, db, ver, quota, stream,
+ dns_message_gettsigkey(request),
+ tsigbuf,
+ request->verified_sig,
+ dns_zone_getmaxxfrout(zone),
+ dns_zone_getidleout(zone),
+ (format == dns_many_answers) ?
+ true : false,
+ &xfr));
+
+ xfr->mnemonic = mnemonic;
+ stream = NULL;
+ quota = NULL;
+
+ CHECK(xfr->stream->methods->first(xfr->stream));
+
+ if (xfr->tsigkey != NULL)
+ dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
+ else
+ keyname[0] = '\0';
+ if (is_poll)
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
+ (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
+ else if (is_ixfr)
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)",
+ mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
+ keyname, begin_serial, current_serial);
+ else
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_INFO, "%s started%s%s (serial %u)",
+ mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
+ keyname, current_serial);
+
+
+ if (zone != NULL) {
+ dns_zone_getraw(zone, &raw);
+ mayberaw = (raw != NULL) ? raw : zone;
+ if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
+ dns_zone_gettype(mayberaw) == dns_zone_slave) {
+ isc_time_t expiretime;
+ uint32_t secs;
+ dns_zone_getexpiretime(zone, &expiretime);
+ secs = isc_time_seconds(&expiretime);
+ if (secs >= client->now && result == ISC_R_SUCCESS) {
+ client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
+ client->expire = secs - client->now;
+ }
+ }
+ if (raw != NULL)
+ dns_zone_detach(&raw);
+ }
+
+ /*
+ * Hand the context over to sendstream(). Set xfr to NULL;
+ * sendstream() is responsible for either passing the
+ * context on to a later event handler or destroying it.
+ */
+ sendstream(xfr);
+ xfr = NULL;
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (result == DNS_R_REFUSED)
+ inc_stats(zone, dns_nsstatscounter_xfrrej);
+ if (quota != NULL)
+ isc_quota_detach(&quota);
+ if (current_soa_tuple != NULL)
+ dns_difftuple_free(&current_soa_tuple);
+ if (stream != NULL)
+ stream->methods->destroy(&stream);
+ if (soa_stream != NULL)
+ soa_stream->methods->destroy(&soa_stream);
+ if (data_stream != NULL)
+ data_stream->methods->destroy(&data_stream);
+ if (ver != NULL)
+ dns_db_closeversion(db, &ver, false);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ /* XXX kludge */
+ if (xfr != NULL) {
+ xfrout_fail(xfr, result, "setting up zone transfer");
+ } else if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
+ NS_LOGMODULE_XFER_OUT,
+ ISC_LOG_DEBUG(3), "zone transfer setup failed");
+ ns_client_error(client, result);
+ }
+}
+
+static isc_result_t
+xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
+ dns_name_t *qname, dns_rdatatype_t qtype,
+ dns_rdataclass_t qclass, dns_zone_t *zone,
+ dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
+ rrstream_t *stream, dns_tsigkey_t *tsigkey,
+ isc_buffer_t *lasttsig, bool verified_tsig,
+ unsigned int maxtime, unsigned int idletime,
+ bool many_answers, xfrout_ctx_t **xfrp)
+{
+ xfrout_ctx_t *xfr;
+ isc_result_t result;
+ unsigned int len;
+ void *mem;
+
+ INSIST(xfrp != NULL && *xfrp == NULL);
+ xfr = isc_mem_get(mctx, sizeof(*xfr));
+ if (xfr == NULL)
+ return (ISC_R_NOMEMORY);
+ xfr->mctx = NULL;
+ isc_mem_attach(mctx, &xfr->mctx);
+ xfr->client = NULL;
+ ns_client_attach(client, &xfr->client);
+ xfr->id = id;
+ xfr->qname = qname;
+ xfr->qtype = qtype;
+ xfr->qclass = qclass;
+ xfr->zone = NULL;
+ xfr->db = NULL;
+ xfr->ver = NULL;
+ if (zone != NULL) /* zone will be NULL if it's DLZ */
+ dns_zone_attach(zone, &xfr->zone);
+ dns_db_attach(db, &xfr->db);
+ dns_db_attachversion(db, ver, &xfr->ver);
+ xfr->end_of_stream = false;
+ xfr->tsigkey = tsigkey;
+ xfr->lasttsig = lasttsig;
+ xfr->verified_tsig = verified_tsig;
+ xfr->nmsg = 0;
+ xfr->many_answers = many_answers;
+ xfr->sends = 0;
+ xfr->shuttingdown = false;
+ xfr->mnemonic = NULL;
+ xfr->buf.base = NULL;
+ xfr->buf.length = 0;
+ xfr->txmem = NULL;
+ xfr->txmemlen = 0;
+ xfr->stream = NULL;
+ xfr->quota = NULL;
+
+ /*
+ * Allocate a temporary buffer for the uncompressed response
+ * message data. The size should be no more than 65535 bytes
+ * so that the compressed data will fit in a TCP message,
+ * and no less than 65535 bytes so that an almost maximum-sized
+ * RR will fit. Note that although 65535-byte RRs are allowed
+ * in principle, they cannot be zone-transferred (at least not
+ * if uncompressible), because the message and RR headers would
+ * push the size of the TCP message over the 65536 byte limit.
+ */
+ len = 65535;
+ mem = isc_mem_get(mctx, len);
+ if (mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ isc_buffer_init(&xfr->buf, mem, len);
+
+ /*
+ * Allocate another temporary buffer for the compressed
+ * response message and its TCP length prefix.
+ */
+ len = 2 + 65535;
+ mem = isc_mem_get(mctx, len);
+ if (mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ isc_buffer_init(&xfr->txlenbuf, mem, 2);
+ isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
+ xfr->txmem = mem;
+ xfr->txmemlen = len;
+
+ CHECK(dns_timer_setidle(xfr->client->timer,
+ maxtime, idletime, false));
+
+ /*
+ * Register a shutdown callback with the client, so that we
+ * can stop the transfer immediately when the client task
+ * gets a shutdown event.
+ */
+ xfr->client->shutdown = xfrout_client_shutdown;
+ xfr->client->shutdown_arg = xfr;
+ /*
+ * These MUST be after the last "goto failure;" / CHECK to
+ * prevent a double free by the caller.
+ */
+ xfr->quota = quota;
+ xfr->stream = stream;
+
+ *xfrp = xfr;
+ return (ISC_R_SUCCESS);
+
+failure:
+ xfrout_ctx_destroy(&xfr);
+ return (result);
+}
+
+
+/*
+ * Arrange to send as much as we can of "stream" without blocking.
+ *
+ * Requires:
+ * The stream iterator is initialized and points at an RR,
+ * or possibly at the end of the stream (that is, the
+ * _first method of the iterator has been called).
+ */
+static void
+sendstream(xfrout_ctx_t *xfr) {
+ dns_message_t *tcpmsg = NULL;
+ dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
+ isc_result_t result;
+ isc_region_t used;
+ isc_region_t region;
+ dns_rdataset_t *qrdataset;
+ dns_name_t *msgname = NULL;
+ dns_rdata_t *msgrdata = NULL;
+ dns_rdatalist_t *msgrdl = NULL;
+ dns_rdataset_t *msgrds = NULL;
+ dns_compress_t cctx;
+ bool cleanup_cctx = false;
+ bool is_tcp;
+
+ int n_rrs;
+
+ isc_buffer_clear(&xfr->buf);
+ isc_buffer_clear(&xfr->txlenbuf);
+ isc_buffer_clear(&xfr->txbuf);
+
+ is_tcp = (xfr->client->attributes & NS_CLIENTATTR_TCP);
+ if (!is_tcp) {
+ /*
+ * In the UDP case, we put the response data directly into
+ * the client message.
+ */
+ msg = xfr->client->message;
+ CHECK(dns_message_reply(msg, true));
+ } else {
+ /*
+ * TCP. Build a response dns_message_t, temporarily storing
+ * the raw, uncompressed owner names and RR data contiguously
+ * in xfr->buf. We know that if the uncompressed data fits
+ * in xfr->buf, the compressed data will surely fit in a TCP
+ * message.
+ */
+
+ CHECK(dns_message_create(xfr->mctx,
+ DNS_MESSAGE_INTENTRENDER, &tcpmsg));
+ msg = tcpmsg;
+
+ msg->id = xfr->id;
+ msg->rcode = dns_rcode_noerror;
+ msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
+ if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
+ msg->flags |= DNS_MESSAGEFLAG_RA;
+ CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
+ CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+ msg->verified_sig = xfr->verified_tsig;
+
+ /*
+ * Add a EDNS option to the message?
+ */
+ if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
+ dns_rdataset_t *opt = NULL;
+
+ CHECK(ns_client_addopt(xfr->client, msg, &opt));
+ CHECK(dns_message_setopt(msg, opt));
+ /*
+ * Add to first message only.
+ */
+ xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
+ xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
+ }
+
+ /*
+ * Account for reserved space.
+ */
+ if (xfr->tsigkey != NULL)
+ INSIST(msg->reserved != 0U);
+ isc_buffer_add(&xfr->buf, msg->reserved);
+
+ /*
+ * Include a question section in the first message only.
+ * BIND 8.2.1 will not recognize an IXFR if it does not
+ * have a question section.
+ */
+ if (xfr->nmsg == 0) {
+ dns_name_t *qname = NULL;
+ isc_region_t r;
+
+ /*
+ * Reserve space for the 12-byte message header
+ * and 4 bytes of question.
+ */
+ isc_buffer_add(&xfr->buf, 12 + 4);
+
+ qrdataset = NULL;
+ result = dns_message_gettemprdataset(msg, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_rdataset_makequestion(qrdataset,
+ xfr->client->message->rdclass,
+ xfr->qtype);
+
+ result = dns_message_gettempname(msg, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_name_init(qname, NULL);
+ isc_buffer_availableregion(&xfr->buf, &r);
+ INSIST(r.length >= xfr->qname->length);
+ r.length = xfr->qname->length;
+ isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
+ xfr->qname->length);
+ dns_name_fromregion(qname, &r);
+ ISC_LIST_INIT(qname->list);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+
+ dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
+ } else {
+ /*
+ * Reserve space for the 12-byte message header
+ */
+ isc_buffer_add(&xfr->buf, 12);
+ msg->tcp_continuation = 1;
+ }
+ }
+
+ /*
+ * Try to fit in as many RRs as possible, unless "one-answer"
+ * format has been requested.
+ */
+ for (n_rrs = 0; ; n_rrs++) {
+ dns_name_t *name = NULL;
+ uint32_t ttl;
+ dns_rdata_t *rdata = NULL;
+
+ unsigned int size;
+ isc_region_t r;
+
+ msgname = NULL;
+ msgrdata = NULL;
+ msgrdl = NULL;
+ msgrds = NULL;
+
+ xfr->stream->methods->current(xfr->stream,
+ &name, &ttl, &rdata);
+ size = name->length + 10 + rdata->length;
+ isc_buffer_availableregion(&xfr->buf, &r);
+ if (size >= r.length) {
+ /*
+ * RR would not fit. If there are other RRs in the
+ * buffer, send them now and leave this RR to the
+ * next message. If this RR overflows the buffer
+ * all by itself, fail.
+ *
+ * In theory some RRs might fit in a TCP message
+ * when compressed even if they do not fit when
+ * uncompressed, but surely we don't want
+ * to send such monstrosities to an unsuspecting
+ * slave.
+ */
+ if (n_rrs == 0) {
+ xfrout_log(xfr, ISC_LOG_WARNING,
+ "RR too large for zone transfer "
+ "(%d bytes)", size);
+ /* XXX DNS_R_RRTOOLARGE? */
+ result = ISC_R_NOSPACE;
+ goto failure;
+ }
+ break;
+ }
+
+ if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
+ log_rr(name, rdata, ttl); /* XXX */
+
+ result = dns_message_gettempname(msg, &msgname);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_name_init(msgname, NULL);
+ isc_buffer_availableregion(&xfr->buf, &r);
+ INSIST(r.length >= name->length);
+ r.length = name->length;
+ isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
+ dns_name_fromregion(msgname, &r);
+
+ /* Reserve space for RR header. */
+ isc_buffer_add(&xfr->buf, 10);
+
+ result = dns_message_gettemprdata(msg, &msgrdata);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ isc_buffer_availableregion(&xfr->buf, &r);
+ r.length = rdata->length;
+ isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
+ dns_rdata_init(msgrdata);
+ dns_rdata_fromregion(msgrdata,
+ rdata->rdclass, rdata->type, &r);
+
+ result = dns_message_gettemprdatalist(msg, &msgrdl);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ msgrdl->type = rdata->type;
+ msgrdl->rdclass = rdata->rdclass;
+ msgrdl->ttl = ttl;
+ if (rdata->type == dns_rdatatype_sig ||
+ rdata->type == dns_rdatatype_rrsig)
+ msgrdl->covers = dns_rdata_covers(rdata);
+ else
+ msgrdl->covers = dns_rdatatype_none;
+ ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
+
+ result = dns_message_gettemprdataset(msg, &msgrds);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = dns_rdatalist_tordataset(msgrdl, msgrds);
+ INSIST(result == ISC_R_SUCCESS);
+
+ ISC_LIST_APPEND(msgname->list, msgrds, link);
+
+ dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
+ msgname = NULL;
+
+ result = xfr->stream->methods->next(xfr->stream);
+ if (result == ISC_R_NOMORE) {
+ xfr->end_of_stream = true;
+ break;
+ }
+ CHECK(result);
+
+ if (! xfr->many_answers)
+ break;
+ /*
+ * At this stage, at least 1 RR has been rendered into
+ * the message. Check if we want to clamp this message
+ * here (TCP only).
+ */
+ if ((isc_buffer_usedlength(&xfr->buf) >=
+ ns_g_server->transfer_tcp_message_size) && is_tcp)
+ break;
+ }
+
+ if (is_tcp) {
+ CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
+ dns_compress_setsensitive(&cctx, true);
+ cleanup_cctx = true;
+ CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
+ CHECK(dns_message_renderend(msg));
+ dns_compress_invalidate(&cctx);
+ cleanup_cctx = false;
+
+ isc_buffer_usedregion(&xfr->txbuf, &used);
+ isc_buffer_putuint16(&xfr->txlenbuf,
+ (uint16_t)used.length);
+ region.base = xfr->txlenbuf.base;
+ region.length = 2 + used.length;
+ xfrout_log(xfr, ISC_LOG_DEBUG(8),
+ "sending TCP message of %d bytes",
+ used.length);
+ CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
+ &region, xfr->client->task,
+ xfrout_senddone,
+ xfr));
+ xfr->sends++;
+ } else {
+ xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
+ ns_client_send(xfr->client);
+ xfr->stream->methods->pause(xfr->stream);
+ xfrout_ctx_destroy(&xfr);
+ return;
+ }
+
+ /* Advance lasttsig to be the last TSIG generated */
+ CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
+
+ xfr->nmsg++;
+
+ failure:
+ if (msgname != NULL) {
+ if (msgrds != NULL) {
+ if (dns_rdataset_isassociated(msgrds))
+ dns_rdataset_disassociate(msgrds);
+ dns_message_puttemprdataset(msg, &msgrds);
+ }
+ if (msgrdl != NULL) {
+ ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
+ dns_message_puttemprdatalist(msg, &msgrdl);
+ }
+ if (msgrdata != NULL)
+ dns_message_puttemprdata(msg, &msgrdata);
+ dns_message_puttempname(msg, &msgname);
+ }
+
+ if (tcpmsg != NULL)
+ dns_message_destroy(&tcpmsg);
+
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+ /*
+ * Make sure to release any locks held by database
+ * iterators before returning from the event handler.
+ */
+ xfr->stream->methods->pause(xfr->stream);
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ xfrout_fail(xfr, result, "sending zone data");
+}
+
+static void
+xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
+ xfrout_ctx_t *xfr = *xfrp;
+ ns_client_t *client = NULL;
+
+ INSIST(xfr->sends == 0);
+
+ xfr->client->shutdown = NULL;
+ xfr->client->shutdown_arg = NULL;
+
+ if (xfr->stream != NULL)
+ xfr->stream->methods->destroy(&xfr->stream);
+ if (xfr->buf.base != NULL)
+ isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
+ if (xfr->txmem != NULL)
+ isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+ if (xfr->quota != NULL)
+ isc_quota_detach(&xfr->quota);
+ if (xfr->ver != NULL)
+ dns_db_closeversion(xfr->db, &xfr->ver, false);
+ if (xfr->zone != NULL)
+ dns_zone_detach(&xfr->zone);
+ if (xfr->db != NULL)
+ dns_db_detach(&xfr->db);
+
+ /*
+ * We want to detch the client after we have released the memory
+ * context as ns_client_detach checks the memory reference count.
+ */
+ ns_client_attach(xfr->client, &client);
+ ns_client_detach(&xfr->client);
+ isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
+ ns_client_detach(&client);
+
+ *xfrp = NULL;
+}
+
+static void
+xfrout_senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sev = (isc_socketevent_t *)event;
+ xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
+ isc_result_t evresult = sev->result;
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ isc_event_free(&event);
+ xfr->sends--;
+ INSIST(xfr->sends == 0);
+
+ (void)isc_timer_touch(xfr->client->timer);
+ if (xfr->shuttingdown == true) {
+ xfrout_maybe_destroy(xfr);
+ } else if (evresult != ISC_R_SUCCESS) {
+ xfrout_fail(xfr, evresult, "send");
+ } else if (xfr->end_of_stream == false) {
+ sendstream(xfr);
+ } else {
+ /* End of zone transfer stream. */
+ inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
+ xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
+ ns_client_next(xfr->client, ISC_R_SUCCESS);
+ xfrout_ctx_destroy(&xfr);
+ }
+}
+
+static void
+xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
+ xfr->shuttingdown = true;
+ xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
+ msg, isc_result_totext(result));
+ xfrout_maybe_destroy(xfr);
+}
+
+static void
+xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
+ INSIST(xfr->shuttingdown == true);
+ if (xfr->sends > 0) {
+ /*
+ * If we are currently sending, cancel it and wait for
+ * cancel event before destroying the context.
+ */
+ isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
+ ISC_SOCKCANCEL_SEND);
+ } else {
+ ns_client_next(xfr->client, ISC_R_CANCELED);
+ xfrout_ctx_destroy(&xfr);
+ }
+}
+
+static void
+xfrout_client_shutdown(void *arg, isc_result_t result) {
+ xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
+ xfrout_fail(xfr, result, "aborted");
+}
+
+/*
+ * Log outgoing zone transfer messages in a format like
+ * <client>: transfer of <zone>: <message>
+ */
+
+static void
+xfrout_logv(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
+ ISC_FORMAT_PRINTF(5, 0);
+
+static void
+xfrout_logv(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
+{
+ char msgbuf[2048];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
+ NS_LOGMODULE_XFER_OUT, level,
+ "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
+}
+
+/*
+ * Logging function for use when a xfrout_ctx_t has not yet been created.
+ */
+static void
+xfrout_log1(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ xfrout_logv(client, zonename, rdclass, level, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Logging function for use when there is a xfrout_ctx_t.
+ */
+static void
+xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
+ va_end(ap);
+}
diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
new file mode 100644
index 0000000..e237bdb
--- /dev/null
+++ b/bin/named/zoneconf.c
@@ -0,0 +1,1824 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.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/ipkeylist.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/masterdump.h>
+#include <dns/rdata.h>
+#include <dns/rdatatype.h>
+#include <dns/rdataset.h>
+#include <dns/rdatalist.h>
+#include <dns/result.h>
+#include <dns/sdlz.h>
+#include <dns/ssu.h>
+#include <dns/stats.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include <named/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:
+ INSIST(0);
+ return (ISC_R_FAILURE);
+ }
+
+ /* First check to see if ACL is defined within the zone */
+ if (zconfig != NULL) {
+ maps[0] = cfg_tuple_get(zconfig, "options");
+ (void)ns_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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ (void)ns_config_get(maps, aclname, &aclobj);
+ if (aclobj == NULL) {
+ (*clearzacl)(zone);
+ return (ISC_R_SUCCESS);
+ }
+
+parse_acl:
+ result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
+ dns_zone_getmctx(zone), 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;
+
+ (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;
+ }
+
+ result = dns_ssutable_create(mctx, &table);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ 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_rdatatype_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
+ INSIST(0);
+
+ str = cfg_obj_asstring(matchtype);
+ CHECK(dns_ssu_mtypefromstring(str, &mtype));
+ if (mtype == dns_ssumatchtype_subdomain) {
+ 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, ns_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ goto cleanup;
+ }
+
+ dns_fixedname_init(&fname);
+ if (usezone) {
+ result = dns_name_copy(dns_zone_getorigin(zone),
+ dns_fixedname_name(&fname),
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
+ "error copying origin: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ } 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, ns_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ goto cleanup;
+ }
+ }
+
+ n = ns_config_listcount(typelist);
+ if (n == 0)
+ types = NULL;
+ else {
+ types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
+ if (types == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ }
+
+ i = 0;
+ for (element2 = cfg_list_first(typelist);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *typeobj;
+ isc_textregion_t r;
+
+ INSIST(i < n);
+
+ typeobj = cfg_listelt_value(element2);
+ str = cfg_obj_asstring(typeobj);
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+
+ result = dns_rdatatype_fromtext(&types[i++], &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid type", str);
+ isc_mem_put(mctx, types,
+ n * sizeof(dns_rdatatype_t));
+ goto cleanup;
+ }
+ }
+ INSIST(i == n);
+
+ result = 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(dns_rdatatype_t));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+
+ /*
+ * 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_rdatatype_t any = dns_rdatatype_any;
+
+ if (ns_g_server->session_keyname == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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;
+ }
+
+ result = dns_ssutable_addrule(table, true,
+ ns_g_server->session_keyname,
+ DNS_SSUMATCHTYPE_LOCAL,
+ dns_zone_getorigin(zone),
+ 1, &any);
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ result = ISC_R_SUCCESS;
+ 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, ns_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, ns_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);
+ if (rdata == NULL)
+ return (ISC_R_NOMEMORY);
+ 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);
+ if (rdata == NULL) {
+ /*
+ * Already allocated data will be freed in the caller, so
+ * we can simply return here.
+ */
+ return (ISC_R_NOMEMORY);
+ }
+ 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, ns_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, ns_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);
+ if (rdata == NULL)
+ return (ISC_R_NOMEMORY);
+ 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_zone_setdb(zone, db);
+
+ 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);
+ result = configure_staticstub_serveraddrs(obj, zone,
+ &rdatalist_ns,
+ &rdatalist_a,
+ &rdatalist_aaaa);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zconfig, "server-names", &obj);
+ if (result == ISC_R_SUCCESS) {
+ INSIST(obj != NULL);
+ result = configure_staticstub_servernames(obj, zone,
+ &rdatalist_ns,
+ zname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ /*
+ * 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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_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).
+ */
+ result = dns_db_newversion(db, &dbversion);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_name_init(&apexname, NULL);
+ dns_name_clone(dns_zone_getorigin(zone), &apexname);
+ result = dns_db_findnode(db, &apexname, false, &apexnode);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Add NS RRset */
+ dns_rdataset_init(&rdataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset)
+ == ISC_R_SUCCESS);
+ result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
+ 0, NULL);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Add glue A RRset, if any */
+ if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset)
+ == ISC_R_SUCCESS);
+ result = dns_db_addrdataset(db, apexnode, dbversion, 0,
+ &rdataset, 0, NULL);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ /* Add glue AAAA RRset, if any */
+ if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa,
+ &rdataset)
+ == ISC_R_SUCCESS);
+ result = dns_db_addrdataset(db, apexnode, dbversion, 0,
+ &rdataset, 0, NULL);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (apexnode != NULL)
+ dns_db_detachnode(db, &apexnode);
+ if (dbversion != NULL)
+ dns_db_closeversion(db, &dbversion, true);
+ 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 inline 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 (ns_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 *));
+ if (*argvp == NULL)
+ return (ISC_R_NOMEMORY);
+ } 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 void
+checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
+ const cfg_obj_t **objp)
+{
+ const char *zone = NULL;
+ isc_result_t result;
+
+ switch (ztype) {
+ case dns_zone_slave: zone = "slave"; break;
+ case dns_zone_master: zone = "master"; break;
+ default:
+ INSIST(0);
+ }
+ result = ns_checknames_get(maps, zone, objp);
+ INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
+}
+
+isc_result_t
+ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
+ 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 *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;
+ bool check = false, fail = false;
+ bool warn = false, ignore = false;
+ bool ixfrdiff;
+ dns_masterformat_t masterformat;
+ const dns_master_style_t *masterstyle = &dns_master_style_default;
+ isc_stats_t *zoneqrystats;
+ dns_stats_t *rcvquerystats;
+ dns_zonestat_level_t statlevel;
+ int seconds;
+ dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
+ isc_dscp_t dscp;
+
+ 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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ if (vconfig != NULL)
+ RETERR(ns_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"));
+
+ RETERR(ns_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_master);
+ } 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)
+ return(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(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': both 'database' and 'dlz' "
+ "specified", zname);
+ return (ISC_R_FAILURE);
+ }
+
+ len = strlen(dlzname) + 5;
+ cpval = isc_mem_allocate(mctx, len);
+ if (cpval == NULL)
+ return (ISC_R_NOMEMORY);
+ 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);
+ return (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.
+ */
+ result = 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);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ 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 master zone
+ * will be needing a master file.
+ */
+ if (ztype == dns_zone_master && cpval == default_dbtype &&
+ filename == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': 'file' not specified",
+ zname);
+ return (ISC_R_FAILURE);
+ }
+
+ if (ztype == dns_zone_slave)
+ masterformat = dns_masterformat_raw;
+ else
+ masterformat = dns_masterformat_text;
+ obj = NULL;
+ result = ns_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 if (strcasecmp(masterformatstr, "map") == 0)
+ masterformat = dns_masterformat_map;
+ else
+ INSIST(0);
+ }
+
+ obj = NULL;
+ result = ns_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, ns_g_lctx, ISC_LOG_ERROR,
+ "zone '%s': 'masterfile-style' "
+ "can only be used with "
+ "'masterfile-format text'", zname);
+ return (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
+ INSIST(0);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-zone-ttl", &obj);
+ if (result == ISC_R_SUCCESS && masterformat == dns_masterformat_map) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': 'max-zone-ttl' is not compatible "
+ "with 'masterfile-format map'", zname);
+ return (ISC_R_FAILURE);
+ } else if (result == ISC_R_SUCCESS) {
+ dns_ttl_t maxttl = 0; /* unlimited */
+
+ if (cfg_obj_isuint32(obj))
+ maxttl = cfg_obj_asuint32(obj);
+ dns_zone_setmaxttl(zone, maxttl);
+ if (raw != NULL)
+ dns_zone_setmaxttl(raw, maxttl);
+ }
+
+ obj = NULL;
+ result = ns_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;
+
+ RETERR(dns_zone_setfile3(raw, filename,
+ masterformat, masterstyle));
+ signedname = isc_mem_get(mctx, signedlen);
+ if (signedname == NULL)
+ return (ISC_R_NOMEMORY);
+
+ (void)snprintf(signedname, signedlen, "%s" SIGNED, filename);
+ result = dns_zone_setfile3(zone, signedname,
+ dns_masterformat_raw, NULL);
+ isc_mem_put(mctx, signedname, signedlen);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else
+ RETERR(dns_zone_setfile3(zone, filename,
+ masterformat, masterstyle));
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "journal", &obj);
+ if (result == ISC_R_SUCCESS)
+ RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj)));
+
+ /*
+ * Notify messages are processed by the raw zone if it exists.
+ */
+ if (ztype == dns_zone_slave)
+ RETERR(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.
+ */
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_query, ac, zone,
+ dns_zone_setqueryacl,
+ dns_zone_clearqueryacl));
+
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_query_on, ac, zone,
+ dns_zone_setqueryonacl,
+ dns_zone_clearqueryonacl));
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+ }
+ if (raw != NULL)
+ dns_zone_setdialup(raw, dialup);
+ dns_zone_setdialup(zone, dialup);
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+ }
+ dns_zone_setstatlevel(zone, statlevel);
+
+ zoneqrystats = NULL;
+ rcvquerystats = NULL;
+ if (statlevel == dns_zonestat_full) {
+ RETERR(isc_stats_create(mctx, &zoneqrystats,
+ dns_nsstatscounter_max));
+ RETERR(dns_rdatatypestats_create(mctx,
+ &rcvquerystats));
+ }
+ dns_zone_setrequeststats(zone, zoneqrystats);
+ dns_zone_setrcvquerystats(zone, rcvquerystats);
+
+ if (zoneqrystats != NULL)
+ isc_stats_detach(&zoneqrystats);
+
+ if(rcvquerystats != NULL)
+ dns_stats_detach(&rcvquerystats);
+
+ /*
+ * Configure master functionality. This applies
+ * to primary masters (type "master") and slaves
+ * acting as masters (type "slave"), but not to stubs.
+ */
+ if (ztype != dns_zone_stub && ztype != dns_zone_staticstub &&
+ ztype != dns_zone_redirect) {
+ obj = NULL;
+ result = ns_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 *notifystr = cfg_obj_asstring(obj);
+ if (strcasecmp(notifystr, "explicit") == 0)
+ notifytype = dns_notifytype_explicit;
+ else if (strcasecmp(notifystr, "master-only") == 0)
+ notifytype = dns_notifytype_masteronly;
+ else
+ INSIST(0);
+ }
+ if (raw != NULL)
+ dns_zone_setnotifytype(raw, dns_notifytype_no);
+ dns_zone_setnotifytype(zone, notifytype);
+
+ obj = NULL;
+ result = ns_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_master)))
+ {
+ dns_ipkeylist_t ipkl;
+ dns_ipkeylist_init(&ipkl);
+
+ RETERR(ns_config_getipandkeylist(config, obj, mctx,
+ &ipkl));
+ result = dns_zone_setalsonotifydscpkeys(zone,
+ ipkl.addrs,
+ ipkl.dscps,
+ ipkl.keys,
+ ipkl.count);
+ dns_ipkeylist_clear(mctx, &ipkl);
+ RETERR(result);
+ } else
+ RETERR(dns_zone_setalsonotify(zone, NULL, 0));
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp == -1)
+ dscp = ns_g_dscp;
+ RETERR(dns_zone_setnotifysrc4dscp(zone, dscp));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp == -1)
+ dscp = ns_g_dscp;
+ RETERR(dns_zone_setnotifysrc6dscp(zone, dscp));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_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, ns_client_isself, NULL);
+
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_transfer, ac, zone,
+ dns_zone_setxfracl,
+ dns_zone_clearxfracl));
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-time-out", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-idle-out", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_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);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ journal_size = UINT32_MAX / 2;
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > UINT32_MAX / 2) {
+ cfg_obj_log(obj, ns_g_lctx,
+ ISC_LOG_ERROR,
+ "'max-journal-size "
+ "%" PRId64 "' "
+ "is too large",
+ value);
+ RETERR(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 = ns_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), "master") &&
+ ztype == dns_zone_master)
+ ixfrdiff = true;
+ else if (!strcasecmp(cfg_obj_asstring(obj), "slave") &&
+ ztype == dns_zone_slave)
+ 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 = ns_config_get(maps, "request-expire", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "request-ixfr", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj));
+
+ 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
+ INSIST(0);
+ 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 = ns_config_get(maps, "notify-delay", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_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 = ns_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
+ INSIST(0);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
+
+ obj = NULL;
+ result = ns_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 = ns_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 = ns_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);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ journal_size = UINT32_MAX / 2;
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > UINT32_MAX / 2) {
+ cfg_obj_log(obj, ns_g_lctx,
+ ISC_LOG_ERROR,
+ "'max-journal-size "
+ "%" PRId64 "' "
+ "is too large",
+ value);
+ RETERR(ISC_R_RANGE);
+ }
+ journal_size = (uint32_t)value;
+ }
+ dns_zone_setjournalsize(zone, journal_size);
+ }
+
+ /*
+ * Configure update-related options. These apply to
+ * primary masters only.
+ */
+ if (ztype == dns_zone_master) {
+ dns_acl_t *updateacl;
+
+ RETERR(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(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "zone '%s' allows unsigned updates "
+ "from remote hosts, which is insecure",
+ zname);
+
+ RETERR(configure_zone_ssutable(zoptions, mayberaw, zname));
+ }
+
+ if (ztype == dns_zone_master || raw != NULL) {
+ const cfg_obj_t *validity, *resign;
+ bool allow = false, maint = false;
+
+ obj = NULL;
+ result = ns_config_get(maps, "sig-validity-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+
+ validity = cfg_tuple_get(obj, "validity");
+ seconds = cfg_obj_asuint32(validity);
+ if (!ns_g_sigvalinsecs) {
+ seconds *= 86400;
+ }
+ dns_zone_setsigvalidityinterval(zone, seconds);
+
+ resign = cfg_tuple_get(obj, "re-sign");
+ if (cfg_obj_isvoid(resign)) {
+ seconds /= 4;
+ } else if (!ns_g_sigvalinsecs) {
+ if (seconds > 7 * 86400) {
+ seconds = cfg_obj_asuint32(resign) * 86400;
+ } else {
+ seconds = cfg_obj_asuint32(resign) * 3600;
+ }
+ } else {
+ seconds = cfg_obj_asuint32(resign);
+ }
+ dns_zone_setsigresigninginterval(zone, seconds);
+
+ obj = NULL;
+ result = ns_config_get(maps, "key-directory", &obj);
+ if (result == ISC_R_SUCCESS) {
+ filename = cfg_obj_asstring(obj);
+ RETERR(dns_zone_setkeydirectory(zone, filename));
+ }
+
+ obj = NULL;
+ result = ns_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 = ns_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 = ns_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 = ns_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));
+
+ obj = NULL;
+ result = ns_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));
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-loadkeys-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setrefreshkeyinterval(zone,
+ cfg_obj_asuint32(obj)));
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "auto-dnssec", &obj);
+ 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)
+ ;
+ else
+ INSIST(0);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
+ }
+ }
+
+ if (ztype == dns_zone_slave) {
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_update_forwarding, ac,
+ mayberaw, dns_zone_setforwardacl,
+ dns_zone_clearforwardacl));
+ }
+
+ /*%
+ * Primary master functionality.
+ */
+ if (ztype == dns_zone_master) {
+ obj = NULL;
+ result = ns_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);
+
+ /*
+ * With map files, the default is ignore duplicate
+ * records. With other master formats, the default is
+ * taken from the global configuration.
+ */
+ obj = NULL;
+ if (masterformat != dns_masterformat_map) {
+ result = ns_config_get(maps, "check-dup-records", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dupcheck = cfg_obj_asstring(obj);
+ } else {
+ result = ns_config_get(nodefault, "check-dup-records",
+ &obj);
+ if (result == ISC_R_SUCCESS)
+ dupcheck = cfg_obj_asstring(obj);
+ else
+ dupcheck = "ignore";
+
+ }
+ 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
+ INSIST(0);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail);
+
+ /*
+ * With map files, the default is *not* to check
+ * integrity. With other master formats, the default is
+ * taken from the global configuration.
+ */
+ obj = NULL;
+ if (masterformat != dns_masterformat_map) {
+ result = ns_config_get(maps, "check-integrity", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
+ cfg_obj_asboolean(obj));
+ } else {
+ check = false;
+ result = ns_config_get(nodefault, "check-integrity",
+ &obj);
+ if (result == ISC_R_SUCCESS)
+ check = cfg_obj_asboolean(obj);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
+ check);
+ }
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
+
+ obj = NULL;
+ result = ns_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
+ INSIST(0);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME,
+ ignore);
+
+ obj = NULL;
+ result = ns_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)
+ ;
+ else
+ INSIST(0);
+ }
+
+ obj = NULL;
+ result = ns_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 slave functionality.
+ */
+ switch (ztype) {
+ case dns_zone_slave:
+ case dns_zone_stub:
+ case dns_zone_redirect:
+ count = 0;
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "masters", &obj);
+ if (obj != NULL) {
+ dns_ipkeylist_t ipkl;
+ dns_ipkeylist_init(&ipkl);
+
+ RETERR(ns_config_getipandkeylist(config, obj, mctx,
+ &ipkl));
+ result = dns_zone_setmasterswithkeys(mayberaw,
+ ipkl.addrs,
+ ipkl.keys,
+ ipkl.count);
+ count = ipkl.count;
+ dns_ipkeylist_clear(mctx, &ipkl);
+ RETERR(result);
+ } else
+ result = dns_zone_setmasters(mayberaw, NULL, 0);
+ RETERR(result);
+
+ multi = false;
+ if (count > 1) {
+ obj = NULL;
+ result = ns_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 = ns_config_get(maps, "max-transfer-time-in", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-idle-in", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_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 = ns_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 = ns_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 = ns_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 = ns_config_get(maps, "transfer-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setxfrsource4(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp == -1)
+ dscp = ns_g_dscp;
+ RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "transfer-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setxfrsource6(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp == -1)
+ dscp = ns_g_dscp;
+ RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "alt-transfer-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setaltxfrsource4(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp == -1)
+ dscp = ns_g_dscp;
+ RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp));
+
+ obj = NULL;
+ result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ RETERR(dns_zone_setaltxfrsource6(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ dscp = cfg_obj_getdscp(obj);
+ if (dscp == -1)
+ dscp = ns_g_dscp;
+ RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp));
+
+ obj = NULL;
+ (void)ns_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)ns_config_get(maps, "try-tcp-refresh", &obj);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH,
+ cfg_obj_asboolean(obj));
+ break;
+
+ case dns_zone_staticstub:
+ RETERR(configure_staticstub(zoptions, zone, zname,
+ default_dbtype));
+ break;
+
+ default:
+ break;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+
+/*
+ * Set up a DLZ zone as writeable
+ */
+isc_result_t
+ns_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
+ns_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;
+ 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;
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "inline-signing", &obj);
+ if ((obj == NULL || !cfg_obj_asboolean(obj)) && has_raw) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "not reusable: old zone was inline-signing");
+ return (false);
+ } else if ((obj != NULL && cfg_obj_asboolean(obj)) && !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);
+}
diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in
new file mode 100644
index 0000000..0276f69
--- /dev/null
+++ b/bin/nsupdate/Makefile.in
@@ -0,0 +1,95 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.36 2009/12/05 23:31:40 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+READLINE_LIB = @READLINE_LIB@
+
+DST_GSSAPI_INC = @DST_GSSAPI_INC@
+
+CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} \
+ ${BIND9_INCLUDES} ${ISC_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${DST_GSSAPI_INC} @DST_OPENSSL_INC@
+
+CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@ @USE_GSSAPI@
+CWARNINGS =
+
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
+
+NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = nsupdate@EXEEXT@
+
+OBJS = nsupdate.@O@
+
+UOBJS =
+
+SRCS = nsupdate.c
+
+MANPAGES = nsupdate.1
+
+HTMLPAGES = nsupdate.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+nsupdate.@O@: nsupdate.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\" \
+ -c ${srcdir}/nsupdate.c
+
+nsupdate@EXEEXT@: nsupdate.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="nsupdate.@O@ ${READLINE_LIB} ${UOBJS}"; \
+ ${FINALBUILDCMD}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+
+install:: nsupdate@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsupdate@EXEEXT@ ${DESTDIR}${bindir}
+ ${INSTALL_DATA} ${srcdir}/nsupdate.1 ${DESTDIR}${mandir}/man1
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man1/nsupdate.1
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/nsupdate@EXEEXT@
diff --git a/bin/nsupdate/nsupdate.1 b/bin/nsupdate/nsupdate.1
new file mode 100644
index 0000000..28f6191
--- /dev/null
+++ b/bin/nsupdate/nsupdate.1
@@ -0,0 +1,524 @@
+.\" Copyright (C) 2000-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: nsupdate
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-04-18
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NSUPDATE" "1" "2014\-04\-18" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nsupdate \- Dynamic DNS update utility
+.SH "SYNOPSIS"
+.HP \w'\fBnsupdate\fR\ 'u
+\fBnsupdate\fR [\fB\-d\fR] [\fB\-D\fR] [\fB\-i\fR] [\fB\-L\ \fR\fB\fIlevel\fR\fR] [[\fB\-g\fR] | [\fB\-o\fR] | [\fB\-l\fR] | [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIkeyname:secret\fR\fR] | [\fB\-k\ \fR\fB\fIkeyfile\fR\fR]] [\fB\-t\ \fR\fB\fItimeout\fR\fR] [\fB\-u\ \fR\fB\fIudptimeout\fR\fR] [\fB\-r\ \fR\fB\fIudpretries\fR\fR] [\fB\-R\ \fR\fB\fIrandomdev\fR\fR] [\fB\-v\fR] [\fB\-T\fR] [\fB\-P\fR] [\fB\-V\fR] [filename]
+.SH "DESCRIPTION"
+.PP
+\fBnsupdate\fR
+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\&.
+.PP
+Zones that are under dynamic control via
+\fBnsupdate\fR
+or a DHCP server should not be edited by hand\&. Manual edits could conflict with dynamic updates and cause data to be lost\&.
+.PP
+The resource records that are dynamically added or removed with
+\fBnsupdate\fR
+have to be in the same zone\&. Requests are sent to the zone\*(Aqs master server\&. This is identified by the MNAME field of the zone\*(Aqs SOA record\&.
+.PP
+Transaction signatures can be used to authenticate the Dynamic DNS updates\&. These use the TSIG resource record type described in RFC 2845 or the SIG(0) record described in RFC 2535 and RFC 2931 or GSS\-TSIG as described in RFC 3645\&.
+.PP
+TSIG relies on a shared secret that should only be known to
+\fBnsupdate\fR
+and the name server\&. For instance, suitable
+\fBkey\fR
+and
+\fBserver\fR
+statements would be added to
+/etc/named\&.conf
+so that the name server can associate the appropriate secret key and algorithm with the IP address of the client application that will be using TSIG authentication\&. You can use
+\fBddns\-confgen\fR
+to generate suitable configuration fragments\&.
+\fBnsupdate\fR
+uses the
+\fB\-y\fR
+or
+\fB\-k\fR
+options to provide the TSIG shared secret\&. These options are mutually exclusive\&.
+.PP
+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\&.
+.PP
+GSS\-TSIG uses Kerberos credentials\&. Standard GSS\-TSIG mode is switched on with the
+\fB\-g\fR
+flag\&. A non\-standards\-compliant variant of GSS\-TSIG used by Windows 2000 can be switched on with the
+\fB\-o\fR
+flag\&.
+.SH "OPTIONS"
+.PP
+\-d
+.RS 4
+Debug mode\&. This provides tracing information about the update requests that are made and the replies received from the name server\&.
+.RE
+.PP
+\-D
+.RS 4
+Extra debug mode\&.
+.RE
+.PP
+\-i
+.RS 4
+Force interactive mode, even when standard input is not a terminal\&.
+.RE
+.PP
+\-k \fIkeyfile\fR
+.RS 4
+The file containing the TSIG authentication key\&. Keyfiles may be in two formats: a single file containing a
+named\&.conf\-format
+\fBkey\fR
+statement, which may be generated automatically by
+\fBddns\-confgen\fR, 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
+\fBdnssec\-keygen\fR\&. The
+\fB\-k\fR
+may 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\&.
+.RE
+.PP
+\-l
+.RS 4
+Local\-host only mode\&. This sets the server address to localhost (disabling the
+\fBserver\fR
+so that the server address cannot be overridden)\&. Connections to the local server will use a TSIG key found in
+/var/run/named/session\&.key, which is automatically generated by
+\fBnamed\fR
+if any local master zone has set
+\fBupdate\-policy\fR
+to
+\fBlocal\fR\&. The location of this key file can be overridden with the
+\fB\-k\fR
+option\&.
+.RE
+.PP
+\-L \fIlevel\fR
+.RS 4
+Set the logging debug level\&. If zero, logging is disabled\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Set the port to use for connections to a name server\&. The default is 53\&.
+.RE
+.PP
+\-P
+.RS 4
+Print the list of private BIND\-specific resource record types whose format is understood by
+\fBnsupdate\fR\&. See also the
+\fB\-T\fR
+option\&.
+.RE
+.PP
+\-r \fIudpretries\fR
+.RS 4
+The number of UDP retries\&. The default is 3\&. If zero, only one update request will be made\&.
+.RE
+.PP
+\-R \fIrandomdev\fR
+.RS 4
+Where to obtain randomness\&. If the operating system does not provide a
+/dev/random
+or equivalent device, the default source of randomness is keyboard input\&.
+randomdev
+specifies the name of a character device or file containing random data to be used instead of the default\&. The special value
+keyboard
+indicates that keyboard input should be used\&. This option may be specified multiple times\&.
+.RE
+.PP
+\-t \fItimeout\fR
+.RS 4
+The maximum time an update request can take before it is aborted\&. The default is 300 seconds\&. Zero can be used to disable the timeout\&.
+.RE
+.PP
+\-T
+.RS 4
+Print the list of IANA standard resource record types whose format is understood by
+\fBnsupdate\fR\&.
+\fBnsupdate\fR
+will exit after the lists are printed\&. The
+\fB\-T\fR
+option can be combined with the
+\fB\-P\fR
+option\&.
+.sp
+Other types can be entered using "TYPEXXXXX" where "XXXXX" is the decimal value of the type with no leading zeros\&. The rdata, if present, will be parsed using the UNKNOWN rdata format, (<backslash> <hash> <space> <length> <space> <hexstring>)\&.
+.RE
+.PP
+\-u \fIudptimeout\fR
+.RS 4
+The UDP retry interval\&. The default is 3 seconds\&. If zero, the interval will be computed from the timeout interval and number of UDP retries\&.
+.RE
+.PP
+\-v
+.RS 4
+Use TCP even for small update requests\&. By default,
+\fBnsupdate\fR
+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 will be used\&. TCP may be preferable when a batch of update requests is made\&.
+.RE
+.PP
+\-V
+.RS 4
+Print the version number and exit\&.
+.RE
+.PP
+\-y \fI[hmac:]\fR\fIkeyname:secret\fR
+.RS 4
+Literal TSIG authentication key\&.
+\fIkeyname\fR
+is the name of the key, and
+\fIsecret\fR
+is the base64 encoded shared secret\&.
+\fIhmac\fR
+is the name of the key algorithm; valid choices are
+hmac\-md5,
+hmac\-sha1,
+hmac\-sha224,
+hmac\-sha256,
+hmac\-sha384, or
+hmac\-sha512\&. If
+\fIhmac\fR
+is not specified, the default is
+hmac\-md5
+or if MD5 was disabled
+hmac\-sha256\&.
+.sp
+NOTE: Use of the
+\fB\-y\fR
+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
+\fBps\fR(1)
+or in a history file maintained by the user\*(Aqs shell\&.
+.RE
+.SH "INPUT FORMAT"
+.PP
+\fBnsupdate\fR
+reads input from
+\fIfilename\fR
+or standard input\&. Each command is supplied on exactly one line of input\&. Some commands are for administrative purposes\&. The 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 will be rejected if the tests for the prerequisite conditions fail\&.
+.PP
+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 present or missing from the zone\&. A blank input line (or the
+\fBsend\fR
+command) causes the accumulated commands to be sent as one Dynamic DNS update request to the name server\&.
+.PP
+The command formats and their meaning are as follows:
+.PP
+\fBserver\fR {servername} [port]
+.RS 4
+Sends all dynamic update requests to the name server
+\fIservername\fR\&. When no server statement is provided,
+\fBnsupdate\fR
+will send updates to the master server of the correct zone\&. The MNAME field of that zone\*(Aqs SOA record will identify the master server for that zone\&.
+\fIport\fR
+is the port number on
+\fIservername\fR
+where the dynamic update requests get sent\&. If no port number is specified, the default DNS port number of 53 is used\&.
+.RE
+.PP
+\fBlocal\fR {address} [port]
+.RS 4
+Sends all dynamic update requests using the local
+\fIaddress\fR\&. When no local statement is provided,
+\fBnsupdate\fR
+will send updates using an address and port chosen by the system\&.
+\fIport\fR
+can additionally be used to make requests come from a specific port\&. If no port number is specified, the system will assign one\&.
+.RE
+.PP
+\fBzone\fR {zonename}
+.RS 4
+Specifies that all updates are to be made to the zone
+\fIzonename\fR\&. If no
+\fIzone\fR
+statement is provided,
+\fBnsupdate\fR
+will attempt determine the correct zone to update based on the rest of the input\&.
+.RE
+.PP
+\fBclass\fR {classname}
+.RS 4
+Specify the default class\&. If no
+\fIclass\fR
+is specified, the default class is
+\fIIN\fR\&.
+.RE
+.PP
+\fBttl\fR {seconds}
+.RS 4
+Specify the default time to live for records to be added\&. The value
+\fInone\fR
+will clear the default ttl\&.
+.RE
+.PP
+\fBkey\fR [hmac:] {keyname} {secret}
+.RS 4
+Specifies that all updates are to be TSIG\-signed using the
+\fIkeyname\fR\fIsecret\fR
+pair\&. If
+\fIhmac\fR
+is specified, then it sets the signing algorithm in use; the default is
+hmac\-md5
+or if MD5 was disabled
+hmac\-sha256\&. The
+\fBkey\fR
+command overrides any key specified on the command line via
+\fB\-y\fR
+or
+\fB\-k\fR\&.
+.RE
+.PP
+\fBgsstsig\fR
+.RS 4
+Use GSS\-TSIG to sign the updated\&. This is equivalent to specifying
+\fB\-g\fR
+on the command line\&.
+.RE
+.PP
+\fBoldgsstsig\fR
+.RS 4
+Use the Windows 2000 version of GSS\-TSIG to sign the updated\&. This is equivalent to specifying
+\fB\-o\fR
+on the command line\&.
+.RE
+.PP
+\fBrealm\fR {[realm_name]}
+.RS 4
+When using GSS\-TSIG use
+\fIrealm_name\fR
+rather than the default realm in
+krb5\&.conf\&. If no realm is specified the saved realm is cleared\&.
+.RE
+.PP
+\fBcheck\-names\fR {[yes_or_no]}
+.RS 4
+Turn 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 will not be added to the UPDATE message\&.
+.RE
+.PP
+\fB[prereq]\fR\fB nxdomain\fR {domain\-name}
+.RS 4
+Requires that no resource record of any type exists with name
+\fIdomain\-name\fR\&.
+.RE
+.PP
+\fB[prereq]\fR\fB yxdomain\fR {domain\-name}
+.RS 4
+Requires that
+\fIdomain\-name\fR
+exists (has as at least one resource record, of any type)\&.
+.RE
+.PP
+\fB[prereq]\fR\fB nxrrset\fR {domain\-name} [class] {type}
+.RS 4
+Requires that no resource record exists of the specified
+\fItype\fR,
+\fIclass\fR
+and
+\fIdomain\-name\fR\&. If
+\fIclass\fR
+is omitted, IN (internet) is assumed\&.
+.RE
+.PP
+\fB[prereq]\fR\fB yxrrset\fR {domain\-name} [class] {type}
+.RS 4
+This requires that a resource record of the specified
+\fItype\fR,
+\fIclass\fR
+and
+\fIdomain\-name\fR
+must exist\&. If
+\fIclass\fR
+is omitted, IN (internet) is assumed\&.
+.RE
+.PP
+\fB[prereq]\fR\fB yxrrset\fR {domain\-name} [class] {type} {data...}
+.RS 4
+The
+\fIdata\fR
+from each set of prerequisites of this form sharing a common
+\fItype\fR,
+\fIclass\fR, and
+\fIdomain\-name\fR
+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
+\fItype\fR,
+\fIclass\fR, and
+\fIdomain\-name\fR\&. The
+\fIdata\fR
+are written in the standard text representation of the resource record\*(Aqs RDATA\&.
+.RE
+.PP
+\fB[update]\fR\fB del\fR\fB[ete]\fR {domain\-name} [ttl] [class] [type\ [data...]]
+.RS 4
+Deletes any resource records named
+\fIdomain\-name\fR\&. If
+\fItype\fR
+and
+\fIdata\fR
+is provided, only matching resource records will be removed\&. The internet class is assumed if
+\fIclass\fR
+is not supplied\&. The
+\fIttl\fR
+is ignored, and is only allowed for compatibility\&.
+.RE
+.PP
+\fB[update]\fR\fB add\fR {domain\-name} {ttl} [class] {type} {data...}
+.RS 4
+Adds a new resource record with the specified
+\fIttl\fR,
+\fIclass\fR
+and
+\fIdata\fR\&.
+.RE
+.PP
+\fBshow\fR
+.RS 4
+Displays the current message, containing all of the prerequisites and updates specified since the last send\&.
+.RE
+.PP
+\fBsend\fR
+.RS 4
+Sends the current message\&. This is equivalent to entering a blank line\&.
+.RE
+.PP
+\fBanswer\fR
+.RS 4
+Displays the answer\&.
+.RE
+.PP
+\fBdebug\fR
+.RS 4
+Turn on debugging\&.
+.RE
+.PP
+\fBversion\fR
+.RS 4
+Print version number\&.
+.RE
+.PP
+\fBhelp\fR
+.RS 4
+Print a list of commands\&.
+.RE
+.PP
+Lines beginning with a semicolon are comments and are ignored\&.
+.SH "EXAMPLES"
+.PP
+The examples below show how
+\fBnsupdate\fR
+could be used to insert and delete resource records from the
+\fBexample\&.com\fR
+zone\&. Notice that the input in each example contains a trailing blank line so that a group of commands are sent as one dynamic update request to the master name server for
+\fBexample\&.com\fR\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nsupdate
+> update delete oldhost\&.example\&.com A
+> update add newhost\&.example\&.com 86400 A 172\&.16\&.1\&.1
+> send
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+Any A records for
+\fBoldhost\&.example\&.com\fR
+are deleted\&. And an A record for
+\fBnewhost\&.example\&.com\fR
+with IP address 172\&.16\&.1\&.1 is added\&. The newly\-added record has a 1 day TTL (86400 seconds)\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nsupdate
+> prereq nxdomain nickname\&.example\&.com
+> update add nickname\&.example\&.com 86400 CNAME somehost\&.example\&.com
+> send
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+The prerequisite condition gets the name server to check that there are no resource records of any type for
+\fBnickname\&.example\&.com\fR\&. 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\&.)
+.SH "FILES"
+.PP
+\fB/etc/resolv\&.conf\fR
+.RS 4
+used to identify default name server
+.RE
+.PP
+\fB/var/run/named/session\&.key\fR
+.RS 4
+sets the default TSIG key for use in local\-only mode
+.RE
+.PP
+\fBK{name}\&.+157\&.+{random}\&.key\fR
+.RS 4
+base\-64 encoding of HMAC\-MD5 key created by
+\fBdnssec-keygen\fR(8)\&.
+.RE
+.PP
+\fBK{name}\&.+157\&.+{random}\&.private\fR
+.RS 4
+base\-64 encoding of HMAC\-MD5 key created by
+\fBdnssec-keygen\fR(8)\&.
+.RE
+.SH "SEE ALSO"
+.PP
+RFC 2136,
+RFC 3007,
+RFC 2104,
+RFC 2845,
+RFC 1034,
+RFC 2535,
+RFC 2931,
+\fBnamed\fR(8),
+\fBddns-confgen\fR(8),
+\fBdnssec-keygen\fR(8)\&.
+.SH "BUGS"
+.PP
+The TSIG key is redundantly stored in two separate files\&. This is a consequence of nsupdate using the DST library for its cryptographic operations, and may change in future releases\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
new file mode 100644
index 0000000..8d1da3b
--- /dev/null
+++ b/bin/nsupdate/nsupdate.c
@@ -0,0 +1,3318 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/site.h>
+
+#include <isccfg/namedconf.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/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/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+#ifdef GSSAPI
+#include <dst/gssapi.h>
+#ifdef WIN32
+#include <krb5/krb5.h>
+#else
+#include ISC_PLATFORM_KRB5HEADER
+#endif
+#endif
+#include <bind9/getaddresses.h>
+
+#if defined(HAVE_READLINE)
+#if defined(HAVE_EDIT_READLINE_READLINE_H)
+#include <edit/readline/readline.h>
+#if defined(HAVE_EDIT_READLINE_HISTORY_H)
+#include <edit/readline/history.h>
+#endif
+#elif defined(HAVE_EDITLINE_READLINE_H)
+#include <editline/readline.h>
+#else
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+#endif
+
+#ifdef HAVE_ADDRINFO
+#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GAISTRERROR
+#define USE_GETADDRINFO
+#endif
+#endif
+#endif
+
+#ifndef USE_GETADDRINFO
+#ifndef ISC_PLATFORM_NONSTDHERRNO
+extern int h_errno;
+#endif
+#endif
+
+#define MAXCMD (128 * 1024)
+#define MAXWIRE (64 * 1024)
+#define PACKETSIZE ((64 * 1024) - 1)
+#define INITTEXT (2 * 1024)
+#define MAXTEXT (128 * 1024)
+#define FIND_TIMEOUT 5
+#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
+
+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_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 isc_socketmgr_t *socketmgr = NULL;
+static isc_timermgr_t *timermgr = 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;
+static dns_name_t restart_master;
+static dns_tsig_keyring_t *gssring = NULL;
+static dns_tsigkey_t *tsigkey = NULL;
+static dst_key_t *sig0key = NULL;
+static lwres_context_t *lwctx = NULL;
+static lwres_conf_t *lwconf;
+static isc_sockaddr_t *servers = NULL;
+static isc_sockaddr_t *master_servers = NULL;
+static bool default_servers = true;
+static int ns_inuse = 0;
+static int master_inuse = 0;
+static int ns_total = 0;
+static int ns_alloc = 0;
+static int master_total = 0;
+static int master_alloc = 0;
+static isc_sockaddr_t *localaddr4 = NULL;
+static isc_sockaddr_t *localaddr6 = NULL;
+static const char *keyfile = NULL;
+static char *keystr = NULL;
+static isc_entropy_t *entropy = 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 dns_message_t *answer = NULL;
+static uint32_t default_ttl = 0;
+static bool default_ttl_set = false;
+static bool checknames = true;
+
+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 *master);
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+static void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+#ifdef 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();
+static void
+start_gssrequest(dns_name_t *master);
+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 /* 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
+
+typedef struct entropysource entropysource_t;
+
+struct entropysource {
+ isc_entropysource_t *source;
+ isc_mem_t *mctx;
+ ISC_LINK(entropysource_t) link;
+};
+
+static ISC_LIST(entropysource_t) sources;
+
+static void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
+ isc_result_t result;
+ isc_entropysource_t *source = NULL;
+ entropysource_t *elt;
+ int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
+
+ REQUIRE(ectx != NULL);
+
+ if (*ectx == NULL) {
+ result = isc_entropy_create(mctx, ectx);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create entropy object");
+ ISC_LIST_INIT(sources);
+ }
+
+ if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+ usekeyboard = ISC_ENTROPY_KEYBOARDYES;
+ randomfile = NULL;
+ }
+
+ result = isc_entropy_usebestsource(*ectx, &source, randomfile,
+ usekeyboard);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize entropy source: %s",
+ isc_result_totext(result));
+
+ if (source != NULL) {
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ fatal("out of memory");
+ elt->source = source;
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ ISC_LIST_APPEND(sources, elt, link);
+ }
+}
+
+static void
+cleanup_entropy(isc_entropy_t **ectx) {
+ entropysource_t *source;
+ while (!ISC_LIST_EMPTY(sources)) {
+ source = ISC_LIST_HEAD(sources);
+ ISC_LIST_UNLINK(sources, source, link);
+ isc_entropy_destroysource(&source->source);
+ isc_mem_put(source->mctx, source, sizeof(*source));
+ }
+ isc_entropy_detach(ectx);
+}
+
+static void
+master_from_servers(void) {
+
+ if (master_servers != NULL && master_servers != servers)
+ isc_mem_put(gmctx, master_servers,
+ master_alloc * sizeof(isc_sockaddr_t));
+ master_servers = servers;
+ master_total = ns_total;
+ master_alloc = ns_alloc;
+ master_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 inline void
+check_result(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS)
+ fatal("%s: %s", msg, isc_result_totext(result));
+}
+
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+static char *
+nsu_strsep(char **stringp, const char *delim) {
+ char *string = *stringp;
+ 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);
+ }
+ }
+ }
+ *stringp = NULL;
+ return (string);
+}
+
+static void
+reset_system(void) {
+ isc_result_t result;
+
+ ddebug("reset_system()");
+ /* If the update message is still around, destroy it */
+ if (updatemsg != NULL)
+ dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
+ else {
+ result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER,
+ &updatemsg);
+ check_result(result, "dns_message_create");
+ }
+ 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(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)));
+
+#ifndef PK11_MD5_DISABLE
+ 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
+#endif
+ 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;
+ 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 {
+#ifndef PK11_MD5_DISABLE
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+#else
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+#endif
+ 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);
+ if (secret == NULL)
+ fatal("out of memory");
+
+ 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, dns_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);
+ if (keystr == NULL)
+ fatal("out of memory");
+ 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;
+ 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)) {
+#ifndef PK11_MD5_DISABLE
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+#endif
+ 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 master_servers must be before the
+ * isc_mem_put of servers as it sets the servers pointer
+ * to NULL.
+ */
+ if (master_servers != NULL && master_servers != servers)
+ isc_mem_put(gmctx, master_servers,
+ master_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_destroy(&updatemsg);
+
+ if (is_dst_up) {
+ ddebug("Destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = false;
+ }
+
+ cleanup_entropy(&entropy);
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ 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_destroy(&dispatchmgr);
+
+}
+
+static void
+maybeshutdown(void) {
+ 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();
+}
+
+static void
+setup_system(void) {
+ isc_result_t result;
+ isc_sockaddr_t bind_any, bind_any6;
+ lwres_result_t lwresult;
+ unsigned int attrs, attrmask;
+ int i;
+ isc_logconfig_t *logconfig = NULL;
+
+ ddebug("setup_system()");
+
+ dns_result_register();
+
+ 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_ipv4 && !have_ipv6)
+ fatal("could not find either IPv4 or IPv6");
+
+ result = isc_log_create(gmctx, &glctx, &logconfig);
+ check_result(result, "isc_log_create");
+
+ 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);
+
+ lwresult = lwres_context_create(&lwctx, gmctx, mem_alloc, mem_free, 1);
+ if (lwresult != LWRES_R_SUCCESS)
+ fatal("lwres_context_create failed");
+
+ (void)lwres_conf_parse(lwctx, RESOLV_CONF);
+ lwconf = lwres_conf_get(lwctx);
+
+ if (servers != NULL) {
+ if (master_servers == servers)
+ master_servers = NULL;
+ isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
+ }
+
+ ns_inuse = 0;
+ if (local_only || lwconf->nsnext <= 0) {
+ 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 (servers == NULL)
+ fatal("out of memory");
+
+ if (have_ipv4) {
+ in.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&servers[0], &in, dnsport);
+ }
+ if (have_ipv6) {
+ memset(&in6, 0, sizeof(in6));
+ in6.s6_addr[15] = 1;
+ isc_sockaddr_fromin6(&servers[(have_ipv4 ? 1 : 0)],
+ &in6, dnsport);
+ }
+ } else {
+ ns_total = ns_alloc = lwconf->nsnext;
+ servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
+ if (servers == NULL)
+ fatal("out of memory");
+ for (i = 0; i < ns_total; i++) {
+ if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4)
+ {
+ struct in_addr in4;
+ memmove(&in4,
+ lwconf->nameservers[i].address, 4);
+ isc_sockaddr_fromin(&servers[i],
+ &in4, dnsport);
+ } else {
+ struct in6_addr in6;
+ memmove(&in6,
+ lwconf->nameservers[i].address, 16);
+ isc_sockaddr_fromin6(&servers[i],
+ &in6, dnsport);
+ }
+ }
+ }
+
+ setup_entropy(gmctx, NULL, &entropy);
+
+ result = isc_hash_create(gmctx, entropy, DNS_NAME_MAXWIRE);
+ check_result(result, "isc_hash_create");
+ isc_hash_init();
+
+ result = dns_dispatchmgr_create(gmctx, entropy, &dispatchmgr);
+ check_result(result, "dns_dispatchmgr_create");
+
+ result = isc_socketmgr_create(gmctx, &socketmgr);
+ check_result(result, "dns_socketmgr_create");
+
+ result = isc_timermgr_create(gmctx, &timermgr);
+ check_result(result, "dns_timermgr_create");
+
+ result = isc_taskmgr_create(gmctx, 1, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_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, entropy, 0);
+ check_result(result, "dst_lib_init");
+ is_dst_up = true;
+
+ attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
+
+ if (have_ipv6) {
+ attrs = DNS_DISPATCHATTR_UDP;
+ attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ isc_sockaddr_any6(&bind_any6);
+ result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any6, PACKETSIZE,
+ 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv6);
+ check_result(result, "dns_dispatch_getudp (v6)");
+ }
+
+ if (have_ipv4) {
+ attrs = DNS_DISPATCHATTR_UDP;
+ attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ isc_sockaddr_any(&bind_any);
+ result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, PACKETSIZE,
+ 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4);
+ check_result(result, "dns_dispatch_getudp (v4)");
+ }
+
+ result = dns_requestmgr_create(gmctx, timermgr,
+ socketmgr, 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);
+}
+
+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) {
+ fputs("nsupdate " VERSION "\n", stderr);
+}
+
+#define PARSE_ARGS_FMT "dDML:y:ghilovk:p:Pr:R::t:Tu:V"
+
+static void
+pre_parse_args(int argc, char **argv) {
+ dns_rdatatype_t t;
+ int ch;
+ char buf[100];
+ bool doexit = 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 '?':
+ case 'h':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ argv[0], isc_commandline_option);
+ fprintf(stderr, "usage: nsupdate [-dDi] [-L level] [-l]"
+ "[-g | -o | -y keyname:secret | -k keyfile] "
+ "[-v] [-V] [-P] [-T] [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, isc_mem_t *mctx, isc_entropy_t **ectx) {
+ 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 '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);
+ }
+ if (udp_timeout == 0)
+ udp_timeout = UINT_MAX;
+ 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':
+ setup_entropy(mctx, isc_commandline_argument, ectx);
+ 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);
+ }
+
+#ifdef GSSAPI
+ if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
+ fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
+ argv[0]);
+ exit(1);
+ }
+#else
+ if (usegsstsig) {
+ fprintf(stderr, "%s: cannot specify -g or -o, " \
+ "program not linked with GSS API Library\n",
+ argv[0]);
+ exit(1);
+ }
+#endif
+
+ 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 *namebuf = NULL;
+ 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");
+ result = isc_buffer_allocate(gmctx, &namebuf, DNS_NAME_MAXWIRE);
+ check_result(result, "isc_buffer_allocate");
+ dns_name_init(*namep, NULL);
+ dns_name_setbuffer(*namep, namebuf);
+ dns_message_takebuffer(msg, &namebuf);
+ 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");
+ result = isc_buffer_allocate(gmctx, &buf, MAXWIRE);
+ check_result(result, "isc_buffer_allocate");
+ 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);
+ result = isc_buffer_allocate(gmctx, &newbuf, r.length);
+ check_result(result, "isc_buffer_allocate");
+ 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 (master_servers == servers)
+ master_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));
+ if (servers == NULL)
+ fatal("out of memory");
+
+ 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));
+ if (localaddr6 == NULL)
+ fatal("out of memory");
+ 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));
+ if (localaddr4 == NULL)
+ fatal("out of memory");
+ 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;
+ 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
+#ifndef PK11_MD5_DISABLE
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+#else
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+#endif
+
+ 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);
+ if (secret == NULL)
+ fatal("out of memory");
+
+ 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, dns_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) {
+#ifdef 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);
+ if (realm == NULL)
+ fatal("out of memory");
+ return (STATUS_MORE);
+#else
+ UNUSED(cmdline);
+ return (STATUS_SYNTAX);
+#endif
+}
+
+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;
+ }
+ }
+
+ 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_init(name, NULL);
+ 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);
+ result = isc_buffer_allocate(gmctx, &buf, bufsz);
+ check_result(result, "isc_buffer_allocate");
+ 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) {
+ if (answer != NULL)
+ show_message(stdout, answer, "Answer:");
+ 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) {
+#ifdef GSSAPI
+ usegsstsig = true;
+ use_win2k_gsstsig = false;
+#else
+ fprintf(stderr, "gsstsig not supported\n");
+#endif
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "oldgsstsig") == 0) {
+#ifdef GSSAPI
+ usegsstsig = true;
+ use_win2k_gsstsig = true;
+#else
+ fprintf(stderr, "gsstsig not supported\n");
+#endif
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "help") == 0) {
+ fprintf(stdout,
+"nsupdate " VERSION ":\n"
+"local address [port] (set local resolver)\n"
+"server address [port] (set master 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 " 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;
+
+ isc_app_block();
+ if (interactive) {
+#ifdef HAVE_READLINE
+ cmdline = readline("> ");
+ if (cmdline != NULL)
+ add_history(cmdline);
+#else
+ fprintf(stdout, "> ");
+ fflush(stdout);
+ cmdline = fgets(cmdlinebuf, MAXCMD, input);
+#endif
+ } 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);
+ }
+#ifdef HAVE_READLINE
+ if (interactive)
+ free(cmdline);
+#endif
+ 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_master(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 (++master_inuse >= master_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_master("update_completed",
+ &master_servers[master_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, &master_servers[master_inuse]);
+ isc_event_free(&event);
+ return;
+ }
+
+ result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &answer);
+ check_result(result, "dns_message_create");
+ 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
+ fprintf(stderr, "; TSIG error with server: %s\n",
+ isc_result_totext(result));
+ seenerror = true;
+ break;
+ default:
+ check_result(result, "dns_request_getresponse");
+ }
+
+ 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:");
+
+ done:
+ dns_request_destroy(&request);
+ if (usegsstsig) {
+ dns_name_free(&tmpzonename, gmctx);
+ dns_name_free(&restart_master, gmctx);
+ }
+ isc_event_free(&event);
+ done_update();
+}
+
+static void
+send_update(dns_name_t *zone, isc_sockaddr_t *master) {
+ 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(master, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "Sending update to %s\n", addrbuf);
+ }
+
+ if (isc_sockaddr_pf(master) == 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_createvia3(requestmgr, updatemsg, srcaddr,
+ master, options, tsigkey, timeout,
+ udp_timeout, udp_retries, global_task,
+ update_completed, NULL, &request);
+ check_result(result, "dns_request_createvia3");
+
+ 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 master;
+ 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_destroy(&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");
+ result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ check_result(result, "dns_message_create");
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ if (result == DNS_R_TSIGERRORSET && servers != NULL) {
+ dns_message_destroy(&rcvmsg);
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ reqinfo->msg = soaquery;
+ reqinfo->addr = addr;
+ dns_message_renderreset(soaquery);
+ ddebug("retrying soa request without TSIG");
+
+ if (isc_sockaddr_pf(addr) == AF_INET6)
+ srcaddr = localaddr6;
+ else
+ srcaddr = localaddr4;
+
+ result = dns_request_createvia3(requestmgr, soaquery, srcaddr,
+ addr, 0, NULL,
+ FIND_TIMEOUT * 20,
+ FIND_TIMEOUT, 3,
+ global_task, recvsoa, reqinfo,
+ &request);
+ check_result(result, "dns_request_createvia3");
+ requests++;
+ return;
+ }
+ check_result(result, "dns_request_getresponse");
+ section = DNS_SECTION_ANSWER;
+ POST(section);
+ if (debugging)
+ show_message(stderr, rcvmsg, "Reply from 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_destroy(&rcvmsg);
+ dns_request_destroy(&request);
+ dns_message_destroy(&soaquery);
+ ddebug("Out of recvsoa");
+ done_update();
+ seenerror = true;
+ 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(&master, NULL);
+ dns_name_clone(&soa.origin, &master);
+
+ 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, NULL);
+ }
+
+ if (debugging) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(&master, namestr, sizeof(namestr));
+ fprintf(stderr, "The master 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(&master, true, &buf);
+ check_result(result, "dns_name_totext");
+ serverstr[isc_buffer_usedlength(&buf)] = 0;
+
+ if (master_servers != NULL && master_servers != servers)
+ isc_mem_put(gmctx, master_servers,
+ master_alloc * sizeof(isc_sockaddr_t));
+ master_alloc = MAX_SERVERADDRS;
+ size = master_alloc * sizeof(isc_sockaddr_t);
+ master_servers = isc_mem_get(gmctx, size);
+ if (master_servers == NULL)
+ fatal("out of memory");
+
+ memset(master_servers, 0, size);
+ master_total = get_addresses(serverstr, dnsport,
+ master_servers, master_alloc);
+ if (master_total == 0) {
+ exit(1);
+ }
+ master_inuse = 0;
+ } else
+ master_from_servers();
+ dns_rdata_freestruct(&soa);
+
+#ifdef GSSAPI
+ if (usegsstsig) {
+ dns_name_init(&tmpzonename, NULL);
+ dns_name_dup(zname, gmctx, &tmpzonename);
+ dns_name_init(&restart_master, NULL);
+ dns_name_dup(&master, gmctx, &restart_master);
+ start_gssrequest(&master);
+ } else {
+ send_update(zname, &master_servers[master_inuse]);
+ setzoneclass(dns_rdataclass_none);
+ }
+#else
+ send_update(zname, &master_servers[master_inuse]);
+ setzoneclass(dns_rdataclass_none);
+#endif
+
+ dns_message_destroy(&soaquery);
+ dns_request_destroy(&request);
+
+ out:
+ dns_message_destroy(&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;
+
+ reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ reqinfo->msg = msg;
+ reqinfo->addr = destaddr;
+
+ if (isc_sockaddr_pf(destaddr) == AF_INET6)
+ srcaddr = localaddr6;
+ else
+ srcaddr = localaddr4;
+
+ result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
+ default_servers ? NULL : tsigkey,
+ FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
+ global_task, recvsoa, reqinfo, request);
+ check_result(result, "dns_request_createvia3");
+ requests++;
+}
+
+#ifdef 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() {
+ seenerror = true;
+
+ dns_name_free(&tmpzonename, gmctx);
+ dns_name_free(&restart_master, gmctx);
+
+ done_update();
+}
+
+static void
+start_gssrequest(dns_name_t *master) {
+ 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(master, namestr, sizeof(namestr));
+ if (kserver == NULL) {
+ kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
+ if (kserver == NULL)
+ fatal("out of memory");
+ }
+
+ memmove(kserver, &master_servers[master_inuse], sizeof(isc_sockaddr_t));
+
+ servname = dns_fixedname_initname(&fname);
+
+ if (realm == NULL)
+ get_ticket_realm(gmctx);
+
+ result = isc_string_printf(servicename, sizeof(servicename),
+ "DNS/%s%s", namestr, realm ? realm : "");
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_string_printf(servicename) failed: %s",
+ isc_result_totext(result));
+ 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_random_get(&val);
+ result = isc_string_printf(mykeystr, sizeof(mykeystr), "%u.sig-%s",
+ val, namestr);
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_string_printf(mykeystr) failed: %s",
+ isc_result_totext(result));
+ 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;
+ result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_message_create failed: %s",
+ isc_result_totext(result));
+
+ /* 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_destroy(&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");
+ reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ 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_createvia3(requestmgr, msg, srcaddr, destaddr,
+ options, tsigkey, FIND_TIMEOUT * 20,
+ FIND_TIMEOUT, 3, global_task, recvgss,
+ reqinfo, request);
+ check_result(result, "dns_request_createvia3");
+ 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;
+ 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_destroy(&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_master("recvgss", addr, eresult)) {
+ dns_message_destroy(&tsigquery);
+ failed_gssrequest();
+ } else {
+ dns_message_renderreset(tsigquery);
+ memmove(kserver, &master_servers[master_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");
+ result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ check_result(result, "dns_message_create");
+
+ 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->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_master);
+ goto done;
+ }
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain)
+ fatal("response to GSS-TSIG query was unsuccessful");
+
+
+ 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_destroy(&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", dns_result_totext(result));
+ check_result(result, "dns_message_checksig");
+#endif /* 0 */
+
+ send_update(&tmpzonename, &master_servers[master_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_destroy(&tsigquery);
+
+ dns_message_destroy(&rcvmsg);
+ ddebug("Out of recvgss");
+}
+#endif
+
+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()");
+
+ if (answer != NULL)
+ dns_message_destroy(&answer);
+
+ /*
+ * 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 master server.
+ */
+ if (userzone != NULL && !default_servers && !usegsstsig) {
+ master_from_servers();
+ send_update(userzone, &master_servers[master_inuse]);
+ setzoneclass(dns_rdataclass_none);
+ return;
+ }
+
+ result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER,
+ &soaquery);
+ check_result(result, "dns_message_create");
+
+ 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_init(name, 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_destroy(&soaquery);
+ done_update();
+ return;
+ }
+ firstname = NULL;
+ dns_message_currentname(updatemsg, section, &firstname);
+ dns_name_init(name, NULL);
+ 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()");
+
+ if (answer != NULL)
+ dns_message_destroy(&answer);
+
+#ifdef 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);
+ }
+ if (kserver != NULL) {
+ isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t));
+ kserver = NULL;
+ }
+ if (realm != NULL) {
+ isc_mem_free(gmctx, realm);
+ realm = NULL;
+ }
+#endif
+
+ if (sig0key != NULL)
+ dst_key_free(&sig0key);
+
+ ddebug("Shutting down task manager");
+ isc_taskmgr_destroy(&taskmgr);
+
+ ddebug("Destroying event");
+ isc_event_free(&global_event);
+
+ ddebug("Shutting down socket manager");
+ isc_socketmgr_destroy(&socketmgr);
+
+ ddebug("Shutting down timer manager");
+ isc_timermgr_destroy(&timermgr);
+
+ ddebug("Destroying hash context");
+ isc_hash_destroy();
+
+ ddebug("Destroying name state");
+ dns_name_destroy();
+
+ ddebug("Removing log context");
+ isc_log_destroy(&glctx);
+
+ ddebug("Destroying memory context");
+ if (memdebugging)
+ isc_mem_stats(gmctx, stderr);
+ isc_mem_destroy(&gmctx);
+}
+
+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;
+ style = &dns_master_style_debug;
+
+ input = stdin;
+
+ interactive = isatty(0);
+
+ isc_app_start();
+
+ pre_parse_args(argc, argv);
+
+ result = isc_mem_create(0, 0, &gmctx);
+ check_result(result, "isc_mem_create");
+
+ parse_args(argc, argv, gmctx, &entropy);
+
+ setup_system();
+
+ 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.docbook b/bin/nsupdate/nsupdate.docbook
new file mode 100644
index 0000000..47f021d
--- /dev/null
+++ b/bin/nsupdate/nsupdate.docbook
@@ -0,0 +1,926 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.nsupdate">
+ <info>
+ <date>2014-04-18</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>nsupdate</application></refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname><application>nsupdate</application></refname>
+ <refpurpose>Dynamic DNS update utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2012</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>nsupdate</command>
+ <arg choice="opt" rep="norepeat"><option>-d</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">level</replaceable></option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-g</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-o</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-y <replaceable class="parameter"><optional>hmac:</optional>keyname:secret</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">keyfile</replaceable></option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">timeout</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-u <replaceable class="parameter">udptimeout</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">udpretries</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat">filename</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>nsupdate</command>
+ 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.
+ </para>
+ <para>
+ Zones that are under dynamic control via
+ <command>nsupdate</command>
+ or a DHCP server should not be edited by hand.
+ Manual edits could
+ conflict with dynamic updates and cause data to be lost.
+ </para>
+ <para>
+ The resource records that are dynamically added or removed with
+ <command>nsupdate</command>
+ have to be in the same zone.
+ Requests are sent to the zone's master server.
+ This is identified by the MNAME field of the zone's SOA record.
+ </para>
+ <para>
+ Transaction signatures can be used to authenticate the Dynamic
+ DNS updates. These use the TSIG resource record type described
+ in RFC 2845 or the SIG(0) record described in RFC 2535 and
+ RFC 2931 or GSS-TSIG as described in RFC 3645.
+ </para>
+ <para>
+ TSIG relies on
+ a shared secret that should only be known to
+ <command>nsupdate</command> and the name server.
+ For instance, suitable <type>key</type> and
+ <type>server</type> statements would be added to
+ <filename>/etc/named.conf</filename> so that the name server
+ can associate the appropriate secret key and algorithm with
+ the IP address of the client application that will be using
+ TSIG authentication. You can use <command>ddns-confgen</command>
+ to generate suitable configuration fragments.
+ <command>nsupdate</command>
+ uses the <option>-y</option> or <option>-k</option> options
+ to provide the TSIG shared secret. These options are mutually exclusive.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode
+ is switched on with the <option>-g</option> flag. A
+ non-standards-compliant variant of GSS-TSIG used by Windows
+ 2000 can be switched on with the <option>-o</option> flag.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-d</term>
+ <listitem>
+ <para>
+ Debug mode. This provides tracing information about the
+ update requests that are made and the replies received
+ from the name server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D</term>
+ <listitem>
+ <para>
+ Extra debug mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i</term>
+ <listitem>
+ <para>
+ Force interactive mode, even when standard input is not a terminal.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">keyfile</replaceable></term>
+ <listitem>
+ <para>
+ The file containing the TSIG authentication key.
+ Keyfiles may be in two formats: a single file containing
+ a <filename>named.conf</filename>-format <command>key</command>
+ statement, which may be generated automatically by
+ <command>ddns-confgen</command>, or a pair of files whose names are
+ of the format <filename>K{name}.+157.+{random}.key</filename> and
+ <filename>K{name}.+157.+{random}.private</filename>, which can be
+ generated by <command>dnssec-keygen</command>.
+ The <option>-k</option> may 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l</term>
+ <listitem>
+ <para>
+ Local-host only mode. This sets the server address to
+ localhost (disabling the <command>server</command> so that the server
+ address cannot be overridden). Connections to the local server will
+ use a TSIG key found in <filename>/var/run/named/session.key</filename>,
+ which is automatically generated by <command>named</command> if any
+ local master zone has set <command>update-policy</command> to
+ <command>local</command>. The location of this key file can be
+ overridden with the <option>-k</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Set the logging debug level. If zero, logging is disabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Set the port to use for connections to a name server. The
+ default is 53.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P</term>
+ <listitem>
+ <para>
+ Print the list of private BIND-specific resource record
+ types whose format is understood
+ by <command>nsupdate</command>. See also
+ the <option>-T</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">udpretries</replaceable></term>
+ <listitem>
+ <para>
+ The number of UDP retries. The default is 3. If zero, only
+ one update request will be made.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Where to obtain randomness. If the operating system
+ does not provide a <filename>/dev/random</filename> or
+ equivalent device, the default source of randomness is keyboard
+ input. <filename>randomdev</filename> specifies the name of
+ a character device or file containing random data to be used
+ instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard input
+ should be used. This option may be specified multiple times.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">timeout</replaceable></term>
+ <listitem>
+ <para>
+ The maximum time an update request can take before it is
+ aborted. The default is 300 seconds. Zero can be used to
+ disable the timeout.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T</term>
+ <listitem>
+ <para>
+ Print the list of IANA standard resource record types
+ whose format is understood by <command>nsupdate</command>.
+ <command>nsupdate</command> will exit after the lists are
+ printed. The <option>-T</option> option can be combined
+ with the <option>-P</option> option.
+ </para>
+ <para>
+ Other types can be entered using "TYPEXXXXX" where "XXXXX" is the
+ decimal value of the type with no leading zeros. The rdata,
+ if present, will be parsed using the UNKNOWN rdata format,
+ (&lt;backslash&gt; &lt;hash&gt; &lt;space&gt; &lt;length&gt;
+ &lt;space&gt; &lt;hexstring&gt;).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">udptimeout</replaceable></term>
+ <listitem>
+ <para>
+ The UDP retry interval. The default is 3 seconds. If zero,
+ the interval will be computed from the timeout interval and
+ number of UDP retries.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Use TCP even for small update requests.
+ By default, <command>nsupdate</command>
+ 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 will be used.
+ TCP may be preferable when a batch of update requests is made.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Print the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y <replaceable class="parameter"><optional>hmac:</optional>keyname:secret</replaceable></term>
+ <listitem>
+ <para>
+ Literal TSIG authentication key.
+ <parameter>keyname</parameter> is the name of the key, and
+ <parameter>secret</parameter> is the base64 encoded shared secret.
+ <parameter>hmac</parameter> is the name of the key algorithm;
+ valid choices are <literal>hmac-md5</literal>,
+ <literal>hmac-sha1</literal>, <literal>hmac-sha224</literal>,
+ <literal>hmac-sha256</literal>, <literal>hmac-sha384</literal>, or
+ <literal>hmac-sha512</literal>. If <parameter>hmac</parameter>
+ is not specified, the default is <literal>hmac-md5</literal>
+ or if MD5 was disabled <literal>hmac-sha256</literal>.
+ </para>
+ <para>
+ NOTE: Use of the <option>-y</option> 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
+ <citerefentry>
+ <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ or in a history file maintained by the user's shell.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>INPUT FORMAT</title></info>
+
+ <para><command>nsupdate</command>
+ reads input from
+ <parameter>filename</parameter>
+ or standard input.
+ Each command is supplied on exactly one line of input.
+ Some commands are for administrative purposes.
+ The 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 will be rejected if the tests for the prerequisite conditions
+ fail.
+ </para>
+ <para>
+ 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 present or missing from the zone.
+ A blank input line (or the <command>send</command> command)
+ causes the
+ accumulated commands to be sent as one Dynamic DNS update request to the
+ name server.
+ </para>
+ <para>
+ The command formats and their meaning are as follows:
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <command>server</command>
+ <arg choice="req" rep="norepeat">servername</arg>
+ <arg choice="opt" rep="norepeat">port</arg>
+ </term>
+ <listitem>
+ <para>
+ Sends all dynamic update requests to the name server
+ <parameter>servername</parameter>.
+ When no server statement is provided,
+ <command>nsupdate</command>
+ will send updates to the master server of the correct zone.
+ The MNAME field of that zone's SOA record will identify the
+ master
+ server for that zone.
+ <parameter>port</parameter>
+ is the port number on
+ <parameter>servername</parameter>
+ where the dynamic update requests get sent.
+ If no port number is specified, the default DNS port number of
+ 53 is
+ used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>local</command>
+ <arg choice="req" rep="norepeat">address</arg>
+ <arg choice="opt" rep="norepeat">port</arg>
+ </term>
+ <listitem>
+ <para>
+ Sends all dynamic update requests using the local
+ <parameter>address</parameter>.
+
+ When no local statement is provided,
+ <command>nsupdate</command>
+ will send updates using an address and port chosen by the
+ system.
+ <parameter>port</parameter>
+ can additionally be used to make requests come from a specific
+ port.
+ If no port number is specified, the system will assign one.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>zone</command>
+ <arg choice="req" rep="norepeat">zonename</arg>
+ </term>
+ <listitem>
+ <para>
+ Specifies that all updates are to be made to the zone
+ <parameter>zonename</parameter>.
+ If no
+ <parameter>zone</parameter>
+ statement is provided,
+ <command>nsupdate</command>
+ will attempt determine the correct zone to update based on the
+ rest of the input.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>class</command>
+ <arg choice="req" rep="norepeat">classname</arg>
+ </term>
+ <listitem>
+ <para>
+ Specify the default class.
+ If no <parameter>class</parameter> is specified, the
+ default class is
+ <parameter>IN</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>ttl</command>
+ <arg choice="req" rep="norepeat">seconds</arg>
+ </term>
+ <listitem>
+ <para>
+ Specify the default time to live for records to be added.
+ The value <parameter>none</parameter> will clear the default
+ ttl.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>key</command>
+ <arg choice="opt" rep="norepeat">hmac:</arg><arg choice="req" rep="norepeat">keyname</arg>
+ <arg choice="req" rep="norepeat">secret</arg>
+ </term>
+ <listitem>
+ <para>
+ Specifies that all updates are to be TSIG-signed using the
+ <parameter>keyname</parameter> <parameter>secret</parameter> pair.
+ If <parameter>hmac</parameter> is specified, then it sets the
+ signing algorithm in use; the default is
+ <literal>hmac-md5</literal> or if MD5 was disabled
+ <literal>hmac-sha256</literal>. The <command>key</command>
+ command overrides any key specified on the command line via
+ <option>-y</option> or <option>-k</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>gsstsig</command>
+ </term>
+ <listitem>
+ <para>
+ Use GSS-TSIG to sign the updated. This is equivalent to
+ specifying <option>-g</option> on the command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>oldgsstsig</command>
+ </term>
+ <listitem>
+ <para>
+ Use the Windows 2000 version of GSS-TSIG to sign the updated.
+ This is equivalent to specifying <option>-o</option> on the
+ command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>realm</command>
+ <arg choice="req" rep="norepeat"><optional>realm_name</optional></arg>
+ </term>
+ <listitem>
+ <para>
+ When using GSS-TSIG use <parameter>realm_name</parameter> rather
+ than the default realm in <filename>krb5.conf</filename>. If no
+ realm is specified the saved realm is cleared.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>check-names</command>
+ <arg choice="req" rep="norepeat"><optional>yes_or_no</optional></arg>
+ </term>
+ <listitem>
+ <para>
+ Turn 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 will not be added to the UPDATE message.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command><optional>prereq</optional> nxdomain</command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ </term>
+ <listitem>
+ <para>
+ Requires that no resource record of any type exists with name
+ <parameter>domain-name</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <command><optional>prereq</optional> yxdomain</command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ </term>
+ <listitem>
+ <para>
+ Requires that
+ <parameter>domain-name</parameter>
+ exists (has as at least one resource record, of any type).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command><optional>prereq</optional> nxrrset</command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="req" rep="norepeat">type</arg>
+ </term>
+ <listitem>
+ <para>
+ Requires that no resource record exists of the specified
+ <parameter>type</parameter>,
+ <parameter>class</parameter>
+ and
+ <parameter>domain-name</parameter>.
+ If
+ <parameter>class</parameter>
+ is omitted, IN (internet) is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <command><optional>prereq</optional> yxrrset</command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="req" rep="norepeat">type</arg>
+ </term>
+ <listitem>
+ <para>
+ This requires that a resource record of the specified
+ <parameter>type</parameter>,
+ <parameter>class</parameter>
+ and
+ <parameter>domain-name</parameter>
+ must exist.
+ If
+ <parameter>class</parameter>
+ is omitted, IN (internet) is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command><optional>prereq</optional> yxrrset</command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="req" rep="norepeat">type</arg>
+ <arg choice="req" rep="repeat">data</arg>
+ </term>
+ <listitem>
+ <para>
+ The
+ <parameter>data</parameter>
+ from each set of prerequisites of this form
+ sharing a common
+ <parameter>type</parameter>,
+ <parameter>class</parameter>,
+ and
+ <parameter>domain-name</parameter>
+ 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
+ <parameter>type</parameter>,
+ <parameter>class</parameter>,
+ and
+ <parameter>domain-name</parameter>.
+ The
+ <parameter>data</parameter>
+ are written in the standard text representation of the resource
+ record's
+ RDATA.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command><optional>update</optional> del<optional>ete</optional></command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ <arg choice="opt" rep="norepeat">ttl</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="opt" rep="norepeat">type <arg choice="opt" rep="repeat">data</arg></arg>
+ </term>
+ <listitem>
+ <para>
+ Deletes any resource records named
+ <parameter>domain-name</parameter>.
+ If
+ <parameter>type</parameter>
+ and
+ <parameter>data</parameter>
+ is provided, only matching resource records will be removed.
+ The internet class is assumed if
+ <parameter>class</parameter>
+ is not supplied. The
+ <parameter>ttl</parameter>
+ is ignored, and is only allowed for compatibility.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command><optional>update</optional> add</command>
+ <arg choice="req" rep="norepeat">domain-name</arg>
+ <arg choice="req" rep="norepeat">ttl</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="req" rep="norepeat">type</arg>
+ <arg choice="req" rep="repeat">data</arg>
+ </term>
+ <listitem>
+ <para>
+ Adds a new resource record with the specified
+ <parameter>ttl</parameter>,
+ <parameter>class</parameter>
+ and
+ <parameter>data</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>show</command>
+ </term>
+ <listitem>
+ <para>
+ Displays the current message, containing all of the
+ prerequisites and
+ updates specified since the last send.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>send</command>
+ </term>
+ <listitem>
+ <para>
+ Sends the current message. This is equivalent to entering a
+ blank line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>answer</command>
+ </term>
+ <listitem>
+ <para>
+ Displays the answer.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>debug</command>
+ </term>
+ <listitem>
+ <para>
+ Turn on debugging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>version</command>
+ </term>
+ <listitem>
+ <para>
+ Print version number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>help</command>
+ </term>
+ <listitem>
+ <para>
+ Print a list of commands.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+
+ <para>
+ Lines beginning with a semicolon are comments and are ignored.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>EXAMPLES</title></info>
+
+ <para>
+ The examples below show how
+ <command>nsupdate</command>
+ could be used to insert and delete resource records from the
+ <type>example.com</type>
+ zone.
+ Notice that the input in each example contains a trailing blank line so
+ that
+ a group of commands are sent as one dynamic update request to the
+ master name server for
+ <type>example.com</type>.
+
+ <programlisting>
+# nsupdate
+&gt; update delete oldhost.example.com A
+&gt; update add newhost.example.com 86400 A 172.16.1.1
+&gt; send
+</programlisting>
+ </para>
+ <para>
+ Any A records for
+ <type>oldhost.example.com</type>
+ are deleted.
+ And an A record for
+ <type>newhost.example.com</type>
+ with IP address 172.16.1.1 is added.
+ The newly-added record has a 1 day TTL (86400 seconds).
+ <programlisting>
+# nsupdate
+&gt; prereq nxdomain nickname.example.com
+&gt; update add nickname.example.com 86400 CNAME somehost.example.com
+&gt; send
+</programlisting>
+ </para>
+ <para>
+ The prerequisite condition gets the name server to check that there
+ are no resource records of any type for
+ <type>nickname.example.com</type>.
+
+ 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.)
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>/etc/resolv.conf</constant></term>
+ <listitem>
+ <para>
+ used to identify default name server
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>/var/run/named/session.key</constant></term>
+ <listitem>
+ <para>
+ sets the default TSIG key for use in local-only mode
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>K{name}.+157.+{random}.key</constant></term>
+ <listitem>
+ <para>
+ base-64 encoding of HMAC-MD5 key created by
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>K{name}.+157.+{random}.private</constant></term>
+ <listitem>
+ <para>
+ base-64 encoding of HMAC-MD5 key created by
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citetitle>RFC 2136</citetitle>,
+ <citetitle>RFC 3007</citetitle>,
+ <citetitle>RFC 2104</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 1034</citetitle>,
+ <citetitle>RFC 2535</citetitle>,
+ <citetitle>RFC 2931</citetitle>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>ddns-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>BUGS</title></info>
+
+ <para>
+ The TSIG key is redundantly stored in two separate files.
+ This is a consequence of nsupdate using the DST library
+ for its cryptographic operations, and may change in future
+ releases.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/nsupdate/nsupdate.html b/bin/nsupdate/nsupdate.html
new file mode 100644
index 0000000..133f706
--- /dev/null
+++ b/bin/nsupdate/nsupdate.html
@@ -0,0 +1,783 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2012, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nsupdate</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.nsupdate"></a><div class="titlepage"></div>
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">nsupdate</span>
+ &#8212; Dynamic DNS update utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">nsupdate</code>
+ [<code class="option">-d</code>]
+ [<code class="option">-D</code>]
+ [<code class="option">-i</code>]
+ [<code class="option">-L <em class="replaceable"><code>level</code></em></code>]
+ [
+ [<code class="option">-g</code>]
+ | [<code class="option">-o</code>]
+ | [<code class="option">-l</code>]
+ | [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></code>]
+ | [<code class="option">-k <em class="replaceable"><code>keyfile</code></em></code>]
+ ]
+ [<code class="option">-t <em class="replaceable"><code>timeout</code></em></code>]
+ [<code class="option">-u <em class="replaceable"><code>udptimeout</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>udpretries</code></em></code>]
+ [<code class="option">-R <em class="replaceable"><code>randomdev</code></em></code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-T</code>]
+ [<code class="option">-P</code>]
+ [<code class="option">-V</code>]
+ [filename]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>nsupdate</strong></span>
+ 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.
+ </p>
+ <p>
+ Zones that are under dynamic control via
+ <span class="command"><strong>nsupdate</strong></span>
+ or a DHCP server should not be edited by hand.
+ Manual edits could
+ conflict with dynamic updates and cause data to be lost.
+ </p>
+ <p>
+ The resource records that are dynamically added or removed with
+ <span class="command"><strong>nsupdate</strong></span>
+ have to be in the same zone.
+ Requests are sent to the zone's master server.
+ This is identified by the MNAME field of the zone's SOA record.
+ </p>
+ <p>
+ Transaction signatures can be used to authenticate the Dynamic
+ DNS updates. These use the TSIG resource record type described
+ in RFC 2845 or the SIG(0) record described in RFC 2535 and
+ RFC 2931 or GSS-TSIG as described in RFC 3645.
+ </p>
+ <p>
+ TSIG relies on
+ a shared secret that should only be known to
+ <span class="command"><strong>nsupdate</strong></span> and the name server.
+ For instance, suitable <span class="type">key</span> and
+ <span class="type">server</span> statements would be added to
+ <code class="filename">/etc/named.conf</code> so that the name server
+ can associate the appropriate secret key and algorithm with
+ the IP address of the client application that will be using
+ TSIG authentication. You can use <span class="command"><strong>ddns-confgen</strong></span>
+ to generate suitable configuration fragments.
+ <span class="command"><strong>nsupdate</strong></span>
+ uses the <code class="option">-y</code> or <code class="option">-k</code> options
+ to provide the TSIG shared secret. These options are mutually exclusive.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode
+ is switched on with the <code class="option">-g</code> flag. A
+ non-standards-compliant variant of GSS-TSIG used by Windows
+ 2000 can be switched on with the <code class="option">-o</code> flag.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-d</span></dt>
+<dd>
+ <p>
+ Debug mode. This provides tracing information about the
+ update requests that are made and the replies received
+ from the name server.
+ </p>
+ </dd>
+<dt><span class="term">-D</span></dt>
+<dd>
+ <p>
+ Extra debug mode.
+ </p>
+ </dd>
+<dt><span class="term">-i</span></dt>
+<dd>
+ <p>
+ Force interactive mode, even when standard input is not a terminal.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyfile</code></em></span></dt>
+<dd>
+ <p>
+ The file containing the TSIG authentication key.
+ Keyfiles may be in two formats: a single file containing
+ a <code class="filename">named.conf</code>-format <span class="command"><strong>key</strong></span>
+ statement, which may be generated automatically by
+ <span class="command"><strong>ddns-confgen</strong></span>, or a pair of files whose names are
+ of the format <code class="filename">K{name}.+157.+{random}.key</code> and
+ <code class="filename">K{name}.+157.+{random}.private</code>, which can be
+ generated by <span class="command"><strong>dnssec-keygen</strong></span>.
+ The <code class="option">-k</code> may 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.
+ </p>
+ </dd>
+<dt><span class="term">-l</span></dt>
+<dd>
+ <p>
+ Local-host only mode. This sets the server address to
+ localhost (disabling the <span class="command"><strong>server</strong></span> so that the server
+ address cannot be overridden). Connections to the local server will
+ use a TSIG key found in <code class="filename">/var/run/named/session.key</code>,
+ which is automatically generated by <span class="command"><strong>named</strong></span> if any
+ local master zone has set <span class="command"><strong>update-policy</strong></span> to
+ <span class="command"><strong>local</strong></span>. The location of this key file can be
+ overridden with the <code class="option">-k</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-L <em class="replaceable"><code>level</code></em></span></dt>
+<dd>
+ <p>
+ Set the logging debug level. If zero, logging is disabled.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Set the port to use for connections to a name server. The
+ default is 53.
+ </p>
+ </dd>
+<dt><span class="term">-P</span></dt>
+<dd>
+ <p>
+ Print the list of private BIND-specific resource record
+ types whose format is understood
+ by <span class="command"><strong>nsupdate</strong></span>. See also
+ the <code class="option">-T</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>udpretries</code></em></span></dt>
+<dd>
+ <p>
+ The number of UDP retries. The default is 3. If zero, only
+ one update request will be made.
+ </p>
+ </dd>
+<dt><span class="term">-R <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd>
+ <p>
+ Where to obtain randomness. If the operating system
+ does not provide a <code class="filename">/dev/random</code> or
+ equivalent device, the default source of randomness is keyboard
+ input. <code class="filename">randomdev</code> specifies the name of
+ a character device or file containing random data to be used
+ instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard input
+ should be used. This option may be specified multiple times.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>timeout</code></em></span></dt>
+<dd>
+ <p>
+ The maximum time an update request can take before it is
+ aborted. The default is 300 seconds. Zero can be used to
+ disable the timeout.
+ </p>
+ </dd>
+<dt><span class="term">-T</span></dt>
+<dd>
+ <p>
+ Print the list of IANA standard resource record types
+ whose format is understood by <span class="command"><strong>nsupdate</strong></span>.
+ <span class="command"><strong>nsupdate</strong></span> will exit after the lists are
+ printed. The <code class="option">-T</code> option can be combined
+ with the <code class="option">-P</code> option.
+ </p>
+ <p>
+ Other types can be entered using "TYPEXXXXX" where "XXXXX" is the
+ decimal value of the type with no leading zeros. The rdata,
+ if present, will be parsed using the UNKNOWN rdata format,
+ (&lt;backslash&gt; &lt;hash&gt; &lt;space&gt; &lt;length&gt;
+ &lt;space&gt; &lt;hexstring&gt;).
+ </p>
+ </dd>
+<dt><span class="term">-u <em class="replaceable"><code>udptimeout</code></em></span></dt>
+<dd>
+ <p>
+ The UDP retry interval. The default is 3 seconds. If zero,
+ the interval will be computed from the timeout interval and
+ number of UDP retries.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Use TCP even for small update requests.
+ By default, <span class="command"><strong>nsupdate</strong></span>
+ 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 will be used.
+ TCP may be preferable when a batch of update requests is made.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Print the version number and exit.
+ </p>
+ </dd>
+<dt><span class="term">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></span></dt>
+<dd>
+ <p>
+ Literal TSIG authentication key.
+ <em class="parameter"><code>keyname</code></em> is the name of the key, and
+ <em class="parameter"><code>secret</code></em> is the base64 encoded shared secret.
+ <em class="parameter"><code>hmac</code></em> is the name of the key algorithm;
+ valid choices are <code class="literal">hmac-md5</code>,
+ <code class="literal">hmac-sha1</code>, <code class="literal">hmac-sha224</code>,
+ <code class="literal">hmac-sha256</code>, <code class="literal">hmac-sha384</code>, or
+ <code class="literal">hmac-sha512</code>. If <em class="parameter"><code>hmac</code></em>
+ is not specified, the default is <code class="literal">hmac-md5</code>
+ or if MD5 was disabled <code class="literal">hmac-sha256</code>.
+ </p>
+ <p>
+ NOTE: Use of the <code class="option">-y</code> 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
+ <span class="citerefentry">
+ <span class="refentrytitle">ps</span>(1)
+ </span>
+ or in a history file maintained by the user's shell.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>INPUT FORMAT</h2>
+
+ <p><span class="command"><strong>nsupdate</strong></span>
+ reads input from
+ <em class="parameter"><code>filename</code></em>
+ or standard input.
+ Each command is supplied on exactly one line of input.
+ Some commands are for administrative purposes.
+ The 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 will be rejected if the tests for the prerequisite conditions
+ fail.
+ </p>
+ <p>
+ 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 present or missing from the zone.
+ A blank input line (or the <span class="command"><strong>send</strong></span> command)
+ causes the
+ accumulated commands to be sent as one Dynamic DNS update request to the
+ name server.
+ </p>
+ <p>
+ The command formats and their meaning are as follows:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term">
+ <span class="command"><strong>server</strong></span>
+ {servername}
+ [port]
+ </span></dt>
+<dd>
+ <p>
+ Sends all dynamic update requests to the name server
+ <em class="parameter"><code>servername</code></em>.
+ When no server statement is provided,
+ <span class="command"><strong>nsupdate</strong></span>
+ will send updates to the master server of the correct zone.
+ The MNAME field of that zone's SOA record will identify the
+ master
+ server for that zone.
+ <em class="parameter"><code>port</code></em>
+ is the port number on
+ <em class="parameter"><code>servername</code></em>
+ where the dynamic update requests get sent.
+ If no port number is specified, the default DNS port number of
+ 53 is
+ used.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>local</strong></span>
+ {address}
+ [port]
+ </span></dt>
+<dd>
+ <p>
+ Sends all dynamic update requests using the local
+ <em class="parameter"><code>address</code></em>.
+
+ When no local statement is provided,
+ <span class="command"><strong>nsupdate</strong></span>
+ will send updates using an address and port chosen by the
+ system.
+ <em class="parameter"><code>port</code></em>
+ can additionally be used to make requests come from a specific
+ port.
+ If no port number is specified, the system will assign one.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>zone</strong></span>
+ {zonename}
+ </span></dt>
+<dd>
+ <p>
+ Specifies that all updates are to be made to the zone
+ <em class="parameter"><code>zonename</code></em>.
+ If no
+ <em class="parameter"><code>zone</code></em>
+ statement is provided,
+ <span class="command"><strong>nsupdate</strong></span>
+ will attempt determine the correct zone to update based on the
+ rest of the input.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>class</strong></span>
+ {classname}
+ </span></dt>
+<dd>
+ <p>
+ Specify the default class.
+ If no <em class="parameter"><code>class</code></em> is specified, the
+ default class is
+ <em class="parameter"><code>IN</code></em>.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>ttl</strong></span>
+ {seconds}
+ </span></dt>
+<dd>
+ <p>
+ Specify the default time to live for records to be added.
+ The value <em class="parameter"><code>none</code></em> will clear the default
+ ttl.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>key</strong></span>
+ [hmac:] {keyname}
+ {secret}
+ </span></dt>
+<dd>
+ <p>
+ Specifies that all updates are to be TSIG-signed using the
+ <em class="parameter"><code>keyname</code></em> <em class="parameter"><code>secret</code></em> pair.
+ If <em class="parameter"><code>hmac</code></em> is specified, then it sets the
+ signing algorithm in use; the default is
+ <code class="literal">hmac-md5</code> or if MD5 was disabled
+ <code class="literal">hmac-sha256</code>. The <span class="command"><strong>key</strong></span>
+ command overrides any key specified on the command line via
+ <code class="option">-y</code> or <code class="option">-k</code>.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>gsstsig</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Use GSS-TSIG to sign the updated. This is equivalent to
+ specifying <code class="option">-g</code> on the command line.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>oldgsstsig</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Use the Windows 2000 version of GSS-TSIG to sign the updated.
+ This is equivalent to specifying <code class="option">-o</code> on the
+ command line.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>realm</strong></span>
+ {[<span class="optional">realm_name</span>]}
+ </span></dt>
+<dd>
+ <p>
+ When using GSS-TSIG use <em class="parameter"><code>realm_name</code></em> rather
+ than the default realm in <code class="filename">krb5.conf</code>. If no
+ realm is specified the saved realm is cleared.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>check-names</strong></span>
+ {[<span class="optional">yes_or_no</span>]}
+ </span></dt>
+<dd>
+ <p>
+ Turn 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 will not be added to the UPDATE message.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">prereq</span>] nxdomain</strong></span>
+ {domain-name}
+ </span></dt>
+<dd>
+ <p>
+ Requires that no resource record of any type exists with name
+ <em class="parameter"><code>domain-name</code></em>.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">prereq</span>] yxdomain</strong></span>
+ {domain-name}
+ </span></dt>
+<dd>
+ <p>
+ Requires that
+ <em class="parameter"><code>domain-name</code></em>
+ exists (has as at least one resource record, of any type).
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">prereq</span>] nxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ </span></dt>
+<dd>
+ <p>
+ Requires that no resource record exists of the specified
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>domain-name</code></em>.
+ If
+ <em class="parameter"><code>class</code></em>
+ is omitted, IN (internet) is assumed.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">prereq</span>] yxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ </span></dt>
+<dd>
+ <p>
+ This requires that a resource record of the specified
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>domain-name</code></em>
+ must exist.
+ If
+ <em class="parameter"><code>class</code></em>
+ is omitted, IN (internet) is assumed.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">prereq</span>] yxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ {data...}
+ </span></dt>
+<dd>
+ <p>
+ The
+ <em class="parameter"><code>data</code></em>
+ from each set of prerequisites of this form
+ sharing a common
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>,
+ and
+ <em class="parameter"><code>domain-name</code></em>
+ 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
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>,
+ and
+ <em class="parameter"><code>domain-name</code></em>.
+ The
+ <em class="parameter"><code>data</code></em>
+ are written in the standard text representation of the resource
+ record's
+ RDATA.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">update</span>] del[<span class="optional">ete</span>]</strong></span>
+ {domain-name}
+ [ttl]
+ [class]
+ [type [data...]]
+ </span></dt>
+<dd>
+ <p>
+ Deletes any resource records named
+ <em class="parameter"><code>domain-name</code></em>.
+ If
+ <em class="parameter"><code>type</code></em>
+ and
+ <em class="parameter"><code>data</code></em>
+ is provided, only matching resource records will be removed.
+ The internet class is assumed if
+ <em class="parameter"><code>class</code></em>
+ is not supplied. The
+ <em class="parameter"><code>ttl</code></em>
+ is ignored, and is only allowed for compatibility.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>[<span class="optional">update</span>] add</strong></span>
+ {domain-name}
+ {ttl}
+ [class]
+ {type}
+ {data...}
+ </span></dt>
+<dd>
+ <p>
+ Adds a new resource record with the specified
+ <em class="parameter"><code>ttl</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>data</code></em>.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>show</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Displays the current message, containing all of the
+ prerequisites and
+ updates specified since the last send.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>send</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Sends the current message. This is equivalent to entering a
+ blank line.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>answer</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Displays the answer.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>debug</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Turn on debugging.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>version</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Print version number.
+ </p>
+ </dd>
+<dt><span class="term">
+ <span class="command"><strong>help</strong></span>
+ </span></dt>
+<dd>
+ <p>
+ Print a list of commands.
+ </p>
+ </dd>
+</dl></div>
+<p>
+ </p>
+
+ <p>
+ Lines beginning with a semicolon are comments and are ignored.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>EXAMPLES</h2>
+
+ <p>
+ The examples below show how
+ <span class="command"><strong>nsupdate</strong></span>
+ could be used to insert and delete resource records from the
+ <span class="type">example.com</span>
+ zone.
+ Notice that the input in each example contains a trailing blank line so
+ that
+ a group of commands are sent as one dynamic update request to the
+ master name server for
+ <span class="type">example.com</span>.
+
+ </p>
+<pre class="programlisting">
+# nsupdate
+&gt; update delete oldhost.example.com A
+&gt; update add newhost.example.com 86400 A 172.16.1.1
+&gt; send
+</pre>
+<p>
+ </p>
+ <p>
+ Any A records for
+ <span class="type">oldhost.example.com</span>
+ are deleted.
+ And an A record for
+ <span class="type">newhost.example.com</span>
+ with IP address 172.16.1.1 is added.
+ The newly-added record has a 1 day TTL (86400 seconds).
+ </p>
+<pre class="programlisting">
+# nsupdate
+&gt; prereq nxdomain nickname.example.com
+&gt; update add nickname.example.com 86400 CNAME somehost.example.com
+&gt; send
+</pre>
+<p>
+ </p>
+ <p>
+ The prerequisite condition gets the name server to check that there
+ are no resource records of any type for
+ <span class="type">nickname.example.com</span>.
+
+ 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.)
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>FILES</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">/etc/resolv.conf</code></span></dt>
+<dd>
+ <p>
+ used to identify default name server
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">/var/run/named/session.key</code></span></dt>
+<dd>
+ <p>
+ sets the default TSIG key for use in local-only mode
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">K{name}.+157.+{random}.key</code></span></dt>
+<dd>
+ <p>
+ base-64 encoding of HMAC-MD5 key created by
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">K{name}.+157.+{random}.private</code></span></dt>
+<dd>
+ <p>
+ base-64 encoding of HMAC-MD5 key created by
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <em class="citetitle">RFC 2136</em>,
+ <em class="citetitle">RFC 3007</em>,
+ <em class="citetitle">RFC 2104</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 1034</em>,
+ <em class="citetitle">RFC 2535</em>,
+ <em class="citetitle">RFC 2931</em>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">ddns-confgen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.13"></a><h2>BUGS</h2>
+
+ <p>
+ The TSIG key is redundantly stored in two separate files.
+ This is a consequence of nsupdate using the DST library
+ for its cryptographic operations, and may change in future
+ releases.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/nsupdate/win32/nsupdate.dsp.in b/bin/nsupdate/win32/nsupdate.dsp.in
new file mode 100644
index 0000000..18442a5
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="nsupdate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=nsupdate - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsupdate - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nsupdate - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIB@ ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/isccfg/win32/Release/libisccfg.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/nsupdate.exe"
+
+!ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIBD@ ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nsupdate - @PLATFORM@ Release"
+# Name "nsupdate - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\nsupdate.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/nsupdate/win32/nsupdate.dsw b/bin/nsupdate/win32/nsupdate.dsw
new file mode 100644
index 0000000..5f0ac36
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nsupdate"=".\nsupdate.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/nsupdate/win32/nsupdate.mak.in b/bin/nsupdate/win32/nsupdate.mak.in
new file mode 100644
index 0000000..7095e13
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.mak.in
@@ -0,0 +1,375 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nsupdate.dsp
+!IF "$(CFG)" == ""
+CFG=nsupdate - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to nsupdate - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nsupdate - @PLATFORM@ Release" && "$(CFG)" != "nsupdate - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsupdate - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nsupdate - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\nsupdate.exe"
+
+!ELSE
+
+ALL : "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\nsupdate.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\nsupdate.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\nsupdate.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nsupdate.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsupdate.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/isccfg/win32/Release/libisccfg.lib @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nsupdate.pdb" @MACHINE@ /out:"../../../Build/Release/nsupdate.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\nsupdate.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib"
+
+"..\..\..\Build\Release\nsupdate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\nsupdate.exe" "$(OUTDIR)\nsupdate.bsc"
+
+!ELSE
+
+ALL : "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\nsupdate.exe" "$(OUTDIR)\nsupdate.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\nsupdate.obj"
+ -@erase "$(INTDIR)\nsupdate.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\nsupdate.bsc"
+ -@erase "$(OUTDIR)\nsupdate.pdb"
+ -@erase "..\..\..\Build\Debug\nsupdate.exe"
+ -@erase "..\..\..\Build\Debug\nsupdate.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsupdate.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\nsupdate.sbr"
+
+"$(OUTDIR)\nsupdate.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIBD@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nsupdate.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\nsupdate.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib"
+
+"..\..\..\Build\Debug\nsupdate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("nsupdate.dep")
+!INCLUDE "nsupdate.dep"
+!ELSE
+!MESSAGE Warning: cannot find "nsupdate.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" || "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+SOURCE=..\nsupdate.c
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+
+
+"$(INTDIR)\nsupdate.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\nsupdate.obj" "$(INTDIR)\nsupdate.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nsupdate - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/nsupdate/win32/nsupdate.vcxproj.filters.in b/bin/nsupdate/win32/nsupdate.vcxproj.filters.in
new file mode 100644
index 0000000..477847e
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nsupdate.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/nsupdate/win32/nsupdate.vcxproj.in b/bin/nsupdate/win32/nsupdate.vcxproj.in
new file mode 100644
index 0000000..58a1a36
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C41266C7-E27E-4D60-9815-82D3B32BF82F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>nsupdate</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@@USE_GSSAPI@USE_READLINE_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GSSAPI_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\lwres\win32\include\lwres;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@READLINE_LIBD@@GSSAPI_LIB@@KRB5_LIB@libisc.lib;libdns.lib;liblwres.lib;libbind9.lib;libisccfg.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@@USE_GSSAPI@USE_READLINE_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GSSAPI_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\lwres\win32\include\lwres;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@READLINE_LIB@@GSSAPI_LIB@@KRB5_LIB@libisc.lib;libdns.lib;liblwres.lib;libbind9.lib;libisccfg.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nsupdate.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/nsupdate/win32/nsupdate.vcxproj.user b/bin/nsupdate/win32/nsupdate.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in
new file mode 100644
index 0000000..ae90616
--- /dev/null
+++ b/bin/pkcs11/Makefile.in
@@ -0,0 +1,103 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.2 2009/10/05 12:07:08 fdupont Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${ISC_INCLUDES}
+
+CDEFINES =
+
+ISCLIBS = ../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+
+DEPLIBS = ${ISCDEPLIBS}
+
+# if FORCE_STATIC_PROVIDER: LIBS += ${PROVIDER}
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS = benchmarks
+
+TARGETS = pkcs11-list@EXEEXT@ pkcs11-destroy@EXEEXT@ \
+ pkcs11-keygen@EXEEXT@ pkcs11-tokens@EXEEXT@
+SRCS = pkcs11-list.c pkcs11-destroy.c \
+ pkcs11-keygen.c pkcs11-tokens.c
+OBJS = pkcs11-list.@O@ pkcs11-destroy.@O@ \
+ pkcs11-keygen.@O@ pkcs11-tokens.@O@
+
+
+MANPAGES = pkcs11-list.8 pkcs11-destroy.8 \
+ pkcs11-keygen.8 pkcs11-tokens.8
+HTMLPAGES = pkcs11-list.html pkcs11-destroy.html \
+ pkcs11-keygen.html pkcs11-tokens.html
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+pkcs11-list@EXEEXT@: pkcs11-list.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ pkcs11-list.@O@ ${LIBS}
+
+pkcs11-destroy@EXEEXT@: pkcs11-destroy.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ pkcs11-destroy.@O@ ${LIBS}
+
+pkcs11-keygen@EXEEXT@: pkcs11-keygen.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ pkcs11-keygen.@O@ ${LIBS}
+
+pkcs11-tokens@EXEEXT@: pkcs11-tokens.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ pkcs11-tokens.@O@ ${LIBS}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: ${TARGETS} installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-keygen@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-tokens@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${INSTALL_DATA} ${srcdir}/pkcs11-list.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/pkcs11-destroy.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/pkcs11-tokens.8 ${DESTDIR}${mandir}/man8
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man8/pkcs11-tokens.8
+ rm -f ${DESTDIR}${mandir}/man8/pkcs11-keygen.8
+ rm -f ${DESTDIR}${mandir}/man8/pkcs11-destroy.8
+ rm -f ${DESTDIR}${mandir}/man8/pkcs11-list.8
+ ${LIBTOOL_MODE_UNINSTALL} rm -f /
+ ${DESTDIR}${sbindir}/pkcs11-tokens@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f /
+ ${DESTDIR}${sbindir}/pkcs11-keygen@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f /
+ ${DESTDIR}${sbindir}/pkcs11-destroy@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f /
+ ${DESTDIR}${sbindir}/pkcs11-list@EXEEXT@
+
+clean distclean::
+ rm -f ${OBJS} ${TARGETS}
diff --git a/bin/pkcs11/OLD-PKCS11-NOTES b/bin/pkcs11/OLD-PKCS11-NOTES
new file mode 100644
index 0000000..2d07e9f
--- /dev/null
+++ b/bin/pkcs11/OLD-PKCS11-NOTES
@@ -0,0 +1,94 @@
+
+ BIND-9 PKCS#11 support
+
+Prerequisite
+
+The PKCS#11 support needs a PKCS#11 OpenSSL engine based on the Solaris one,
+released the 2008-12-02 for OpenSSL 0.9.8i, with back port of key by reference
+and some improvements, including user friendly PIN management. You may also
+use the original engine code.
+
+Compilation
+
+"configure --with-pkcs11 ..."
+
+PKCS#11 Libraries
+
+Tested with Solaris one with a SCA board and with openCryptoki with the
+software token. Known to work on Linux and Windows 2003 server so
+should work on most operating systems. For AEP Keyper or any device used
+only for its protected key store, please switch to the sign-only engine.
+
+OpenSSL Engines
+
+With PKCS#11 support the PKCS#11 engine is statically loaded but at its
+initialization it dynamically loads the PKCS#11 objects.
+Even the pre commands are therefore unused they are defined with:
+ SO_PATH:
+ define: PKCS11_SO_PATH
+ default: /usr/local/lib/engines/engine_pkcs11.so
+ MODULE_PATH:
+ define: PKCS11_MODULE_PATH
+ default: /usr/lib/libpkcs11.so
+Without PKCS#11 support, a specific OpenSSL engine can be still used
+by defining ENGINE_ID at compile time.
+
+PKCS#11 tools
+
+The contrib/pkcs11-keygen directory contains a set of experimental tools
+to handle keys stored in a Hardware Security Module at the benefit of BIND.
+
+The patch for OpenSSL 0.9.8i is in this directory. Read its README.pkcs11
+for the way to use it (these are the original notes so with the original
+path, etc. Define HAVE_GETPASSPHRASE if you have getpassphrase() on
+a operating system which is not Solaris.)
+
+Not all tools are supported on AEP Keyper but genkey and dnssec-keyfromlabel
+are functional.
+
+PIN management
+
+With the just fixed PKCS#11 OpenSSL engine, the PIN should be entered
+each time it is required. With the improved engine, the PIN should be
+entered the first time it is required or can be configured in the
+OpenSSL configuration file (aka. openssl.cnf) by adding in it:
+ - at the beginning:
+ openssl_conf = openssl_def
+ - at any place these sections:
+ [ openssl_def ]
+ engines = engine_section
+ [ engine_section ]
+ pkcs11 = pkcs11_section
+ [ pkcs11_section ]
+ PIN = put__your__pin__value__here
+
+Slot management
+
+The engine tries to use the first best slot but it is recommended
+to simply use the slot 0 (usual default, meta-slot on Solaris).
+
+Sign-only engine
+
+openssl.../crypto/engine/hw_pk11-kp.c and hw_pk11_pub-kp.c contain
+a stripped down version of hw_pk11.c and hw_pk11_pub.c files which
+has only the useful functions (i.e., signature with a RSA private
+key in the device protected key store and key loading).
+
+This engine should be used with a device which provides mainly
+a protected store and no acceleration. AEP Keyper is an example
+of such a device (BTW with the fully capable engine, key export
+must be enabled on this device and this configuration is not yet
+supported).
+
+Original engine
+
+If you are using the original engine and getpassphrase() is not defined, add:
+#define getpassphrase(x) getpass(x)
+in openssl.../crypto/engine/hw_pk11_pub.c
+
+Notes
+
+Some names here are registered trademarks, at least Solaris is a trademark
+of Sun Microsystems Inc...
+Include files are from RSA Labs., PKCS#11 version is 2.20 amendment 3.
+The PKCS#11 support is compatible with the forthcoming FIPS 140-2 support.
diff --git a/bin/pkcs11/openssl-0.9.8zh-patch b/bin/pkcs11/openssl-0.9.8zh-patch
new file mode 100644
index 0000000..d41feaf
--- /dev/null
+++ b/bin/pkcs11/openssl-0.9.8zh-patch
@@ -0,0 +1,15909 @@
+Index: openssl/Configure
+diff -u openssl/Configure:1.8.6.1.4.1.2.1 openssl/Configure:1.8.2.2
+--- openssl/Configure:1.8.6.1.4.1.2.1 Thu Jul 3 12:12:31 2014
++++ openssl/Configure Thu Jul 3 12:31:57 2014
+@@ -12,7 +12,7 @@
+
+ # see INSTALL for instructions.
+
+-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
++my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+
+ # Options:
+ #
+@@ -25,6 +25,12 @@
+ # default). This needn't be set in advance, you can
+ # just as well use "make INSTALL_PREFIX=/whatever install".
+ #
++# --pk11-libname PKCS#11 library name.
++# (No default)
++#
++# --pk11-flavor either crypto-accelerator or sign-only
++# (No default)
++#
+ # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected
+ # to live in the subdirectory lib/ and the header files in
+ # include/. A value is required.
+@@ -336,7 +342,7 @@
+ "linux-ppc", "gcc:-DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL::linux_ppc32.o::::::::::dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ #### IA-32 targets...
+ "linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_out_asm}",
+ ####
+ "linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+@@ -344,7 +350,7 @@
+ "linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ #### SPARC Linux setups
+ # Ray Miller <ray.miller@computing-services.oxford.ac.uk> has patiently
+ # assisted with debugging of following two configs.
+@@ -591,6 +597,10 @@
+ my $idx_ranlib = $idx++;
+ my $idx_arflags = $idx++;
+
++# PKCS#11 engine patch
++my $pk11_libname="";
++my $pk11_flavor="";
++
+ my $prefix="";
+ my $libdir="";
+ my $openssldir="";
+@@ -829,6 +839,14 @@
+ {
+ $flags.=$_." ";
+ }
++ elsif (/^--pk11-libname=(.*)$/)
++ {
++ $pk11_libname=$1;
++ }
++ elsif (/^--pk11-flavor=(.*)$/)
++ {
++ $pk11_flavor=$1;
++ }
+ elsif (/^--prefix=(.*)$/)
+ {
+ $prefix=$1;
+@@ -964,6 +982,22 @@
+ exit 0;
+ }
+
++if (! $pk11_libname)
++ {
++ print STDERR "You must set --pk11-libname for PKCS#11 library.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
++if (! $pk11_flavor
++ || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only"))
++ {
++ print STDERR "You must set --pk11-flavor.\n";
++ print STDERR "Choices are crypto-accelerator and sign-only.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
+ if ($target =~ m/^CygWin32(-.*)$/) {
+ $target = "Cygwin".$1;
+ }
+@@ -1079,6 +1113,25 @@
+ print "\n";
+ }
+
++if ($pk11_flavor eq "crypto-accelerator")
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $options .= " no-hw-pkcs11so";
++ print " no-hw-pkcs11so [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11SO\n";
++ }
++else
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $options .= " no-hw-pkcs11ca";
++ print " no-hw-pkcs11ca [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11CA\n";
++}
++
+ my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds;
+
+ $IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
+@@ -1130,6 +1183,8 @@
+ if ($flags ne "") { $cflags="$flags$cflags"; }
+ else { $no_user_cflags=1; }
+
++$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags";
++
+ # Kerberos settings. The flavor must be provided from outside, either through
+ # the script "config" or manually.
+ if (!$no_krb5)
+@@ -1493,6 +1548,7 @@
+ s/^VERSION=.*/VERSION=$version/;
+ s/^MAJOR=.*/MAJOR=$major/;
+ s/^MINOR=.*/MINOR=$minor/;
++ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/;
+ s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/;
+ s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/;
+ s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/;
+Index: openssl/Makefile.org
+diff -u openssl/Makefile.org:1.4.6.1.6.1.6.1 openssl/Makefile.org:1.4.2.2
+--- openssl/Makefile.org:1.4.6.1.6.1.6.1 Wed Dec 23 16:02:57 2015
++++ openssl/Makefile.org Wed Dec 23 16:44:50 2015
+@@ -26,6 +26,9 @@
+ INSTALL_PREFIX=
+ INSTALLTOP=/usr/local/ssl
+
++# You must set this through --pk11-libname configure option.
++PK11_LIB_LOCATION=
++
+ # Do not edit this manually. Use Configure --openssldir=DIR do change this!
+ OPENSSLDIR=/usr/local/ssl
+
+Index: openssl/README.pkcs11
+diff -u /dev/null openssl/README.pkcs11:1.6.4.2
+--- /dev/null Wed Dec 23 16:49:05 2015
++++ openssl/README.pkcs11 Fri Oct 4 14:45:25 2013
+@@ -0,0 +1,266 @@
++ISC modified
++============
++
++The previous key naming scheme was kept for backward compatibility.
++
++The PKCS#11 engine exists in two flavors, crypto-accelerator and
++sign-only. The first one is from the Solaris patch and uses the
++PKCS#11 device for all crypto operations it supports. The second
++is a stripped down version which provides only the useful
++function (i.e., signature with a RSA private key in the device
++protected key store and key loading).
++
++As a hint PKCS#11 boards should use the crypto-accelerator flavor,
++external PKCS#11 devices the sign-only. SCA 6000 is an example
++of the first, AEP Keyper of the second.
++
++Note it is mandatory to set a pk11-flavor (and only one) in
++config/Configure.
++
++It is highly recommended to compile in (vs. as a DSO) the engine.
++The way to configure this is system dependent, on Unixes it is no-shared
++(and is in general the default), on WIN32 it is enable-static-engine
++(and still enable to build the OpenSSL libraries as DLLs).
++
++PKCS#11 engine support for OpenSSL 0.9.8l
++=========================================
++
++[Nov 19, 2009]
++
++Contents:
++
++Overview
++Revisions of the patch for 0.9.8 branch
++FAQs
++Feedback
++
++Overview
++========
++
++This patch containing code available in OpenSolaris adds support for PKCS#11
++engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against
++OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system
++must provide PKCS#11 backend otherwise the patch is useless. You provide the
++PKCS#11 library name during the build configuration phase, see below.
++
++Patch can be applied like this:
++
++ # NOTE: use gtar if on Solaris
++ tar xfzv openssl-0.9.8l.tar.gz
++ # now download the patch to the current directory
++ # ...
++ cd openssl-0.9.8l
++ # NOTE: must use gpatch if on Solaris (is part of the system)
++ patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19
++
++It is designed to support pure acceleration for RSA, DSA, DH and all the
++symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share
++except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA.
++
++According to the PKCS#11 providers installed on your machine, it can support
++following mechanisms:
++
++ RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4,
++ AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB,
++ AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224,
++ SHA256, SHA384, SHA512
++
++Note that for AES counter mode the application must provide their own EVP
++functions since OpenSSL doesn't support counter mode through EVP yet. You may
++see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an
++example of code that uses the PKCS#11 engine and deals with the fork-safety
++problem (see engine.c and packet.c files if interested).
++
++You must provide the location of PKCS#11 library in your system to the
++configure script. You will be instructed to do that when you try to run the
++config script:
++
++ $ ./config
++ Operating system: i86pc-whatever-solaris2
++ Configuring for solaris-x86-cc
++ You must set --pk11-libname for PKCS#11 library.
++ See README.pkcs11 for more information.
++
++Taking openCryptoki project on Linux AMD64 box as an example, you would run
++configure script like this:
++
++ ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so
++
++To check whether newly built openssl really supports PKCS#11 it's enough to run
++"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the
++output. If you see no PKCS#11 engine support check that the built openssl binary
++and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits.
++
++The patch, during various phases of development, was tested on Solaris against
++PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and
++OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project
++(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more
++information). Some Linux distributions even ship those libraries with the
++system. The patch should work on any system that is supported by OpenSSL itself
++and has functional PKCS#11 library.
++
++The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are
++copyrighted by RSA Security Inc., see pkcs11.h for more information.
++
++Other added/modified code in this patch is copyrighted by Sun Microsystems,
++Inc. and is released under the OpenSSL license (see LICENSE file for more
++information).
++
++Revisions of the patch for 0.9.8 branch
++=======================================
++
++2009-11-19
++- adjusted for OpenSSL version 0.9.8l
++
++- bugs and RFEs:
++
++ 6479874 OpenSSL should support RSA key by reference/hardware keystores
++ 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split
++ 6732677 make check to trigger Solaris specific code automatic in the
++ PKCS#11 engine
++
++2009-03-11
++- adjusted for OpenSSL version 0.9.8j
++
++- README.pkcs11 moved out of the patch, and is shipped together with it in a
++ tarball instead so that it can be read before the patch is applied.
++
++- fixed bugs:
++
++ 6804216 pkcs#11 engine should support a key length range for RC4
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-12-02
++- fixed bugs and RFEs (most of the work done by Vladimir Kotal)
++
++ 6723504 more granular locking in PKCS#11 engine
++ 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true
++ 6710420 PKCS#11 engine source should be lint clean
++ 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take
++ it seriously
++ 6746712 PKCS#11 engine source code should be cstyle clean
++ 6731380 return codes of several functions are not checked in the PKCS#11
++ engine code
++ 6746735 PKCS#11 engine should use extended FILE space API
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-08-01
++- fixed bug
++
++ 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers
++ and digests
++
++- Solaris specific code for slot selection made automatic
++
++2008-07-29
++- update the patch to OpenSSL 0.9.8h version
++- pkcs11t.h updated to the latest version:
++
++ 6545665 make CKM_AES_CTR available to non-kernel users
++
++- fixed bugs in the engine code:
++
++ 6602801 PK11_SESSION cache has to employ reference counting scheme for
++ asymmetric key operations
++ 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called
++ atomically
++ 6607307 pkcs#11 engine can't read RSA private keys
++ 6652362 pk11_RSA_finish() is cutting corners
++ 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in
++ suboptimal way
++ 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more
++ resilient to destroy failures
++ 6667273 OpenSSL engine should not use free() but OPENSSL_free()
++ 6670363 PKCS#11 engine fails to reuse existing symmetric keys
++ 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine
++ 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size
++ of big numbers leading to failures
++ 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of
++ -1
++ 6706622 pk11_load_{pub,priv}key create corrupted RSA key references
++ 6707129 return values from BN_new() in pk11_DH_generate_key() are not
++ checked
++ 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to
++ structure reuse
++ 6707782 OpenSSL PKCS#11 engine pretends to be aware of
++ OPENSSL_NO_{RSA,DSA,DH}
++ defines but fails miserably
++ 6709966 make check_new_*() to return values to indicate cache hit/miss
++ 6705200 pk11_dh struct initialization in PKCS#11 engine is missing
++ generate_params parameter
++ 6709513 PKCS#11 engine sets IV length even for ECB modes
++ 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the
++ PKCS#11 engine
++ 6728871 PKCS#11 engine must reset global_session in pk11_finish()
++
++- new features and enhancements:
++
++ 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512
++ 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes
++ 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric
++ ciphers and digests
++
++2007-10-15
++- update for 0.9.8f version
++- update for "6607670 teach pkcs#11 engine how to use keys be reference"
++
++2007-10-02
++- draft for "6607670 teach pkcs#11 engine how to use keys be reference"
++- draft for "6607307 pkcs#11 engine can't read RSA private keys"
++
++2007-09-26
++- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes
++ significant performance drop
++- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine
++
++2007-05-25
++- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers
++
++2007-05-19
++- initial patch for 0.9.8e using latest OpenSolaris code
++
++FAQs
++====
++
++(1) my build failed on Linux distro with this error:
++
++../libcrypto.a(hw_pk11.o): In function `pk11_library_init':
++hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork'
++
++Answer:
++
++ - don't use "no-threads" when configuring
++ - if you didn't then OpenSSL failed to create a threaded library by
++ default. You may manually edit Configure and try again. Look for the
++ architecture that Configure printed, for example:
++
++Configured for linux-elf.
++
++ - then edit Configure, find string "linux-elf" (inluding the quotes),
++ and add flags to support threads to the 4th column of the 2nd string.
++ If you build with GCC then adding "-pthread" should be enough. With
++ "linux-elf" as an example, you would add " -pthread" right after
++ "-D_REENTRANT", like this:
++
++....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:.....
++
++(2) I'm using MinGW/MSYS environment and get undeclared reference error for
++pthread_atfork() function when trying to build OpenSSL with the patch.
++
++Answer:
++
++ Sorry, pthread_atfork() is not implemented in the current pthread-win32
++ (as of Nov 2009). You can not use the patch there.
++
++
++Feedback
++========
++
++Please send feedback to security-discuss@opensolaris.org. The patch was
++created by Jan.Pechanec@Sun.COM from code available in OpenSolaris.
++
++Latest version should be always available on http://blogs.sun.com/janp.
++
+Index: openssl/crypto/opensslconf.h
+diff -u openssl/crypto/opensslconf.h:1.5.10.1 openssl/crypto/opensslconf.h:1.5
+--- openssl/crypto/opensslconf.h:1.5.10.1 Sun Jan 15 15:45:34 2012
++++ openssl/crypto/opensslconf.h Fri Sep 4 10:43:21 2009
+@@ -38,6 +38,9 @@
+
+ #endif /* OPENSSL_DOING_MAKEDEPEND */
+
++#ifndef OPENSSL_THREADS
++# define OPENSSL_THREADS
++#endif
+ #ifndef OPENSSL_NO_DYNAMIC_ENGINE
+ # define OPENSSL_NO_DYNAMIC_ENGINE
+ #endif
+@@ -79,6 +82,8 @@
+ # endif
+ #endif
+
++#define OPENSSL_CPUID_OBJ
++
+ /* crypto/opensslconf.h.in */
+
+ #ifdef OPENSSL_DOING_MAKEDEPEND
+@@ -140,7 +145,7 @@
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+-#undef RC4_CHUNK
++#define RC4_CHUNK unsigned long
+ #endif
+ #endif
+
+@@ -148,7 +153,7 @@
+ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+ #ifndef DES_LONG
+-#define DES_LONG unsigned long
++#define DES_LONG unsigned int
+ #endif
+ #endif
+
+@@ -162,9 +167,9 @@
+ /* The prime number generation stuff may not work when
+ * EIGHT_BIT but I don't care since I've only used this mode
+ * for debuging the bignum libraries */
+-#undef SIXTY_FOUR_BIT_LONG
++#define SIXTY_FOUR_BIT_LONG
+ #undef SIXTY_FOUR_BIT
+-#define THIRTY_TWO_BIT
++#undef THIRTY_TWO_BIT
+ #undef SIXTEEN_BIT
+ #undef EIGHT_BIT
+ #endif
+@@ -178,7 +183,7 @@
+
+ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+ #define CONFIG_HEADER_BF_LOCL_H
+-#undef BF_PTR
++#define BF_PTR2
+ #endif /* HEADER_BF_LOCL_H */
+
+ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+@@ -208,7 +213,7 @@
+ /* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+ #ifndef DES_UNROLL
+-#undef DES_UNROLL
++#define DES_UNROLL
+ #endif
+
+ /* These default values were supplied by
+Index: openssl/crypto/bio/bss_file.c
+diff -u openssl/crypto/bio/bss_file.c:1.5.6.1.12.1 openssl/crypto/bio/bss_file.c:1.5.2.1
+--- openssl/crypto/bio/bss_file.c:1.5.6.1.12.1 Wed Dec 23 16:03:19 2015
++++ openssl/crypto/bio/bss_file.c Wed Dec 23 16:45:10 2015
+@@ -123,7 +123,7 @@
+ if ((file = fopen(filename, mode)) == NULL) {
+ SYSerr(SYS_F_FOPEN, get_last_sys_error());
+ ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
+- if (errno == ENOENT)
++ if ((errno == ENOENT) || ((*mode == 'r') && (errno == EACCES)))
+ BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
+ else
+ BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
+Index: openssl/crypto/engine/Makefile
+diff -u openssl/crypto/engine/Makefile:1.6.6.1 openssl/crypto/engine/Makefile:1.6
+--- openssl/crypto/engine/Makefile:1.6.6.1 Sun Jan 15 15:45:35 2012
++++ openssl/crypto/engine/Makefile Mon Jun 13 14:25:19 2011
+@@ -21,12 +21,14 @@
+ eng_table.c eng_pkey.c eng_fat.c eng_all.c \
+ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \
+ tb_cipher.c tb_digest.c \
+- eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c
++ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c \
++ hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c
+ LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
+ eng_table.o eng_pkey.o eng_fat.o eng_all.o \
+ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \
+ tb_cipher.o tb_digest.o \
+- eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o
++ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o \
++ hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o
+
+ SRC= $(LIBSRC)
+
+@@ -288,6 +290,102 @@
+ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+ eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+ eng_table.o: eng_table.c
++hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
++hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h
++hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h
++hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h
++hw_pk11.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h
++hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h
++hw_pk11.o: ../../include/openssl/dh.h ../../include/openssl/rand.h
++hw_pk11.o: ../../include/openssl/ui.h ../../include/openssl/err.h
++hw_pk11.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h
++hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/evp.h
++hw_pk11.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
++hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/sha.h
++hw_pk11.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h
++hw_pk11.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h
++hw_pk11.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h
++hw_pk11.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h
++hw_pk11.o: ../../include/openssl/cast.h ../../include/openssl/idea.h
++hw_pk11.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h
++hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h
++hw_pk11.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h
++hw_pk11.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h
++hw_pk11.o: ../../include/openssl/pem2.h ../cryptlib.h
++hw_pk11.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11.c
++hw_pk11_pub.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
++hw_pk11_pub.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h
++hw_pk11_pub.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h
++hw_pk11_pub.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11_pub.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h
++hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h
++hw_pk11_pub.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h
++hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/rand.h
++hw_pk11_pub.o: ../../include/openssl/ui.h ../../include/openssl/err.h
++hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h
++hw_pk11_pub.o: ../../include/openssl/pem.h ../../include/openssl/evp.h
++hw_pk11_pub.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
++hw_pk11_pub.o: ../../include/openssl/md5.h ../../include/openssl/sha.h
++hw_pk11_pub.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h
++hw_pk11_pub.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h
++hw_pk11_pub.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h
++hw_pk11_pub.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h
++hw_pk11_pub.o: ../../include/openssl/cast.h ../../include/openssl/idea.h
++hw_pk11_pub.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h
++hw_pk11_pub.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h
++hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h
++hw_pk11_pub.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h
++hw_pk11_pub.o: ../../include/openssl/pem2.h ../cryptlib.h
++hw_pk11_pub.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11_pub.c
++hw_pk11so.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
++hw_pk11so.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h
++hw_pk11so.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h
++hw_pk11so.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11so.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h
++hw_pk11so.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h
++hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h
++hw_pk11so.o: ../../include/openssl/dh.h ../../include/openssl/rand.h
++hw_pk11so.o: ../../include/openssl/ui.h ../../include/openssl/err.h
++hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h
++hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/evp.h
++hw_pk11so.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
++hw_pk11so.o: ../../include/openssl/md5.h ../../include/openssl/sha.h
++hw_pk11so.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h
++hw_pk11so.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h
++hw_pk11so.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h
++hw_pk11so.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h
++hw_pk11so.o: ../../include/openssl/cast.h ../../include/openssl/idea.h
++hw_pk11so.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h
++hw_pk11so.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h
++hw_pk11so.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h
++hw_pk11so.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h
++hw_pk11so.o: ../../include/openssl/pem2.h ../cryptlib.h
++hw_pk11so.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11so.c
++hw_pk11so_pub.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
++hw_pk11so_pub.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h
++hw_pk11so_pub.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h
++hw_pk11so_pub.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11so_pub.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h
++hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h
++hw_pk11so_pub.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h
++hw_pk11so_pub.o: ../../include/openssl/dh.h ../../include/openssl/rand.h
++hw_pk11so_pub.o: ../../include/openssl/ui.h ../../include/openssl/err.h
++hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h
++hw_pk11so_pub.o: ../../include/openssl/pem.h ../../include/openssl/evp.h
++hw_pk11so_pub.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
++hw_pk11so_pub.o: ../../include/openssl/md5.h ../../include/openssl/sha.h
++hw_pk11so_pub.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h
++hw_pk11so_pub.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h
++hw_pk11so_pub.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h
++hw_pk11so_pub.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h
++hw_pk11so_pub.o: ../../include/openssl/cast.h ../../include/openssl/idea.h
++hw_pk11so_pub.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h
++hw_pk11so_pub.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h
++hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h
++hw_pk11so_pub.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h
++hw_pk11so_pub.o: ../../include/openssl/pem2.h ../cryptlib.h
++hw_pk11so_pub.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11so_pub.c
+ tb_cipher.o: ../../e_os.h ../../include/openssl/asn1.h
+ tb_cipher.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+ tb_cipher.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+Index: openssl/crypto/engine/cryptoki.h
+diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4
+--- /dev/null Wed Dec 23 16:49:05 2015
++++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008
+@@ -0,0 +1,103 @@
++/*
++ * CDDL HEADER START
++ *
++ * The contents of this file are subject to the terms of the
++ * Common Development and Distribution License, Version 1.0 only
++ * (the "License"). You may not use this file except in compliance
++ * with the License.
++ *
++ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
++ * or http://www.opensolaris.org/os/licensing.
++ * See the License for the specific language governing permissions
++ * and limitations under the License.
++ *
++ * When distributing Covered Code, include this CDDL HEADER in each
++ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
++ * If applicable, add the following below this CDDL HEADER, with the
++ * fields enclosed by brackets "[]" replaced with your own identifying
++ * information: Portions Copyright [yyyy] [name of copyright owner]
++ *
++ * CDDL HEADER END
++ */
++/*
++ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _CRYPTOKI_H
++#define _CRYPTOKI_H
++
++/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef CK_PTR
++#define CK_PTR *
++#endif
++
++#ifndef CK_DEFINE_FUNCTION
++#define CK_DEFINE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION
++#define CK_DECLARE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION_POINTER
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
++#endif
++
++#ifndef CK_CALLBACK_FUNCTION
++#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
++#endif
++
++#ifndef NULL_PTR
++#include <unistd.h> /* For NULL */
++#define NULL_PTR NULL
++#endif
++
++/*
++ * pkcs11t.h defines TRUE and FALSE in a way that upsets lint
++ */
++#ifndef CK_DISABLE_TRUE_FALSE
++#define CK_DISABLE_TRUE_FALSE
++#ifndef TRUE
++#define TRUE 1
++#endif /* TRUE */
++#ifndef FALSE
++#define FALSE 0
++#endif /* FALSE */
++#endif /* CK_DISABLE_TRUE_FALSE */
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++#include "pkcs11.h"
++
++/* Solaris specific functions */
++
++#include <stdlib.h>
++
++/*
++ * SUNW_C_GetMechSession will initialize the framework and do all
++ * the necessary PKCS#11 calls to create a session capable of
++ * providing operations on the requested mechanism
++ */
++CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech,
++ CK_SESSION_HANDLE_PTR hSession);
++
++/*
++ * SUNW_C_KeyToObject will create a secret key object for the given
++ * mechanism from the rawkey data.
++ */
++CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len,
++ CK_OBJECT_HANDLE_PTR obj);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _CRYPTOKI_H */
+Index: openssl/crypto/engine/eng_all.c
+diff -u openssl/crypto/engine/eng_all.c:1.4.6.1.6.1.6.1 openssl/crypto/engine/eng_all.c:1.4.2.2
+--- openssl/crypto/engine/eng_all.c:1.4.6.1.6.1.6.1 Wed Dec 23 16:03:42 2015
++++ openssl/crypto/engine/eng_all.c Wed Dec 23 16:45:32 2015
+@@ -113,6 +113,14 @@
+ # if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+ ENGINE_load_cryptodev();
+ # endif
++# ifndef OPENSSL_NO_HW_PKCS11
++# ifndef OPENSSL_NO_HW_PKCS11CA
++ ENGINE_load_pk11ca();
++# endif
++# ifndef OPENSSL_NO_HW_PKCS11SO
++ ENGINE_load_pk11so();
++# endif
++# endif
+ #endif
+ }
+
+Index: openssl/crypto/engine/engine.h
+diff -u openssl/crypto/engine/engine.h:1.4.6.1.6.1.6.1 openssl/crypto/engine/engine.h:1.4.2.2
+--- openssl/crypto/engine/engine.h:1.4.6.1.6.1.6.1 Wed Dec 23 16:03:44 2015
++++ openssl/crypto/engine/engine.h Wed Dec 23 16:45:34 2015
+@@ -403,6 +403,12 @@
+ void ENGINE_load_cryptodev(void);
+ void ENGINE_load_padlock(void);
+ void ENGINE_load_builtin_engines(void);
++# ifndef OPENSSL_NO_HW_PKCS11CA
++void ENGINE_load_pk11ca(void);
++# endif
++# ifndef OPENSSL_NO_HW_PKCS11SO
++void ENGINE_load_pk11so(void);
++# endif
+
+ /*
+ * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+Index: openssl/crypto/engine/hw_pk11.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.26.4.4
+--- /dev/null Wed Dec 23 16:49:05 2015
++++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:45:25 2013
+@@ -0,0 +1,4116 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++#include <openssl/aes.h>
++#include <openssl/des.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/* #undef DEBUG_SLOT_SELECTION */
++/*
++ * Solaris specific code. See comment at check_hw_mechanisms() for more
++ * information.
++ */
++#if defined(__SVR4) && defined(__sun)
++#undef SOLARIS_HW_SLOT_SELECTION
++#endif
++
++/*
++ * AES counter mode is not supported in the OpenSSL EVP API yet and neither
++ * there are official OIDs for mechanisms based on this mode. With our changes,
++ * an application can define its own EVP calls for AES counter mode and then
++ * it can make use of hardware acceleration through this engine. However, it's
++ * better if we keep AES CTR support code under ifdef's.
++ */
++#define SOLARIS_AES_CTR
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.c"
++
++#ifdef SOLARIS_AES_CTR
++/*
++ * NIDs for AES counter mode that will be defined during the engine
++ * initialization.
++ */
++static int NID_aes_128_ctr = NID_undef;
++static int NID_aes_192_ctr = NID_undef;
++static int NID_aes_256_ctr = NID_undef;
++#endif /* SOLARIS_AES_CTR */
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel
++ * library. See comment at check_hw_mechanisms() for more information.
++ */
++static int *hw_cnids;
++static int *hw_dnids;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++#ifndef OPENSSL_NO_RSA
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DSA
++int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DH
++int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock);
++#endif
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++/* Symmetric cipher and digest support functions */
++static int cipher_nid_to_pk11(int nid);
++#ifdef SOLARIS_AES_CTR
++static int pk11_add_NID(char *sn, char *ln);
++static int pk11_add_aes_ctr_NIDs(void);
++#endif /* SOLARIS_AES_CTR */
++static int pk11_usable_ciphers(const int **nids);
++static int pk11_usable_digests(const int **nids);
++static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc);
++static int pk11_cipher_final(PK11_SESSION *sp);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl);
++#else
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl);
++#endif
++static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx);
++static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid);
++static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid);
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp);
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len);
++static int md_nid_to_pk11(int nid);
++static int pk11_digest_init(EVP_MD_CTX *ctx);
++static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data,
++ size_t count);
++static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md);
++static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
++static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
++
++static int pk11_choose_slots(int *any_slot_found);
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher,
++ int *local_cipher_nids);
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest,
++ int *local_digest_nids);
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids,
++ int id);
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++static int check_hw_mechanisms(void);
++static int nid_in_table(int nid, int *nid_table);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* Index for the supported ciphers */
++enum pk11_cipher_id {
++ PK11_DES_CBC,
++ PK11_DES3_CBC,
++ PK11_DES_ECB,
++ PK11_DES3_ECB,
++ PK11_RC4,
++ PK11_AES_128_CBC,
++ PK11_AES_192_CBC,
++ PK11_AES_256_CBC,
++ PK11_AES_128_ECB,
++ PK11_AES_192_ECB,
++ PK11_AES_256_ECB,
++ PK11_BLOWFISH_CBC,
++#ifdef SOLARIS_AES_CTR
++ PK11_AES_128_CTR,
++ PK11_AES_192_CTR,
++ PK11_AES_256_CTR,
++#endif /* SOLARIS_AES_CTR */
++ PK11_CIPHER_MAX
++};
++
++/* Index for the supported digests */
++enum pk11_digest_id {
++ PK11_MD5,
++ PK11_SHA1,
++ PK11_SHA224,
++ PK11_SHA256,
++ PK11_SHA384,
++ PK11_SHA512,
++ PK11_DIGEST_MAX
++};
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static int cipher_nids[PK11_CIPHER_MAX];
++static int digest_nids[PK11_DIGEST_MAX];
++static int cipher_count = 0;
++static int digest_count = 0;
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_recover = CK_FALSE;
++static CK_BBOOL pk11_have_dsa = CK_FALSE;
++static CK_BBOOL pk11_have_dh = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++typedef struct PK11_CIPHER_st
++ {
++ enum pk11_cipher_id id;
++ int nid;
++ int iv_len;
++ int min_key_len;
++ int max_key_len;
++ CK_KEY_TYPE key_type;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_CIPHER;
++
++static PK11_CIPHER ciphers[] =
++ {
++ { PK11_DES_CBC, NID_des_cbc, 8, 8, 8,
++ CKK_DES, CKM_DES_CBC, },
++ { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24,
++ CKK_DES3, CKM_DES3_CBC, },
++ { PK11_DES_ECB, NID_des_ecb, 0, 8, 8,
++ CKK_DES, CKM_DES_ECB, },
++ { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24,
++ CKK_DES3, CKM_DES3_ECB, },
++ { PK11_RC4, NID_rc4, 0, 16, 256,
++ CKK_RC4, CKM_RC4, },
++ { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16,
++ CKK_BLOWFISH, CKM_BLOWFISH_CBC, },
++#ifdef SOLARIS_AES_CTR
++ /* we don't know the correct NIDs until the engine is initialized */
++ { PK11_AES_128_CTR, NID_undef, 16, 16, 16,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_192_CTR, NID_undef, 16, 24, 24,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_256_CTR, NID_undef, 16, 32, 32,
++ CKK_AES, CKM_AES_CTR, },
++#endif /* SOLARIS_AES_CTR */
++ };
++
++typedef struct PK11_DIGEST_st
++ {
++ enum pk11_digest_id id;
++ int nid;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_DIGEST;
++
++static PK11_DIGEST digests[] =
++ {
++ {PK11_MD5, NID_md5, CKM_MD5, },
++ {PK11_SHA1, NID_sha1, CKM_SHA_1, },
++ {PK11_SHA224, NID_sha224, CKM_SHA224, },
++ {PK11_SHA256, NID_sha256, CKM_SHA256, },
++ {PK11_SHA384, NID_sha384, CKM_SHA384, },
++ {PK11_SHA512, NID_sha512, CKM_SHA512, },
++ {0, NID_undef, 0xFFFF, },
++ };
++
++/*
++ * Structure to be used for the cipher_data/md_data in
++ * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11
++ * session in multiple cipher_update calls
++ */
++typedef struct PK11_CIPHER_STATE_st
++ {
++ PK11_SESSION *sp;
++ } PK11_CIPHER_STATE;
++
++
++/*
++ * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets
++ * called when libcrypto requests a cipher NID.
++ *
++ * Note how the PK11_CIPHER_STATE is used here.
++ */
++
++/* DES CBC EVP */
++static const EVP_CIPHER pk11_des_cbc =
++ {
++ NID_des_cbc,
++ 8, 8, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/* 3DES CBC EVP */
++static const EVP_CIPHER pk11_3des_cbc =
++ {
++ NID_des_ede3_cbc,
++ 8, 24, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and
++ * get_asn1_parameters fields are set to NULL.
++ */
++static const EVP_CIPHER pk11_des_ecb =
++ {
++ NID_des_ecb,
++ 8, 8, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_3des_ecb =
++ {
++ NID_des_ede3_ecb,
++ 8, 24, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++
++static const EVP_CIPHER pk11_aes_128_cbc =
++ {
++ NID_aes_128_cbc,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_cbc =
++ {
++ NID_aes_192_cbc,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_cbc =
++ {
++ NID_aes_256_cbc,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use IV so that's why set_asn1_parameters and
++ * get_asn1_parameters are set to NULL.
++ */
++static const EVP_CIPHER pk11_aes_128_ecb =
++ {
++ NID_aes_128_ecb,
++ 16, 16, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_ecb =
++ {
++ NID_aes_192_ecb,
++ 16, 24, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_ecb =
++ {
++ NID_aes_256_ecb,
++ 16, 32, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++#ifdef SOLARIS_AES_CTR
++/*
++ * NID_undef's will be changed to the AES counter mode NIDs as soon they are
++ * created in pk11_library_init(). Note that the need to change these structures
++ * is the reason why we don't define them with the const keyword.
++ */
++static EVP_CIPHER pk11_aes_128_ctr =
++ {
++ NID_undef,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static EVP_CIPHER pk11_aes_192_ctr =
++ {
++ NID_undef,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static EVP_CIPHER pk11_aes_256_ctr =
++ {
++ NID_undef,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++#endif /* SOLARIS_AES_CTR */
++
++static const EVP_CIPHER pk11_bf_cbc =
++ {
++ NID_bf_cbc,
++ 8, 16, 8,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_rc4 =
++ {
++ NID_rc4,
++ 1, 16, 0,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_MD pk11_md5 =
++ {
++ NID_md5,
++ NID_md5WithRSAEncryption,
++ MD5_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ MD5_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha1 =
++ {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha224 =
++ {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-224 uses the same cblock size as SHA-256 */
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha256 =
++ {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha384 =
++ {
++ NID_sha384,
++ NID_sha384WithRSAEncryption,
++ SHA384_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-384 uses the same cblock size as SHA-512 */
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha512 =
++ {
++ NID_sha512,
++ NID_sha512WithRSAEncryption,
++ SHA512_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11SO
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name =
++ "PKCS #11 engine support (crypto accelerator)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++#ifndef OPENSSL_NO_RSA
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DSA], &attr);
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DH] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DH], &attr);
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++#ifndef OPENSSL_NO_RSA
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (find_lock[OP_DSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DSA]);
++ OPENSSL_free(find_lock[OP_DSA]);
++ find_lock[OP_DSA] = NULL;
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (find_lock[OP_DH] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DH]);
++ OPENSSL_free(find_lock[OP_DH]);
++ find_lock[OP_DH] = NULL;
++ }
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++#ifndef OPENSSL_NO_RSA
++ const RSA_METHOD *rsa = NULL;
++ RSA_METHOD *pk11_rsa = PK11_RSA();
++#endif /* OPENSSL_NO_RSA */
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name) ||
++ !ENGINE_set_ciphers(e, pk11_engine_ciphers) ||
++ !ENGINE_set_digests(e, pk11_engine_digests))
++ return (0);
++#ifndef OPENSSL_NO_RSA
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (pk11_have_dsa == CK_TRUE)
++ {
++ if (!ENGINE_set_DSA(e, PK11_DSA()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (pk11_have_dh == CK_TRUE)
++ {
++ if (!ENGINE_set_DH(e, PK11_DH()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DH\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DH */
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++/*
++ * Apache calls OpenSSL function RSA_blinding_on() once during startup
++ * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp
++ * here, we wire it back to the OpenSSL software implementation.
++ * Since it is used only once, performance is not a concern.
++ */
++#ifndef OPENSSL_NO_RSA
++ rsa = RSA_PKCS1_SSLeay();
++ pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp;
++ pk11_rsa->bn_mod_exp = rsa->bn_mod_exp;
++ if (pk11_have_recover != CK_TRUE)
++ pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec;
++#endif /* OPENSSL_NO_RSA */
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ LOCK_OBJSTORE(OP_DSA);
++ LOCK_OBJSTORE(OP_DH);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ CK_ULONG ul_state_len;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++#ifdef SOLARIS_AES_CTR
++ /*
++ * We must do this before we start working with slots since we need all
++ * NIDs there.
++ */
++ if (pk11_add_aes_ctr_NIDs() == 0)
++ goto err;
++#endif /* SOLARIS_AES_CTR */
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ /*
++ * Disable digest if C_GetOperationState is not supported since
++ * this function is required by OpenSSL digest copy function
++ */
++ /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */
++ if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len)
++ != CKR_OK) {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: C_GetOperationState() not supported, "
++ "setting digest_count to 0\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ digest_count = 0;
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ break;
++#endif
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++#ifndef OPENSSL_NO_RSA
++ (void) pk11_destroy_rsa_key_objects(NULL);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ (void) pk11_destroy_dsa_key_objects(NULL);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ (void) pk11_destroy_dh_key_objects(NULL);
++#endif /* OPENSSL_NO_DH */
++ (void) pk11_destroy_cipher_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ case OP_DIGEST:
++ case OP_CIPHER:
++ myslot = SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ break;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ sp->opdata_dsa_pub_num = NULL;
++ sp->opdata_dsa_priv = NULL;
++ sp->opdata_dsa_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ sp->opdata_dh_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DH */
++ case OP_CIPHER:
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ sp->opdata_encrypt = -1;
++ break;
++ default:
++ break;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++/* Destroy DSA public key from single session. */
++int
++pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key,
++ ret, uselock, OP_DSA, CK_FALSE);
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy DSA private key from single session. */
++int
++pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key,
++ ret, uselock, OP_DSA, CK_TRUE);
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv = NULL;
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_dsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_dsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++/* Destroy DH key from single session. */
++int
++pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dh_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dh_key,
++ ret, uselock, OP_DH, CK_TRUE);
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DH key object wrapper.
++ *
++ * arg0: pointer to PKCS#11 engine session structure
++ * if session is NULL, try to destroy all objects in the free list
++ */
++int
++pk11_destroy_dh_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DH].head;
++ uselock = FALSE;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dh_object(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DH */
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/* Symmetric ciphers and digests support functions */
++
++static int
++cipher_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; i++)
++ if (ciphers[i].nid == nid)
++ return (ciphers[i].id);
++ return (-1);
++ }
++
++static int
++pk11_usable_ciphers(const int **nids)
++ {
++ if (cipher_count > 0)
++ *nids = cipher_nids;
++ else
++ *nids = NULL;
++ return (cipher_count);
++ }
++
++static int
++pk11_usable_digests(const int **nids)
++ {
++ if (digest_count > 0)
++ *nids = digest_nids;
++ else
++ *nids = NULL;
++ return (digest_count);
++ }
++
++/*
++ * Init context for encryption or decryption using a symmetric key.
++ */
++static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher,
++ PK11_SESSION *sp, CK_MECHANISM_PTR pmech)
++ {
++ CK_RV rv;
++#ifdef SOLARIS_AES_CTR
++ CK_AES_CTR_PARAMS ctr_params;
++#endif /* SOLARIS_AES_CTR */
++
++ /*
++ * We expect pmech->mechanism to be already set and
++ * pParameter/ulParameterLen initialized to NULL/0 before
++ * pk11_init_symetric() is called.
++ */
++ OPENSSL_assert(pmech->mechanism != 0);
++ OPENSSL_assert(pmech->pParameter == NULL);
++ OPENSSL_assert(pmech->ulParameterLen == 0);
++
++#ifdef SOLARIS_AES_CTR
++ if (ctx->cipher->nid == NID_aes_128_ctr ||
++ ctx->cipher->nid == NID_aes_192_ctr ||
++ ctx->cipher->nid == NID_aes_256_ctr)
++ {
++ pmech->pParameter = (void *)(&ctr_params);
++ pmech->ulParameterLen = sizeof (ctr_params);
++ /*
++ * For now, we are limited to the fixed length of the counter,
++ * it covers the whole counter block. That's what RFC 4344
++ * needs. For more information on internal structure of the
++ * counter block, see RFC 3686. If needed in the future, we can
++ * add code so that the counter length can be set via
++ * ENGINE_ctrl() function.
++ */
++ ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8;
++ OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE);
++ (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE);
++ }
++ else
++#endif /* SOLARIS_AES_CTR */
++ {
++ if (pcipher->iv_len > 0)
++ {
++ pmech->pParameter = (void *)ctx->iv;
++ pmech->ulParameterLen = pcipher->iv_len;
++ }
++ }
++
++ /* if we get here, the encryption needs to be reinitialized */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++ else
++ rv = pFuncList->C_DecryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ?
++ PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/* ARGSUSED */
++static int
++pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc)
++ {
++ CK_MECHANISM mech;
++ int index;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ PK11_CIPHER *p_ciph_table_row;
++
++ state->sp = NULL;
++
++ index = cipher_nid_to_pk11(ctx->cipher->nid);
++ if (index < 0 || index >= PK11_CIPHER_MAX)
++ return (0);
++
++ p_ciph_table_row = &ciphers[index];
++ /*
++ * iv_len in the ctx->cipher structure is the maximum IV length for the
++ * current cipher and it must be less or equal to the IV length in our
++ * ciphers table. The key length must be in the allowed interval. From
++ * all cipher modes that the PKCS#11 engine supports only RC4 allows a
++ * key length to be in some range, all other NIDs have a precise key
++ * length. Every application can define its own EVP functions so this
++ * code serves as a sanity check.
++ *
++ * Note that the reason why the IV length in ctx->cipher might be
++ * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs
++ * macro to define functions that return EVP structures for all DES
++ * modes. So, even ECB modes get 8 byte IV.
++ */
++ if (ctx->cipher->iv_len < p_ciph_table_row->iv_len ||
++ ctx->key_len < p_ciph_table_row->min_key_len ||
++ ctx->key_len > p_ciph_table_row->max_key_len) {
++ PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM);
++ return (0);
++ }
++
++ if ((sp = pk11_get_session(OP_CIPHER)) == NULL)
++ return (0);
++
++ /* if applicable, the mechanism parameter is used for IV */
++ mech.mechanism = p_ciph_table_row->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ /* The key object is destroyed here if it is not the current key. */
++ (void) check_new_cipher_key(sp, key, ctx->key_len);
++
++ /*
++ * If the key is the same and the encryption is also the same, then
++ * just reuse it. However, we must not forget to reinitialize the
++ * context that was finalized in pk11_cipher_cleanup().
++ */
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE &&
++ sp->opdata_encrypt == ctx->encrypt)
++ {
++ state->sp = sp;
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ return (1);
++ }
++
++ /*
++ * Check if the key has been invalidated. If so, a new key object
++ * needs to be created.
++ */
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ sp->opdata_cipher_key = pk11_get_cipher_key(
++ ctx, key, p_ciph_table_row->key_type, sp);
++ }
++
++ if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1)
++ {
++ /*
++ * The previous encryption/decryption is different. Need to
++ * terminate the previous * active encryption/decryption here.
++ */
++ if (!pk11_cipher_final(sp))
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++ }
++
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ /* now initialize the context with a new key */
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ sp->opdata_encrypt = ctx->encrypt;
++ state->sp = sp;
++
++ return (1);
++ }
++
++/*
++ * When reusing the same key in an encryption/decryption session for a
++ * decryption/encryption session, we need to close the active session
++ * and recreate a new one. Note that the key is in the global session so
++ * that it needs not be recreated.
++ *
++ * It is more appropriate to use C_En/DecryptFinish here. At the time of this
++ * development, these two functions in the PKCS#11 libraries used return
++ * unexpected errors when passing in 0 length output. It may be a good
++ * idea to try them again if performance is a problem here and fix
++ * C_En/DecryptFinial if there are bugs there causing the problem.
++ */
++static int
++pk11_cipher_final(PK11_SESSION *sp)
++ {
++ CK_RV rv;
++
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * An engine interface function. The calling function allocates sufficient
++ * memory for the output buffer "out" to hold the results.
++ */
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl)
++#else
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl)
++#endif
++ {
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ CK_RV rv;
++ unsigned long outl = inl;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ sp = (PK11_SESSION *) state->sp;
++
++ if (!inl)
++ return (1);
++
++ /* RC4 is the only stream cipher we support */
++ if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0)
++ return (0);
++
++ if (ctx->encrypt)
++ {
++ rv = pFuncList->C_EncryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_ENCRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++ else
++ {
++ rv = pFuncList->C_DecryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_DECRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++
++ /*
++ * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always
++ * the same size of input.
++ * The application has guaranteed to call the block ciphers with
++ * correctly aligned buffers.
++ */
++ if (inl != outl)
++ return (0);
++
++ return (1);
++ }
++
++/*
++ * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal()
++ * here is the right thing because in EVP_DecryptFinal_ex(), engine's
++ * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but
++ * the engine can't find out that it's the finalizing call. We wouldn't
++ * necessarily have to finalize the context here since reinitializing it with
++ * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness,
++ * let's do it. Some implementations might leak memory if the previously used
++ * context is initialized without finalizing it first.
++ */
++static int
++pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_ULONG len = EVP_MAX_BLOCK_LENGTH;
++ CK_BYTE buf[EVP_MAX_BLOCK_LENGTH];
++ PK11_CIPHER_STATE *state = ctx->cipher_data;
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * We are not interested in the data here, we just need to get
++ * rid of the context.
++ */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptFinal(
++ state->sp->session, buf, &len);
++ else
++ rv = pFuncList->C_DecryptFinal(
++ state->sp->session, buf, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ?
++ PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv);
++ pk11_return_session(state->sp, OP_CIPHER);
++ return (0);
++ }
++
++ pk11_return_session(state->sp, OP_CIPHER);
++ state->sp = NULL;
++ }
++
++ return (1);
++ }
++
++/*
++ * Registered by the ENGINE when used to find out how to deal with
++ * a particular NID in the ENGINE. This says what we'll do at the
++ * top level - note, that list is restricted by what we answer with
++ */
++/* ARGSUSED */
++static int
++pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid)
++ {
++ if (!cipher)
++ return (pk11_usable_ciphers(nids));
++
++ switch (nid)
++ {
++ case NID_des_ede3_cbc:
++ *cipher = &pk11_3des_cbc;
++ break;
++ case NID_des_cbc:
++ *cipher = &pk11_des_cbc;
++ break;
++ case NID_des_ede3_ecb:
++ *cipher = &pk11_3des_ecb;
++ break;
++ case NID_des_ecb:
++ *cipher = &pk11_des_ecb;
++ break;
++ case NID_aes_128_cbc:
++ *cipher = &pk11_aes_128_cbc;
++ break;
++ case NID_aes_192_cbc:
++ *cipher = &pk11_aes_192_cbc;
++ break;
++ case NID_aes_256_cbc:
++ *cipher = &pk11_aes_256_cbc;
++ break;
++ case NID_aes_128_ecb:
++ *cipher = &pk11_aes_128_ecb;
++ break;
++ case NID_aes_192_ecb:
++ *cipher = &pk11_aes_192_ecb;
++ break;
++ case NID_aes_256_ecb:
++ *cipher = &pk11_aes_256_ecb;
++ break;
++ case NID_bf_cbc:
++ *cipher = &pk11_bf_cbc;
++ break;
++ case NID_rc4:
++ *cipher = &pk11_rc4;
++ break;
++ default:
++#ifdef SOLARIS_AES_CTR
++ /*
++ * These can't be in separated cases because the NIDs
++ * here are not constants.
++ */
++ if (nid == NID_aes_128_ctr)
++ *cipher = &pk11_aes_128_ctr;
++ else if (nid == NID_aes_192_ctr)
++ *cipher = &pk11_aes_192_ctr;
++ else if (nid == NID_aes_256_ctr)
++ *cipher = &pk11_aes_256_ctr;
++ else
++#endif /* SOLARIS_AES_CTR */
++ *cipher = NULL;
++ break;
++ }
++ return (*cipher != NULL);
++ }
++
++/* ARGSUSED */
++static int
++pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid)
++ {
++ if (!digest)
++ return (pk11_usable_digests(nids));
++
++ switch (nid)
++ {
++ case NID_md5:
++ *digest = &pk11_md5;
++ break;
++ case NID_sha1:
++ *digest = &pk11_sha1;
++ break;
++ case NID_sha224:
++ *digest = &pk11_sha224;
++ break;
++ case NID_sha256:
++ *digest = &pk11_sha256;
++ break;
++ case NID_sha384:
++ *digest = &pk11_sha384;
++ break;
++ case NID_sha512:
++ *digest = &pk11_sha512;
++ break;
++ default:
++ *digest = NULL;
++ break;
++ }
++ return (*digest != NULL);
++ }
++
++
++/* Create a secret key object in a PKCS#11 session */
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY;
++ CK_ULONG ul_key_attr_count = 6;
++ unsigned char key_buf[PK11_KEY_LEN_MAX];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VALUE, (void*) NULL, 0},
++ };
++
++ /*
++ * Create secret key object in global_session. All other sessions
++ * can use the key handles. Here is why:
++ * OpenSSL will call EncryptInit and EncryptUpdate using a secret key.
++ * It may then call DecryptInit and DecryptUpdate using the same key.
++ * To use the same key object, we need to call EncryptFinal with
++ * a 0 length message. Currently, this does not work for 3DES
++ * mechanism. To get around this problem, we close the session and
++ * then create a new session to use the same key object. When a session
++ * is closed, all the object handles will be invalid. Thus, create key
++ * objects in a global session, an individual session may be closed to
++ * terminate the active operation.
++ */
++ CK_SESSION_HANDLE session = global_session;
++ a_key_template[0].pValue = &obj_key;
++ a_key_template[1].pValue = &key_type;
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ a_key_template[5].pValue = (void *) key;
++ }
++ else
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ memcpy(key_buf, key, ctx->key_len);
++ if ((key_type == CKK_DES) ||
++ (key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[0]);
++ if ((key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[8]);
++ if (key_type == CKK_DES3)
++ DES_fixup_key_parity((DES_cblock *) &key_buf[16]);
++ a_key_template[5].pValue = (void *) key_buf;
++ }
++ a_key_template[5].ulValueLen = (unsigned long) ctx->key_len;
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++
++ /*
++ * Save the key information used in this session.
++ * The max can be saved is PK11_KEY_LEN_MAX.
++ */
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ sp->opdata_key_len = PK11_KEY_LEN_MAX;
++ (void) memcpy(sp->opdata_key, key, sp->opdata_key_len);
++ }
++ else
++ {
++ sp->opdata_key_len = ctx->key_len;
++ (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len);
++ }
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++err:
++
++ return (h_key);
++ }
++
++static int
++md_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; i++)
++ if (digests[i].nid == nid)
++ return (digests[i].id);
++ return (-1);
++ }
++
++static int
++pk11_digest_init(EVP_MD_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_MECHANISM mech;
++ int index;
++ PK11_SESSION *sp;
++ PK11_DIGEST *pdp;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ state->sp = NULL;
++
++ index = md_nid_to_pk11(ctx->digest->type);
++ if (index < 0 || index >= PK11_DIGEST_MAX)
++ return (0);
++
++ pdp = &digests[index];
++ if ((sp = pk11_get_session(OP_DIGEST)) == NULL)
++ return (0);
++
++ /* at present, no parameter is needed for supported digests */
++ mech.mechanism = pdp->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ rv = pFuncList->C_DigestInit(sp->session, &mech);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv);
++ pk11_return_session(sp, OP_DIGEST);
++ return (0);
++ }
++
++ state->sp = sp;
++
++ return (1);
++ }
++
++static int
++pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
++ {
++ CK_RV rv;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ /* 0 length message will cause a failure in C_DigestFinal */
++ if (count == 0)
++ return (1);
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data,
++ count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ return (1);
++ }
++
++static int
++pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
++ {
++ CK_RV rv;
++ unsigned long len;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++ len = ctx->digest->md_size;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestFinal(state->sp->session, md, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ if (ctx->digest->md_size != len)
++ return (0);
++
++ /*
++ * Final is called and digest is returned, so return the session
++ * to the pool
++ */
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++
++ return (1);
++ }
++
++static int
++pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
++ {
++ CK_RV rv;
++ int ret = 0;
++ PK11_CIPHER_STATE *state, *state_to;
++ CK_BYTE_PTR pstate = NULL;
++ CK_ULONG ul_state_len;
++
++ /* The copy-from state */
++ state = (PK11_CIPHER_STATE *) from->md_data;
++ if (state == NULL || state->sp == NULL)
++ goto err;
++
++ /* Initialize the copy-to state */
++ if (!pk11_digest_init(to))
++ goto err;
++ state_to = (PK11_CIPHER_STATE *) to->md_data;
++
++ /* Get the size of the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, NULL,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++ if (ul_state_len == 0)
++ {
++ goto err;
++ }
++
++ pstate = OPENSSL_malloc(ul_state_len);
++ if (pstate == NULL)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, pstate,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++
++ /* Set the operation state of the copy-to session */
++ rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate,
++ ul_state_len, 0, 0);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY,
++ PK11_R_SET_OPERATION_STATE, rv);
++ goto err;
++ }
++
++ ret = 1;
++err:
++ if (pstate != NULL)
++ OPENSSL_free(pstate);
++
++ return (ret);
++ }
++
++/* Return any pending session state to the pool */
++static int
++pk11_digest_cleanup(EVP_MD_CTX *ctx)
++ {
++ PK11_CIPHER_STATE *state = ctx->md_data;
++ unsigned char buf[EVP_MAX_MD_SIZE];
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * If state->sp is not NULL then pk11_digest_final() has not
++ * been called yet. We must call it now to free any memory
++ * that might have been allocated in the token when
++ * pk11_digest_init() was called. pk11_digest_final()
++ * will return the session to the cache.
++ */
++ if (!pk11_digest_final(ctx, buf))
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * Check if the new key is the same as the key object in the session. If the key
++ * is the same, no need to create a new key object. Otherwise, the old key
++ * object needs to be destroyed and a new one will be created. Return 1 for
++ * cache hit, 0 for cache miss. Note that we must check the key length first
++ * otherwise we could end up reusing a different, longer key with the same
++ * prefix.
++ */
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len)
++ {
++ if (sp->opdata_key_len != key_len ||
++ memcmp(sp->opdata_key, key, key_len) != 0)
++ {
++ (void) pk11_destroy_cipher_key_objects(sp);
++ return (0);
++ }
++ return (1);
++ }
++
++/* Destroy one or more secret key objects. */
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_CIPHER].head;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE)
++ {
++ /*
++ * The secret key object is created in the
++ * global_session. See pk11_get_cipher_key().
++ */
++ if (pk11_destroy_object(global_session,
++ sp->opdata_cipher_key, CK_FALSE) == 0)
++ goto err;
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ }
++ }
++ ret = 1;
++err:
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_X_509
++ * CKM_RSA_PKCS
++ * CKM_DSA
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * Symmetric ciphers optionally supported
++ *
++ * CKM_DES3_CBC
++ * CKM_DES_CBC
++ * CKM_AES_CBC
++ * CKM_DES3_ECB
++ * CKM_DES_ECB
++ * CKM_AES_ECB
++ * CKM_AES_CTR
++ * CKM_RC4
++ * CKM_BLOWFISH_CBC
++ *
++ * Digests optionally supported
++ *
++ * CKM_MD5
++ * CKM_SHA_1
++ * CKM_SHA224
++ * CKM_SHA256
++ * CKM_SHA384
++ * CKM_SHA512
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ int slot_n_cipher = 0;
++ int slot_n_digest = 0;
++ CK_SLOT_ID current_slot = 0;
++ int current_slot_n_cipher = 0;
++ int current_slot_n_digest = 0;
++
++ int local_cipher_nids[PK11_CIPHER_MAX];
++ int local_digest_nids[PK11_DIGEST_MAX];
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ CK_BBOOL slot_has_recover = CK_FALSE;
++ CK_BBOOL slot_has_dsa = CK_FALSE;
++ CK_BBOOL slot_has_dh = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_RSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ /*
++ * Check if this slot is capable of encryption,
++ * decryption, sign, and verify with CKM_RSA_X_509.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_RSA_X_509, &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY) &&
++ (mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT)))
++ {
++ slot_has_rsa = CK_TRUE;
++ if (mech_info.flags & CKF_VERIFY_RECOVER)
++ {
++ slot_has_recover = CK_TRUE;
++ }
++ }
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_DSA.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
++ &mech_info);
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ slot_has_dsa = CK_TRUE;
++ }
++
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ /*
++ * Check if this slot is capable of DH key generataion and
++ * derivation.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
++
++ if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
++ {
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_DERIVE, &mech_info);
++ if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
++ {
++ slot_has_dh = CK_TRUE;
++ }
++ }
++#endif /* OPENSSL_NO_DH */
++
++ if (!found_candidate_slot &&
++ (slot_has_rsa || slot_has_dsa || slot_has_dh))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ pk11_have_recover = slot_has_recover;
++ pk11_have_dsa = slot_has_dsa;
++ pk11_have_dh = slot_has_dh;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa/dsa/dh\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ found_candidate_slot = CK_FALSE;
++ best_slot_sofar = 0;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ current_slot = pSlotList[i];
++ current_slot_n_cipher = 0;
++ current_slot_n_digest = 0;
++ (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
++ (void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
++
++ pk11_find_symmetric_ciphers(pFuncList, current_slot,
++ &current_slot_n_cipher, local_cipher_nids);
++
++ pk11_find_digests(pFuncList, current_slot,
++ &current_slot_n_digest, local_digest_nids);
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG,
++ current_slot_n_cipher);
++ fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG,
++ current_slot_n_digest);
++ fprintf(stderr, "%s: best so far cipher/digest slot: %d\n",
++ PK11_DBG, best_slot_sofar);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * If the current slot supports more ciphers/digests than
++ * the previous best one we change the current best to this one,
++ * otherwise leave it where it is.
++ */
++ if ((current_slot_n_cipher + current_slot_n_digest) >
++ (slot_n_cipher + slot_n_digest))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: changing best so far slot to %d\n",
++ PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = SLOTID = current_slot;
++ cipher_count = slot_n_cipher = current_slot_n_cipher;
++ digest_count = slot_n_digest = current_slot_n_digest;
++ (void) memcpy(cipher_nids, local_cipher_nids,
++ sizeof (local_cipher_nids));
++ (void) memcpy(digest_nids, local_digest_nids,
++ sizeof (local_digest_nids));
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover);
++ fprintf(stderr,
++ "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa);
++ fprintf(stderr,
++ "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++ fprintf(stderr,
++ "%s: cipher_count %d\n", PK11_DBG, cipher_count);
++ fprintf(stderr,
++ "%s: digest_count %d\n", PK11_DBG, digest_count);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ OPENSSL_free(hw_cnids);
++ OPENSSL_free(hw_dnids);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist,
++ int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher,
++ int *local_cipher_nids, int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if ((mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT))
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(ciphers[id].nid, hw_cnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_cipher_nids[(*current_slot_n_cipher)++] =
++ ciphers[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if (mech_info.flags & CKF_DIGEST)
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(digests[id].nid, hw_dnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_digest_nids[(*current_slot_n_digest)++] =
++ digests[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++#ifdef SOLARIS_AES_CTR
++/* create a new NID when we have no OID for that mechanism */
++static int pk11_add_NID(char *sn, char *ln)
++ {
++ ASN1_OBJECT *o;
++ int nid;
++
++ if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"",
++ 1, sn, ln)) == NULL)
++ {
++ return (0);
++ }
++
++ /* will return NID_undef on error */
++ nid = OBJ_add_object(o);
++ ASN1_OBJECT_free(o);
++
++ return (nid);
++ }
++
++/*
++ * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we
++ * have to help ourselves here.
++ */
++static int pk11_add_aes_ctr_NIDs(void)
++ {
++ /* are we already set? */
++ if (NID_aes_256_ctr != NID_undef)
++ return (1);
++
++ /*
++ * There are no official names for AES counter modes yet so we just
++ * follow the format of those that exist.
++ */
++ if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) ==
++ NID_undef)
++ goto err;
++ ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr;
++ if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) ==
++ NID_undef)
++ goto err;
++ ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr;
++ if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) ==
++ NID_undef)
++ goto err;
++ ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr;
++ return (1);
++
++err:
++ PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED);
++ return (0);
++ }
++#endif /* SOLARIS_AES_CTR */
++
++/* Find what symmetric ciphers this slot supports. */
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; ++i)
++ {
++ pk11_get_symmetric_cipher(pflist, current_slot,
++ ciphers[i].mech_type, current_slot_n_cipher,
++ local_cipher_nids, ciphers[i].id);
++ }
++ }
++
++/* Find what digest algorithms this slot supports. */
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; ++i)
++ {
++ pk11_get_digest(pflist, current_slot, digests[i].mech_type,
++ current_slot_n_digest, local_digest_nids, digests[i].id);
++ }
++ }
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * It would be great if we could use pkcs11_kernel directly since this library
++ * offers hardware slots only. That's the easiest way to achieve the situation
++ * where we use the hardware accelerators when present and OpenSSL native code
++ * otherwise. That presumes the fact that OpenSSL native code is faster than the
++ * code in the soft token. It's a logical assumption - Crypto Framework has some
++ * inherent overhead so going there for the software implementation of a
++ * mechanism should be logically slower in contrast to the OpenSSL native code,
++ * presuming that both implementations are of similar speed. For example, the
++ * soft token for AES is roughly three times slower than OpenSSL for 64 byte
++ * blocks and still 20% slower for 8KB blocks. So, if we want to ship products
++ * that use the PKCS#11 engine by default, we must somehow avoid that regression
++ * on machines without hardware acceleration. That's why switching to the
++ * pkcs11_kernel library seems like a very good idea.
++ *
++ * The problem is that OpenSSL built with SunStudio is roughly 2x slower for
++ * asymmetric operations (RSA/DSA/DH) than the soft token built with the same
++ * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11
++ * library, we would have had a performance regression on machines without
++ * hardware acceleration for asymmetric operations for all applications that use
++ * the PKCS#11 engine. There is one such application - Apache web server since
++ * it's shipped configured to use the PKCS#11 engine by default. Having said
++ * that, we can't switch to the pkcs11_kernel library now and have to come with
++ * a solution that, on non-accelerated machines, uses the OpenSSL native code
++ * for all symmetric ciphers and digests while it uses the soft token for
++ * asymmetric operations.
++ *
++ * This is the idea: dlopen() pkcs11_kernel directly and find out what
++ * mechanisms are there. We don't care about duplications (more slots can
++ * support the same mechanism), we just want to know what mechanisms can be
++ * possibly supported in hardware on that particular machine. As said before,
++ * pkcs11_kernel will show you hardware providers only.
++ *
++ * Then, we rely on the fact that since we use libpkcs11 library we will find
++ * the metaslot. When we go through the metaslot's mechanisms for symmetric
++ * ciphers and digests, we check that any found mechanism is in the table
++ * created using the pkcs11_kernel library. So, as a result we have two arrays
++ * of mechanisms that were advertised as supported in hardware which was the
++ * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token
++ * code for symmetric ciphers and digests. See pk11_choose_slots() for more
++ * information.
++ *
++ * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined
++ * the code won't be used.
++ */
++#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64)
++static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1";
++#else
++static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1";
++#endif
++
++/*
++ * Check hardware capabilities of the machines. The output are two lists,
++ * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware
++ * providers together. They are not sorted and may contain duplicate mechanisms.
++ */
++static int check_hw_mechanisms(void)
++ {
++ int i;
++ CK_RV rv;
++ void *handle;
++ CK_C_GetFunctionList p;
++ CK_TOKEN_INFO token_info;
++ CK_ULONG ulSlotCount = 0;
++ int n_cipher = 0, n_digest = 0;
++ CK_FUNCTION_LIST_PTR pflist = NULL;
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL;
++ int hw_ctable_size, hw_dtable_size;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n",
++ PK11_DBG);
++#endif
++ if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ if ((p = (CK_C_GetFunctionList)dlsym(handle,
++ PK11_GET_FUNCTION_LIST)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ if (p(&pflist) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /* no slots, set the hw mechanism tables as empty */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG);
++#endif
++ hw_cnids = OPENSSL_malloc(sizeof (int));
++ hw_dnids = OPENSSL_malloc(sizeof (int));
++ if (hw_cnids == NULL || hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ /* this means empty tables */
++ hw_cnids[0] = NID_undef;
++ hw_dnids[0] = NID_undef;
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the slot list for processing */
++ if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /*
++ * We don't care about duplicit mechanisms in multiple slots and also
++ * reserve one slot for the terminal NID_undef which we use to stop the
++ * search.
++ */
++ hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1;
++ hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1;
++ tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int));
++ tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int));
++ if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * Do not use memset since we should not rely on the fact that NID_undef
++ * is zero now.
++ */
++ for (i = 0; i < hw_ctable_size; ++i)
++ tmp_hw_cnids[i] = NID_undef;
++ for (i = 0; i < hw_dtable_size; ++i)
++ tmp_hw_dnids[i] = NID_undef;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel);
++ fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount);
++ fprintf(stderr, "%s: now looking for mechs supported in hw\n",
++ PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * We are filling the hw mech tables here. Global tables are
++ * still NULL so all mechanisms are put into tmp tables.
++ */
++ pk11_find_symmetric_ciphers(pflist, pSlotList[i],
++ &n_cipher, tmp_hw_cnids);
++ pk11_find_digests(pflist, pSlotList[i],
++ &n_digest, tmp_hw_dnids);
++ }
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects. Also, C_Finalize() is triggered by
++ * dlclose(3C).
++ */
++#if 0
++ pflist->C_Finalize(NULL);
++#endif
++ OPENSSL_free(pSlotList);
++ (void) dlclose(handle);
++ hw_cnids = tmp_hw_cnids;
++ hw_dnids = tmp_hw_dnids;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++
++err:
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++ if (tmp_hw_cnids != NULL)
++ OPENSSL_free(tmp_hw_cnids);
++ if (tmp_hw_dnids != NULL)
++ OPENSSL_free(tmp_hw_dnids);
++
++ return (0);
++ }
++
++/*
++ * Check presence of a NID in the table of NIDs. The table may be NULL (i.e.,
++ * non-existent).
++ */
++static int nid_in_table(int nid, int *nid_table)
++ {
++ int i = 0;
++
++ /*
++ * a special case. NULL means that we are initializing a new
++ * table.
++ */
++ if (nid_table == NULL)
++ return (1);
++
++ /*
++ * the table is never full, there is always at least one
++ * NID_undef.
++ */
++ while (nid_table[i] != NID_undef)
++ {
++ if (nid_table[i++] == nid)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++ }
++
++ return (0);
++ }
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11_err.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.4.10.1
+--- /dev/null Wed Dec 23 16:49:05 2015
++++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 21:52:40 2011
+@@ -0,0 +1,288 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_err.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <openssl/err.h>
++#include "hw_pk11_err.h"
++
++/* BEGIN ERROR CODES */
++#ifndef OPENSSL_NO_ERR
++static ERR_STRING_DATA pk11_str_functs[]=
++{
++{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"},
++{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"},
++{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"},
++{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"},
++{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"},
++{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"},
++{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"},
++{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"},
++{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"},
++{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"},
++{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"},
++{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"},
++{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"},
++{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"},
++{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"},
++{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"},
++{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"},
++{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"},
++{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"},
++{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"},
++{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"},
++{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"},
++{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"},
++{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"},
++{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"},
++{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"},
++{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"},
++{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"},
++{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"},
++{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"},
++{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"},
++{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"},
++{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"},
++{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"},
++{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"},
++{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"},
++{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"},
++{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"},
++{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"},
++{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"},
++{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"},
++{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"},
++{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"},
++{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"},
++{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"},
++{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"},
++{ 0, NULL}
++};
++
++static ERR_STRING_DATA pk11_str_reasons[]=
++{
++{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"},
++{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"},
++{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"},
++{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"},
++{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"},
++{ PK11_R_INITIALIZE, "C_Initialize failed"},
++{ PK11_R_FINALIZE, "C_Finalize failed"},
++{ PK11_R_GETINFO, "C_GetInfo faile"},
++{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"},
++{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"},
++{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"},
++{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"},
++{ PK11_R_NO_MODULUS, "no modulus"},
++{ PK11_R_NO_EXPONENT, "no exponent"},
++{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"},
++{ PK11_R_FINDOBJECTS, "C_FindObjects failed"},
++{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"},
++{ PK11_R_CREATEOBJECT, "C_CreateObject failed"},
++{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"},
++{ PK11_R_OPENSESSION, "C_OpenSession failed"},
++{ PK11_R_CLOSESESSION, "C_CloseSession failed"},
++{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"},
++{ PK11_R_ENCRYPT, "C_Encrypt failed"},
++{ PK11_R_SIGNINIT, "C_SignInit failed"},
++{ PK11_R_SIGN, "C_Sign failed"},
++{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"},
++{ PK11_R_DECRYPT, "C_Decrypt failed"},
++{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"},
++{ PK11_R_VERIFY, "C_Verify failed"},
++{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"},
++{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"},
++{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"},
++{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"},
++{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"},
++{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"},
++{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"},
++{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"},
++{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"},
++{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"},
++{ PK11_R_DIGEST_TOO_BIG, "digest too big"},
++{ PK11_R_MALLOC_FAILURE, "malloc failure"},
++{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"},
++{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"},
++{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"},
++{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"},
++{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"},
++{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"},
++{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"},
++{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"},
++{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"},
++{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"},
++{ PK11_R_DIGESTINIT, "C_DigestInit failed"},
++{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"},
++{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"},
++{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"},
++{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"},
++{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"},
++{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"},
++{ PK11_R_DERIVEKEY, "C_DeriveKey failed"},
++{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"},
++{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"},
++{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"},
++{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"},
++{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"},
++{ PK11_R_ADD_NID_FAILED, "failed to add NID" },
++{ PK11_R_ATFORK_FAILED, "atfork() failed" },
++{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" },
++{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" },
++{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" },
++{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" },
++{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" },
++{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" },
++{ PK11_R_PIPE_FAILED, "pipe() failed" },
++{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" },
++{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" },
++{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" },
++{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" },
++{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" },
++{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" },
++{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" },
++{ PK11_R_NO_OBJECT_FOUND, "specified object not found" },
++{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" },
++{ PK11_R_SYSCONF_FAILED, "sysconf() failed" },
++{ PK11_R_MMAP_FAILED, "mmap() failed" },
++{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" },
++{ PK11_R_MLOCK_FAILED, "mlock() failed" },
++{ PK11_R_FORK_FAILED, "fork() failed" },
++{ 0, NULL}
++};
++#endif /* OPENSSL_NO_ERR */
++
++static int pk11_lib_error_code = 0;
++static int pk11_error_init = 1;
++
++static void
++ERR_load_pk11_strings(void)
++ {
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++
++ if (pk11_error_init)
++ {
++ pk11_error_init = 0;
++#ifndef OPENSSL_NO_ERR
++ ERR_load_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_load_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ }
++}
++
++static void
++ERR_unload_pk11_strings(void)
++ {
++ if (pk11_error_init == 0)
++ {
++#ifndef OPENSSL_NO_ERR
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ pk11_error_init = 1;
++ }
++}
++
++void
++ERR_pk11_error(int function, int reason, char *file, int line)
++{
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++ ERR_PUT_error(pk11_lib_error_code, function, reason, file, line);
++}
++
++void
++PK11err_add_data(int function, int reason, CK_RV rv)
++{
++ char tmp_buf[20];
++
++ PK11err(function, reason);
++ (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++}
+Index: openssl/crypto/engine/hw_pk11_err.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.9.10.2
+--- /dev/null Wed Dec 23 16:49:05 2015
++++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:45:25 2013
+@@ -0,0 +1,440 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#ifndef HW_PK11_ERR_H
++#define HW_PK11_ERR_H
++
++void ERR_pk11_error(int function, int reason, char *file, int line);
++void PK11err_add_data(int function, int reason, CK_RV rv);
++#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__)
++
++/* Error codes for the PK11 functions. */
++
++/* Function codes. */
++
++#define PK11_F_INIT 100
++#define PK11_F_FINISH 101
++#define PK11_F_DESTROY 102
++#define PK11_F_CTRL 103
++#define PK11_F_RSA_INIT 104
++#define PK11_F_RSA_FINISH 105
++#define PK11_F_GET_PUB_RSA_KEY 106
++#define PK11_F_GET_PRIV_RSA_KEY 107
++#define PK11_F_RSA_GEN_KEY 108
++#define PK11_F_RSA_PUB_ENC 109
++#define PK11_F_RSA_PRIV_ENC 110
++#define PK11_F_RSA_PUB_DEC 111
++#define PK11_F_RSA_PRIV_DEC 112
++#define PK11_F_RSA_SIGN 113
++#define PK11_F_RSA_VERIFY 114
++#define PK11_F_RAND_ADD 115
++#define PK11_F_RAND_BYTES 116
++#define PK11_F_GET_SESSION 117
++#define PK11_F_FREE_SESSION 118
++#define PK11_F_LOAD_PUBKEY 119
++#define PK11_F_LOAD_PRIVKEY 120
++#define PK11_F_RSA_PUB_ENC_LOW 121
++#define PK11_F_RSA_PRIV_ENC_LOW 122
++#define PK11_F_RSA_PUB_DEC_LOW 123
++#define PK11_F_RSA_PRIV_DEC_LOW 124
++#define PK11_F_DSA_SIGN 125
++#define PK11_F_DSA_VERIFY 126
++#define PK11_F_DSA_INIT 127
++#define PK11_F_DSA_FINISH 128
++#define PK11_F_GET_PUB_DSA_KEY 129
++#define PK11_F_GET_PRIV_DSA_KEY 130
++#define PK11_F_DH_INIT 131
++#define PK11_F_DH_FINISH 132
++#define PK11_F_MOD_EXP_DH 133
++#define PK11_F_GET_DH_KEY 134
++#define PK11_F_FREE_ALL_SESSIONS 135
++#define PK11_F_SETUP_SESSION 136
++#define PK11_F_DESTROY_OBJECT 137
++#define PK11_F_CIPHER_INIT 138
++#define PK11_F_CIPHER_DO_CIPHER 139
++#define PK11_F_GET_CIPHER_KEY 140
++#define PK11_F_DIGEST_INIT 141
++#define PK11_F_DIGEST_UPDATE 142
++#define PK11_F_DIGEST_FINAL 143
++#define PK11_F_CHOOSE_SLOT 144
++#define PK11_F_CIPHER_FINAL 145
++#define PK11_F_LIBRARY_INIT 146
++#define PK11_F_LOAD 147
++#define PK11_F_DH_GEN_KEY 148
++#define PK11_F_DH_COMP_KEY 149
++#define PK11_F_DIGEST_COPY 150
++#define PK11_F_CIPHER_CLEANUP 151
++#define PK11_F_ACTIVE_ADD 152
++#define PK11_F_ACTIVE_DELETE 153
++#define PK11_F_CHECK_HW_MECHANISMS 154
++#define PK11_F_INIT_SYMMETRIC 155
++#define PK11_F_ADD_AES_CTR_NIDS 156
++#define PK11_F_INIT_ALL_LOCKS 157
++#define PK11_F_RETURN_SESSION 158
++#define PK11_F_GET_PIN 159
++#define PK11_F_FIND_ONE_OBJECT 160
++#define PK11_F_CHECK_TOKEN_ATTRS 161
++#define PK11_F_CACHE_PIN 162
++#define PK11_F_MLOCK_PIN_IN_MEMORY 163
++#define PK11_F_TOKEN_LOGIN 164
++#define PK11_F_TOKEN_RELOGIN 165
++#define PK11_F_RUN_ASKPASS 166
++
++/* Reason codes. */
++#define PK11_R_ALREADY_LOADED 100
++#define PK11_R_DSO_FAILURE 101
++#define PK11_R_NOT_LOADED 102
++#define PK11_R_PASSED_NULL_PARAMETER 103
++#define PK11_R_COMMAND_NOT_IMPLEMENTED 104
++#define PK11_R_INITIALIZE 105
++#define PK11_R_FINALIZE 106
++#define PK11_R_GETINFO 107
++#define PK11_R_GETSLOTLIST 108
++#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109
++#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110
++#define PK11_R_GETATTRIBUTVALUE 111
++#define PK11_R_NO_MODULUS 112
++#define PK11_R_NO_EXPONENT 113
++#define PK11_R_FINDOBJECTSINIT 114
++#define PK11_R_FINDOBJECTS 115
++#define PK11_R_FINDOBJECTSFINAL 116
++#define PK11_R_CREATEOBJECT 118
++#define PK11_R_DESTROYOBJECT 119
++#define PK11_R_OPENSESSION 120
++#define PK11_R_CLOSESESSION 121
++#define PK11_R_ENCRYPTINIT 122
++#define PK11_R_ENCRYPT 123
++#define PK11_R_SIGNINIT 124
++#define PK11_R_SIGN 125
++#define PK11_R_DECRYPTINIT 126
++#define PK11_R_DECRYPT 127
++#define PK11_R_VERIFYINIT 128
++#define PK11_R_VERIFY 129
++#define PK11_R_VERIFYRECOVERINIT 130
++#define PK11_R_VERIFYRECOVER 131
++#define PK11_R_GEN_KEY 132
++#define PK11_R_SEEDRANDOM 133
++#define PK11_R_GENERATERANDOM 134
++#define PK11_R_INVALID_MESSAGE_LENGTH 135
++#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136
++#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137
++#define PK11_R_UNKNOWN_PADDING_TYPE 138
++#define PK11_R_PADDING_CHECK_FAILED 139
++#define PK11_R_DIGEST_TOO_BIG 140
++#define PK11_R_MALLOC_FAILURE 141
++#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142
++#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143
++#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144
++#define PK11_R_MISSING_KEY_COMPONENT 145
++#define PK11_R_INVALID_SIGNATURE_LENGTH 146
++#define PK11_R_INVALID_DSA_SIGNATURE_R 147
++#define PK11_R_INVALID_DSA_SIGNATURE_S 148
++#define PK11_R_INCONSISTENT_KEY 149
++#define PK11_R_ENCRYPTUPDATE 150
++#define PK11_R_DECRYPTUPDATE 151
++#define PK11_R_DIGESTINIT 152
++#define PK11_R_DIGESTUPDATE 153
++#define PK11_R_DIGESTFINAL 154
++#define PK11_R_ENCRYPTFINAL 155
++#define PK11_R_DECRYPTFINAL 156
++#define PK11_R_NO_PRNG_SUPPORT 157
++#define PK11_R_GETTOKENINFO 158
++#define PK11_R_DERIVEKEY 159
++#define PK11_R_GET_OPERATION_STATE 160
++#define PK11_R_SET_OPERATION_STATE 161
++#define PK11_R_INVALID_HANDLE 162
++#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163
++#define PK11_R_INVALID_OPERATION_TYPE 164
++#define PK11_R_ADD_NID_FAILED 165
++#define PK11_R_ATFORK_FAILED 166
++
++#define PK11_R_TOKEN_LOGIN_FAILED 167
++#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168
++#define PK11_R_INVALID_PKCS11_URI 169
++#define PK11_R_COULD_NOT_READ_PIN 170
++#define PK11_R_COULD_NOT_OPEN_COMMAND 171
++#define PK11_R_PIPE_FAILED 172
++#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173
++#define PK11_R_BAD_PASSPHRASE_SPEC 174
++#define PK11_R_TOKEN_NOT_INITIALIZED 175
++#define PK11_R_TOKEN_PIN_NOT_SET 176
++#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177
++#define PK11_R_MISSING_OBJECT_LABEL 178
++#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179
++#define PK11_R_PRIV_KEY_NOT_FOUND 180
++#define PK11_R_NO_OBJECT_FOUND 181
++#define PK11_R_PIN_CACHING_POLICY_INVALID 182
++#define PK11_R_SYSCONF_FAILED 183
++#define PK11_R_MMAP_FAILED 183
++#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184
++#define PK11_R_MLOCK_FAILED 185
++#define PK11_R_FORK_FAILED 186
++
++/* max byte length of a symetric key we support */
++#define PK11_KEY_LEN_MAX 32
++
++#ifdef NOPTHREADS
++/*
++ * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the
++ * free_session list and active_list but generally serves as a global
++ * per-process lock for the whole engine.
++ *
++ * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as
++ * the global engine lock. This is not optimal w.r.t. performance but
++ * it's safe.
++ */
++#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC
++#endif
++
++/*
++ * This structure encapsulates all reusable information for a PKCS#11
++ * session. A list of these objects is created on behalf of the
++ * calling application using an on-demand method. Each operation
++ * type (see PK11_OPTYPE below) has its own per-process list.
++ * Each of the lists is basically a cache for faster PKCS#11 object
++ * access to avoid expensive C_Find{,Init,Final}Object() calls.
++ *
++ * When a new request comes in, an object will be taken from the list
++ * (if there is one) or a new one is created to handle the request
++ * (if the list is empty). See pk11_get_session() on how it is done.
++ */
++typedef struct PK11_st_SESSION
++ {
++ struct PK11_st_SESSION *next;
++ CK_SESSION_HANDLE session; /* PK11 session handle */
++ pid_t pid; /* Current process ID */
++ CK_BBOOL pub_persistent; /* is pub key in keystore? */
++ CK_BBOOL priv_persistent;/* is priv key in keystore? */
++ union
++ {
++#ifndef OPENSSL_NO_RSA
++ struct
++ {
++ CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */
++ RSA *rsa_pub; /* pub key addr */
++ BIGNUM *rsa_n_num; /* pub modulus */
++ BIGNUM *rsa_e_num; /* pub exponent */
++ RSA *rsa_priv; /* priv key addr */
++ BIGNUM *rsa_pn_num; /* pub modulus */
++ BIGNUM *rsa_pe_num; /* pub exponent */
++ BIGNUM *rsa_d_num; /* priv exponent */
++ } u_RSA;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ struct
++ {
++ CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */
++ DSA *dsa_pub; /* pub key addr */
++ BIGNUM *dsa_pub_num; /* pub key */
++ DSA *dsa_priv; /* priv key addr */
++ BIGNUM *dsa_priv_num; /* priv key */
++ } u_DSA;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ struct
++ {
++ CK_OBJECT_HANDLE dh_key; /* key handle */
++ DH *dh; /* dh key addr */
++ BIGNUM *dh_priv_num; /* priv dh key */
++ } u_DH;
++#endif /* OPENSSL_NO_DH */
++ struct
++ {
++ CK_OBJECT_HANDLE cipher_key; /* key handle */
++ unsigned char key[PK11_KEY_LEN_MAX];
++ int key_len; /* priv key len */
++ int encrypt; /* 1/0 enc/decr */
++ } u_cipher;
++ } opdata_u;
++ } PK11_SESSION;
++
++#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key
++#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key
++#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub
++#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv
++#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num
++#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num
++#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num
++#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num
++#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num
++#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key
++#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key
++#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub
++#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num
++#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv
++#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num
++#define opdata_dh_key opdata_u.u_DH.dh_key
++#define opdata_dh opdata_u.u_DH.dh
++#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num
++#define opdata_cipher_key opdata_u.u_cipher.cipher_key
++#define opdata_key opdata_u.u_cipher.key
++#define opdata_key_len opdata_u.u_cipher.key_len
++#define opdata_encrypt opdata_u.u_cipher.encrypt
++
++/*
++ * We have 3 different groups of operation types:
++ * 1) asymmetric operations
++ * 2) random operations
++ * 3) symmetric and digest operations
++ *
++ * This division into groups stems from the fact that it's common that hardware
++ * providers may support operations from one group only. For example, hardware
++ * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support
++ * only a single group of operations.
++ *
++ * For every group a different slot can be chosen. That means that we must have
++ * at least 3 different lists of cached PKCS#11 sessions since sessions from
++ * different groups may be initialized in different slots.
++ *
++ * To provide locking granularity in multithreaded environment, the groups are
++ * further splitted into types with each type having a separate session cache.
++ */
++typedef enum PK11_OPTYPE_ENUM
++ {
++ OP_RAND,
++ OP_RSA,
++ OP_DSA,
++ OP_DH,
++ OP_CIPHER,
++ OP_DIGEST,
++ OP_MAX
++ } PK11_OPTYPE;
++
++/*
++ * This structure contains the heads of the lists forming the object caches
++ * and locks associated with the lists.
++ */
++typedef struct PK11_st_CACHE
++ {
++ PK11_SESSION *head;
++#ifndef NOPTHREADS
++ pthread_mutex_t *lock;
++#endif
++ } PK11_CACHE;
++
++/* structure for tracking handles of asymmetric key objects */
++typedef struct PK11_active_st
++ {
++ CK_OBJECT_HANDLE h;
++ unsigned int refcnt;
++ struct PK11_active_st *prev;
++ struct PK11_active_st *next;
++ } PK11_active;
++
++#ifndef NOPTHREADS
++extern pthread_mutex_t *find_lock[];
++#endif
++extern PK11_active *active_list[];
++/*
++ * These variables are specific for the RSA keys by reference code. See
++ * hw_pk11_pub.c for explanation.
++ */
++extern CK_FLAGS pubkey_token_flags;
++
++#ifndef NOPTHREADS
++#define LOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0)
++#define UNLOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0)
++#else
++#define LOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE)
++#define UNLOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE)
++#endif
++
++extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++extern int pk11_token_relogin(CK_SESSION_HANDLE session);
++
++#ifndef OPENSSL_NO_RSA
++extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern RSA_METHOD *PK11_RSA(void);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DSA_METHOD *PK11_DSA(void);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++extern int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DH_METHOD *PK11_DH(void);
++#endif /* OPENSSL_NO_DH */
++
++extern CK_FUNCTION_LIST_PTR pFuncList;
++
++#endif /* HW_PK11_ERR_H */
+Index: openssl/crypto/engine/hw_pk11_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.32.4.7
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:45:25 2013
+@@ -0,0 +1,3556 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif /* OPENSSL_NO_DH */
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++#ifndef OPENSSL_NO_RSA
++/* RSA stuff */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_init(RSA *rsa);
++static int pk11_RSA_finish(RSA *rsa);
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#else
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#endif
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++#endif
++
++/* DSA stuff */
++#ifndef OPENSSL_NO_DSA
++static int pk11_DSA_init(DSA *dsa);
++static int pk11_DSA_finish(DSA *dsa);
++static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen,
++ DSA *dsa);
++static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len,
++ DSA_SIG *sig, DSA *dsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session);
++
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa);
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa);
++#endif
++
++/* DH stuff */
++#ifndef OPENSSL_NO_DH
++static int pk11_DH_init(DH *dh);
++static int pk11_DH_finish(DH *dh);
++static int pk11_DH_generate_key(DH *dh);
++static int pk11_DH_compute_key(unsigned char *key,
++ const BIGNUM *pub_key, DH *dh);
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr,
++ BIGNUM **priv_key, CK_SESSION_HANDLE session);
++
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh);
++#endif
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa =
++ {
++ "PKCS#11 RSA method",
++ pk11_RSA_public_encrypt, /* rsa_pub_encrypt */
++ pk11_RSA_public_decrypt, /* rsa_pub_decrypt */
++ pk11_RSA_private_encrypt, /* rsa_priv_encrypt */
++ pk11_RSA_private_decrypt, /* rsa_priv_decrypt */
++ NULL, /* rsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_RSA_init, /* init */
++ pk11_RSA_finish, /* finish */
++ RSA_FLAG_SIGN_VER, /* flags */
++ NULL, /* app_data */
++ pk11_RSA_sign, /* rsa_sign */
++ pk11_RSA_verify /* rsa_verify */
++ };
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ return (&pk11_rsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* Our internal DSA_METHOD that we provide pointers to */
++static DSA_METHOD pk11_dsa =
++ {
++ "PKCS#11 DSA method",
++ pk11_dsa_do_sign, /* dsa_do_sign */
++ NULL, /* dsa_sign_setup */
++ pk11_dsa_do_verify, /* dsa_do_verify */
++ NULL, /* dsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_DSA_init, /* init */
++ pk11_DSA_finish, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++ };
++
++DSA_METHOD *
++PK11_DSA(void)
++ {
++ return (&pk11_dsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DH
++/*
++ * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for
++ * output buffer may somewhat exceed the precise number of bytes needed, but
++ * should not exceed it by a large amount. That may be caused, for example, by
++ * rounding it up to multiple of X in the underlying bignum library. 8 should be
++ * enough.
++ */
++#define DH_BUF_RESERVE 8
++
++/* Our internal DH_METHOD that we provide pointers to */
++static DH_METHOD pk11_dh =
++ {
++ "PKCS#11 DH method",
++ pk11_DH_generate_key, /* generate_key */
++ pk11_DH_compute_key, /* compute_key */
++ NULL, /* bn_mod_exp */
++ pk11_DH_init, /* init */
++ pk11_DH_finish, /* finish */
++ 0, /* flags */
++ NULL, /* app_data */
++ NULL /* generate_params */
++ };
++
++DH_METHOD *
++PK11_DH(void)
++ {
++ return (&pk11_dh);
++ }
++#endif
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++/* Lengths of DSA data and signature */
++#define DSA_DATA_LEN 20
++#define DSA_SIGNATURE_LEN 40
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++#ifndef OPENSSL_NO_RSA
++/*
++ * Similiar to OpenSSL to take advantage of the paddings. The goal is to
++ * support all paddings in this engine although PK11 library does not
++ * support all the paddings used in OpenSSL.
++ * The input errors should have been checked in the padding functions.
++ */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ i = RSA_padding_add_SSLv23(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++
++/*
++ * Similar to Openssl to take advantage of the paddings. The input errors
++ * should be catched in the padding functions
++ */
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ case RSA_SSLV23_PADDING:
++ default:
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int j, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++
++ num = BN_num_bytes(rsa->n);
++
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ /* make data into a big number */
++ if (BN_bin2bn(from, (int)flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's paddings here.
++ */
++ for (j = 0; j < r; j++)
++ if (buf[j] != 0)
++ break;
++
++ p = buf + j;
++ j = r - j; /* j is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ r = RSA_padding_check_SSLv23(to, num, p, j, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, j, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int i, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++ num = BN_num_bytes(rsa->n);
++ buf = (unsigned char *)OPENSSL_malloc(num);
++ if (buf == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ if (BN_bin2bn(from, flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's here
++ */
++ for (i = 0; i < r; i++)
++ if (buf[i] != 0)
++ break;
++
++ p = buf + i;
++ i = r - i; /* i is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, i, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/*
++ * This function implements RSA public encryption using C_EncryptInit and
++ * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_encrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_EncryptInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Encrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_encrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_encrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private encryption using C_SignInit and
++ * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG ul_sig_len = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ {
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW,
++ PK11_R_SIGNINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char *)from, flen, to, &ul_sig_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN,
++ rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ retval = ul_sig_len;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private decryption using C_DecryptInit and
++ * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DecryptInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Decrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA public decryption using C_VerifyRecoverInit
++ * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyRecoverInit(sp->session,
++ p_mech, h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVERINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_VerifyRecover(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVER, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++static int pk11_RSA_init(RSA *rsa)
++ {
++ /*
++ * This flag in the RSA_METHOD enables the new rsa_sign,
++ * rsa_verify functions. See rsa.h for details.
++ */
++ rsa->flags |= RSA_FLAG_SIGN_VER;
++
++ return (1);
++ }
++
++static int pk11_RSA_finish(RSA *rsa)
++ {
++ /*
++ * Since we are overloading OpenSSL's native RSA_eay_finish() we need
++ * to do the same as in the original function, i.e. to free bignum
++ * structures.
++ */
++ if (rsa->_method_mod_n != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_n);
++ if (rsa->_method_mod_p != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_p);
++ if (rsa->_method_mod_q != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_q);
++
++ return (1);
++ }
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#else
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#endif
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto err;
++ }
++ rv = pFuncList->C_Verify(sp->session, s, i,
++ (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* The DSA function implementation */
++/* ARGSUSED */
++static int pk11_DSA_init(DSA *dsa)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DSA_finish(DSA *dsa)
++ {
++ return (1);
++ }
++
++
++static DSA_SIG *
++pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
++ {
++ BIGNUM *r = NULL, *s = NULL;
++ int i;
++ DSA_SIG *dsa_sig = NULL;
++
++ CK_RV rv;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_priv_key;
++
++ /*
++ * The signature is the concatenation of r and s,
++ * each is 20 bytes long
++ */
++ unsigned char sigret[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned int siglen2 = DSA_SIGNATURE_LEN / 2;
++
++ PK11_SESSION *sp = NULL;
++
++ if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_priv(sp, dsa);
++
++ h_priv_key = sp->opdata_dsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_dsa_priv_key =
++ pk11_get_private_dsa_key((DSA *)dsa,
++ &sp->opdata_dsa_priv,
++ &sp->opdata_dsa_priv_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto ret;
++ }
++
++ (void) memset(sigret, 0, siglen);
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char*) dgst, dlen, sigret,
++ (CK_ULONG_PTR) &siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv);
++ goto ret;
++ }
++ }
++
++
++ if ((s = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((r = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((dsa_sig = DSA_SIG_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if (BN_bin2bn(sigret, siglen2, r) == NULL ||
++ BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ dsa_sig->r = r;
++ dsa_sig->s = s;
++
++ret:
++ if (dsa_sig == NULL)
++ {
++ if (r != NULL)
++ BN_free(r);
++ if (s != NULL)
++ BN_free(s);
++ }
++
++ pk11_return_session(sp, OP_DSA);
++ return (dsa_sig);
++ }
++
++static int
++pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig,
++ DSA *dsa)
++ {
++ int i;
++ CK_RV rv;
++ int retval = 0;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_pub_key;
++
++ unsigned char sigbuf[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned long siglen2 = DSA_SIGNATURE_LEN/2;
++
++ PK11_SESSION *sp = NULL;
++
++ if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_R);
++ goto ret;
++ }
++
++ if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_S);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_pub(sp, dsa);
++
++ h_pub_key = sp->opdata_dsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_dsa_pub_key =
++ pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub,
++ &sp->opdata_dsa_pub_num, sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto ret;
++ }
++
++ /*
++ * The representation of each of the two big numbers could
++ * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need
++ * to act accordingly and shift if necessary.
++ */
++ (void) memset(sigbuf, 0, siglen);
++ BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r));
++ BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 -
++ BN_num_bytes(sig->s));
++
++ rv = pFuncList->C_Verify(sp->session,
++ (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv);
++ goto ret;
++ }
++ }
++
++ retval = 1;
++ret:
++
++ pk11_return_session(sp, OP_DSA);
++ return (retval);
++ }
++
++
++/*
++ * Create a public key object in a session from a given dsa structure.
++ * The *dsa_pub_num pointer is non-NULL for DSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ if (init_template_value(dsa->p, &a_key_template[4].pValue,
++ &a_key_template[4].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->pub_key, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_pub_num != NULL)
++ if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ for (i = 4; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given dsa structure
++ * The *dsa_priv_num pointer is non-NULL for DSA private keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ int i;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 9;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(dsa->p, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(dsa->priv_key, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_priv_num != NULL)
++ if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ /*
++ * 5 to 8 entries in the key template are key components.
++ * They need to be freed apon exit or error.
++ */
++ for (i = 5; i <= 8; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only public key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_pub != dsa) ||
++ (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only private key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_priv != dsa) ||
++ (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++
++#ifndef OPENSSL_NO_DH
++/* The DH function implementation */
++/* ARGSUSED */
++static int pk11_DH_init(DH *dh)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DH_finish(DH *dh)
++ {
++ return (1);
++ }
++
++/*
++ * Generate DH key-pair.
++ *
++ * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key
++ * and override it even if it is set. OpenSSL does not touch dh->priv_key
++ * if set and just computes dh->pub_key. It looks like PKCS#11 standard
++ * is not capable of providing this functionality. This could be a problem
++ * for applications relying on OpenSSL's semantics.
++ */
++static int pk11_DH_generate_key(DH *dh)
++ {
++ CK_ULONG i;
++ CK_RV rv, rv1;
++ int reuse_mem_len = 0, ret = 0;
++ PK11_SESSION *sp = NULL;
++ CK_BYTE_PTR reuse_mem;
++
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++
++ CK_ULONG ul_pub_key_attr_count = 3;
++ CK_ATTRIBUTE pub_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *)NULL, 0},
++ {CKA_BASE, (void *)NULL, 0}
++ };
++
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)}
++ };
++
++ CK_ULONG pub_key_attr_result_count = 1;
++ CK_ATTRIBUTE pub_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ pub_key_template[1].ulValueLen = BN_num_bytes(dh->p);
++ if (pub_key_template[1].ulValueLen > 0)
++ {
++ /*
++ * We must not increase ulValueLen by DH_BUF_RESERVE since that
++ * could cause the same rounding problem. See definition of
++ * DH_BUF_RESERVE above.
++ */
++ pub_key_template[1].pValue =
++ OPENSSL_malloc(pub_key_template[1].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[1].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->p, pub_key_template[1].pValue);
++ }
++ else
++ goto err;
++
++ pub_key_template[2].ulValueLen = BN_num_bytes(dh->g);
++ if (pub_key_template[2].ulValueLen > 0)
++ {
++ pub_key_template[2].pValue =
++ OPENSSL_malloc(pub_key_template[2].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[2].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->g, pub_key_template[2].pValue);
++ }
++ else
++ goto err;
++
++ /*
++ * Note: we are only using PK11_SESSION structure for getting
++ * a session handle. The objects created in this function are
++ * destroyed before return and thus not cached.
++ */
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ rv = pFuncList->C_GenerateKeyPair(sp->session,
++ &mechanism,
++ pub_key_template,
++ ul_pub_key_attr_count,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_pub_key,
++ &h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv);
++ goto err;
++ }
++
++ /*
++ * Reuse the larger memory allocated. We know the larger memory
++ * should be sufficient for reuse.
++ */
++ if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen)
++ {
++ reuse_mem = pub_key_template[1].pValue;
++ reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE;
++ }
++ else
++ {
++ reuse_mem = pub_key_template[2].pValue;
++ reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++ rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK || rv1 != CKR_OK)
++ {
++ rv = (rv != CKR_OK) ? rv : rv1;
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 ||
++ ((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++
++ /* Reuse the memory allocated */
++ pub_key_result[0].pValue = reuse_mem;
++ pub_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (pub_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->pub_key == NULL)
++ if ((dh->pub_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->pub_key = BN_bin2bn(pub_key_result[0].pValue,
++ pub_key_result[0].ulValueLen, dh->pub_key);
++ if (dh->pub_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ /* Reuse the memory allocated */
++ priv_key_result[0].pValue = reuse_mem;
++ priv_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->priv_key == NULL)
++ if ((dh->priv_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->priv_key = BN_bin2bn(priv_key_result[0].pValue,
++ priv_key_result[0].ulValueLen, dh->priv_key);
++ if (dh->priv_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ ret = 1;
++
++err:
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_pub_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ for (i = 1; i <= 2; i++)
++ {
++ if (pub_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(pub_key_template[i].pValue);
++ pub_key_template[i].pValue = NULL;
++ }
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key,
++ DH *dh)
++ {
++ unsigned int i;
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0};
++ CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
++ CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
++ CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++
++ CK_ULONG seclen;
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (key_class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_VALUE_LEN, &seclen, sizeof (seclen)},
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_RV rv;
++ int ret = -1;
++ PK11_SESSION *sp = NULL;
++
++ if (dh->priv_key == NULL)
++ goto err;
++
++ priv_key_template[0].pValue = &key_class;
++ priv_key_template[1].pValue = &key_type;
++ seclen = BN_num_bytes(dh->p);
++
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ mechanism.ulParameterLen = BN_num_bytes(pub_key);
++ mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen);
++ if (mechanism.pParameter == NULL)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ BN_bn2bin(pub_key, mechanism.pParameter);
++
++ (void) check_new_dh_key(sp, dh);
++
++ h_key = sp->opdata_dh_key;
++ if (h_key == CK_INVALID_HANDLE)
++ h_key = sp->opdata_dh_key =
++ pk11_get_dh_key((DH*) dh, &sp->opdata_dh,
++ &sp->opdata_dh_priv_num, sp->session);
++
++ if (h_key == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT);
++ goto err;
++ }
++
++ rv = pFuncList->C_DeriveKey(sp->session,
++ &mechanism,
++ h_key,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++ priv_key_result[0].pValue =
++ OPENSSL_malloc(priv_key_result[0].ulValueLen);
++ if (!priv_key_result[0].pValue)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ /*
++ * OpenSSL allocates the output buffer 'key' which is the same
++ * length of the public key. It is long enough for the derived key
++ */
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ /*
++ * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip
++ * leading zeros from a computed shared secret. However,
++ * OpenSSL always did it so we must do the same here. The
++ * vagueness of the spec regarding leading zero bytes was
++ * finally cleared with TLS 1.1 (RFC 4346) saying that leading
++ * zeros are stripped before the computed data is used as the
++ * pre-master secret.
++ */
++ for (i = 0; i < priv_key_result[0].ulValueLen; ++i)
++ {
++ if (((char *)priv_key_result[0].pValue)[i] != 0)
++ break;
++ }
++
++ (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i,
++ priv_key_result[0].ulValueLen - i);
++ ret = priv_key_result[0].ulValueLen - i;
++ }
++
++err:
++
++ if (h_derived_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++ if (priv_key_result[0].pValue)
++ {
++ OPENSSL_free(priv_key_result[0].pValue);
++ priv_key_result[0].pValue = NULL;
++ }
++
++ if (mechanism.pParameter)
++ {
++ OPENSSL_free(mechanism.pParameter);
++ mechanism.pParameter = NULL;
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh,
++ DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE key_type = CKK_DH;
++ CK_ULONG found;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ULONG ul_key_attr_count = 7;
++ CK_ATTRIBUTE key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)},
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *) NULL, 0},
++ {CKA_BASE, (void *) NULL, 0},
++ {CKA_VALUE, (void *) NULL, 0},
++ };
++
++ key_template[0].pValue = &class;
++ key_template[1].pValue = &key_type;
++
++ key_template[4].ulValueLen = BN_num_bytes(dh->p);
++ key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[4].ulValueLen);
++ if (key_template[4].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->p, key_template[4].pValue);
++
++ key_template[5].ulValueLen = BN_num_bytes(dh->g);
++ key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[5].ulValueLen);
++ if (key_template[5].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->g, key_template[5].pValue);
++
++ key_template[6].ulValueLen = BN_num_bytes(dh->priv_key);
++ key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[6].ulValueLen);
++ if (key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->priv_key, key_template[6].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DH);
++ rv = pFuncList->C_FindObjectsInit(session, key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL,
++ rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++ }
++
++ if (dh_priv_num != NULL)
++ if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dh;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DH);
++
++malloc_err:
++ for (i = 4; i <= 6; i++)
++ {
++ if (key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(key_template[i].pValue);
++ key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ *
++ * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh
++ * to CK_INVALID_HANDLE even when it fails to destroy the object.
++ */
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh)
++ {
++ /*
++ * Provide protection against DH structure reuse by making the
++ * check for cache hit stronger. Private key component of DH key
++ * is unique so it is sufficient to compare it with value cached
++ * in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dh != dh) ||
++ (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dh_object(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11ca.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.2.4.2
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:32 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */
++
++#define token_lock pk11ca_token_lock
++#define find_lock pk11ca_find_lock
++#define active_list pk11ca_active_list
++#define pubkey_token_flags pk11ca_pubkey_token_flags
++#define pubkey_SLOTID pk11ca_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11ca_error
++#define PK11err_add_data PK11CAerr_add_data
++#define pk11_get_session pk11ca_get_session
++#define pk11_return_session pk11ca_return_session
++#define pk11_active_add pk11ca_active_add
++#define pk11_active_delete pk11ca_active_delete
++#define pk11_active_remove pk11ca_active_remove
++#define pk11_free_active_list pk11ca_free_active_list
++#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv
++#define pk11_load_privkey pk11ca_load_privkey
++#define pk11_load_pubkey pk11ca_load_pubkey
++#define PK11_RSA PK11CA_RSA
++#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv
++#define PK11_DSA PK11CA_DSA
++#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11ca_destroy_dh_object
++#define PK11_DH PK11CA_DH
++#define pk11_token_relogin pk11ca_token_relogin
++#define pFuncList pk11ca_pFuncList
++#define pk11_pin pk11ca_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11ca
+Index: openssl/crypto/engine/hw_pk11so.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.3.4.3
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:45:25 2013
+@@ -0,0 +1,1775 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/*#undef DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_DSA
++#define OPENSSL_NO_DSA
++#endif
++#ifndef OPENSSL_NO_DH
++#define OPENSSL_NO_DH
++#endif
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.c"
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++static int pk11_choose_slots(int *any_slot_found);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11CA
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name = "PKCS #11 engine support (sign only)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name))
++ return (0);
++
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++ (void) pk11_destroy_rsa_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ if (optype == OP_RSA)
++ {
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_PKCS
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ CK_SLOT_ID current_slot = 0;
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * Check if this slot is capable of signing with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN)))
++ {
++ slot_has_rsa = CK_TRUE;
++ }
++
++ if (!found_candidate_slot && slot_has_rsa)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ /*SLOTID = pSlotList[0];*/
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11so.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.2.4.2
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:32 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */
++
++#define token_lock pk11so_token_lock
++#define find_lock pk11so_find_lock
++#define active_list pk11so_active_list
++#define pubkey_token_flags pk11so_pubkey_token_flags
++#define pubkey_SLOTID pk11so_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11so_error
++#define PK11err_add_data PK11SOerr_add_data
++#define pk11_get_session pk11so_get_session
++#define pk11_return_session pk11so_return_session
++#define pk11_active_add pk11so_active_add
++#define pk11_active_delete pk11so_active_delete
++#define pk11_active_remove pk11so_active_remove
++#define pk11_free_active_list pk11so_free_active_list
++#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv
++#define pk11_load_privkey pk11so_load_privkey
++#define pk11_load_pubkey pk11so_load_pubkey
++#define PK11_RSA PK11SO_RSA
++#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv
++#define PK11_DSA PK11SO_DSA
++#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11so_destroy_dh_object
++#define PK11_DH PK11SO_DH
++#define pk11_token_relogin pk11so_token_relogin
++#define pFuncList pk11so_pFuncList
++#define pk11_pin pk11so_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11so
+Index: openssl/crypto/engine/hw_pk11so_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.2.4.6
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:45:25 2013
+@@ -0,0 +1,1642 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++/* RSA stuff */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa;
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ const RSA_METHOD *rsa;
++
++ if (pk11_rsa.name == NULL)
++ {
++ rsa = RSA_PKCS1_SSLeay();
++ memcpy(&pk11_rsa, rsa, sizeof(*rsa));
++ pk11_rsa.name = "PKCS#11 RSA method";
++ pk11_rsa.rsa_sign = pk11_RSA_sign;
++ }
++ return (&pk11_rsa);
++ }
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/pkcs11.h
+diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,299 @@
++/* pkcs11.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++#ifndef _PKCS11_H_
++#define _PKCS11_H_ 1
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Before including this file (pkcs11.h) (or pkcs11t.h by
++ * itself), 6 platform-specific macros must be defined. These
++ * macros are described below, and typical definitions for them
++ * are also given. Be advised that these definitions can depend
++ * on both the platform and the compiler used (and possibly also
++ * on whether a Cryptoki library is linked statically or
++ * dynamically).
++ *
++ * In addition to defining these 6 macros, the packing convention
++ * for Cryptoki structures should be set. The Cryptoki
++ * convention on packing is that structures should be 1-byte
++ * aligned.
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, this might be done by using the following
++ * preprocessor directive before including pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(push, cryptoki, 1)
++ *
++ * and using the following preprocessor directive after including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(pop, cryptoki)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, this might be done by using
++ * the following preprocessor directive before including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(1)
++ *
++ * In a UNIX environment, you're on your own for this. You might
++ * not need to do (or be able to do!) anything.
++ *
++ *
++ * Now for the macros:
++ *
++ *
++ * 1. CK_PTR: The indirection string for making a pointer to an
++ * object. It can be used like this:
++ *
++ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, it might be defined by:
++ *
++ * #define CK_PTR far *
++ *
++ * In a typical UNIX environment, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ *
++ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
++ * an exportable Cryptoki library function definition out of a
++ * return type and a function name. It should be used in the
++ * following fashion to define the exposed Cryptoki functions in
++ * a Cryptoki library:
++ *
++ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * )
++ * {
++ * ...
++ * }
++ *
++ * If you're using Microsoft Developer Studio 5.0 to define a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllexport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to define a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
++ * an importable Cryptoki library function declaration out of a
++ * return type and a function name. It should be used in the
++ * following fashion:
++ *
++ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * );
++ *
++ * If you're using Microsoft Developer Studio 5.0 to declare a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllimport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to declare a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
++ * which makes a Cryptoki API function pointer declaration or
++ * function pointer type declaration out of a return type and a
++ * function name. It should be used in the following fashion:
++ *
++ * // Define funcPtr to be a pointer to a Cryptoki API function
++ * // taking arguments args and returning CK_RV.
++ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
++ *
++ * or
++ *
++ * // Define funcPtrType to be the type of a pointer to a
++ * // Cryptoki API function taking arguments args and returning
++ * // CK_RV, and then define funcPtr to be a variable of type
++ * // funcPtrType.
++ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
++ * funcPtrType funcPtr;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to access
++ * functions in a Win32 Cryptoki .dll, in might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __declspec(dllimport) (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to access functions in a Win16 Cryptoki .dll, it might
++ * be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __export _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
++ * a function pointer type for an application callback out of
++ * a return type for the callback and a name for the callback.
++ * It should be used in the following fashion:
++ *
++ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
++ *
++ * to declare a function pointer, myCallback, to a callback
++ * which takes arguments args and returns a CK_RV. It can also
++ * be used like this:
++ *
++ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
++ * myCallbackType myCallback;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to do Win32
++ * Cryptoki development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to do Win16 development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 6. NULL_PTR: This macro is the value of a NULL pointer.
++ *
++ * In any ANSI/ISO C environment (and in many others as well),
++ * this should best be defined by
++ *
++ * #ifndef NULL_PTR
++ * #define NULL_PTR 0
++ * #endif
++ */
++
++
++/* All the various Cryptoki types and #define'd values are in the
++ * file pkcs11t.h. */
++#include "pkcs11t.h"
++
++#define __PASTE(x,y) x##y
++
++
++/* ==============================================================
++ * Define the "extern" form of all the entry points.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ extern CK_DECLARE_FUNCTION(CK_RV, name)
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define the typedef form of all the entry points. That is, for
++ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
++ * a pointer to that kind of function.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define structed vector of entry points. A CK_FUNCTION_LIST
++ * contains a CK_VERSION indicating a library's Cryptoki version
++ * and then a whole slew of function pointers to the routines in
++ * the library. This type was declared, but not defined, in
++ * pkcs11t.h.
++ * ==============================================================
++ */
++
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ __PASTE(CK_,name) name;
++
++struct CK_FUNCTION_LIST {
++
++ CK_VERSION version; /* Cryptoki version */
++
++/* Pile all the function pointers into the CK_FUNCTION_LIST. */
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++};
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++#undef __PASTE
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+Index: openssl/crypto/engine/pkcs11f.h
+diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,912 @@
++/* pkcs11f.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This header file contains pretty much everything about all the */
++/* Cryptoki function prototypes. Because this information is */
++/* used for more than just declaring function prototypes, the */
++/* order of the functions appearing herein is important, and */
++/* should not be altered. */
++
++/* General-purpose */
++
++/* C_Initialize initializes the Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Initialize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
++ * cast to CK_C_INITIALIZE_ARGS_PTR
++ * and dereferenced */
++);
++#endif
++
++
++/* C_Finalize indicates that an application is done with the
++ * Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Finalize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
++);
++#endif
++
++
++/* C_GetInfo returns general information about Cryptoki. */
++CK_PKCS11_FUNCTION_INFO(C_GetInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_INFO_PTR pInfo /* location that receives information */
++);
++#endif
++
++
++/* C_GetFunctionList returns the function list. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
++ * function list */
++);
++#endif
++
++
++
++/* Slot and token management */
++
++/* C_GetSlotList obtains a list of slots in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_BBOOL tokenPresent, /* only slots with tokens? */
++ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
++ CK_ULONG_PTR pulCount /* receives number of slots */
++);
++#endif
++
++
++/* C_GetSlotInfo obtains information about a particular slot in
++ * the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the ID of the slot */
++ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
++);
++#endif
++
++
++/* C_GetTokenInfo obtains information about a particular token
++ * in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
++);
++#endif
++
++
++/* C_GetMechanismList obtains a list of mechanism types
++ * supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of token's slot */
++ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
++ CK_ULONG_PTR pulCount /* gets # of mechs. */
++);
++#endif
++
++
++/* C_GetMechanismInfo obtains information about a particular
++ * mechanism possibly supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_MECHANISM_TYPE type, /* type of mechanism */
++ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
++);
++#endif
++
++
++/* C_InitToken initializes a token. */
++CK_PKCS11_FUNCTION_INFO(C_InitToken)
++#ifdef CK_NEED_ARG_LIST
++/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
++ CK_ULONG ulPinLen, /* length in bytes of the PIN */
++ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
++);
++#endif
++
++
++/* C_InitPIN initializes the normal user's PIN. */
++CK_PKCS11_FUNCTION_INFO(C_InitPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
++ CK_ULONG ulPinLen /* length in bytes of the PIN */
++);
++#endif
++
++
++/* C_SetPIN modifies the PIN of the user who is logged in. */
++CK_PKCS11_FUNCTION_INFO(C_SetPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
++ CK_ULONG ulOldLen, /* length of the old PIN */
++ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
++ CK_ULONG ulNewLen /* length of the new PIN */
++);
++#endif
++
++
++
++/* Session management */
++
++/* C_OpenSession opens a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_OpenSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the slot's ID */
++ CK_FLAGS flags, /* from CK_SESSION_INFO */
++ CK_VOID_PTR pApplication, /* passed to callback */
++ CK_NOTIFY Notify, /* callback function */
++ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
++);
++#endif
++
++
++/* C_CloseSession closes a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CloseAllSessions closes all sessions with a token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID /* the token's slot */
++);
++#endif
++
++
++/* C_GetSessionInfo obtains information about the session. */
++CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_SESSION_INFO_PTR pInfo /* receives session info */
++);
++#endif
++
++
++/* C_GetOperationState obtains the state of the cryptographic operation
++ * in a session. */
++CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* gets state */
++ CK_ULONG_PTR pulOperationStateLen /* gets state length */
++);
++#endif
++
++
++/* C_SetOperationState restores the state of the cryptographic
++ * operation in a session. */
++CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* holds state */
++ CK_ULONG ulOperationStateLen, /* holds state length */
++ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
++ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
++);
++#endif
++
++
++/* C_Login logs a user into a token. */
++CK_PKCS11_FUNCTION_INFO(C_Login)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_USER_TYPE userType, /* the user type */
++ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
++ CK_ULONG ulPinLen /* the length of the PIN */
++);
++#endif
++
++
++/* C_Logout logs a user out from a token. */
++CK_PKCS11_FUNCTION_INFO(C_Logout)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Object management */
++
++/* C_CreateObject creates a new object. */
++CK_PKCS11_FUNCTION_INFO(C_CreateObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
++);
++#endif
++
++
++/* C_CopyObject copies an object, creating a new object for the
++ * copy. */
++CK_PKCS11_FUNCTION_INFO(C_CopyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
++);
++#endif
++
++
++/* C_DestroyObject destroys an object. */
++CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject /* the object's handle */
++);
++#endif
++
++
++/* C_GetObjectSize gets the size of an object in bytes. */
++CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ULONG_PTR pulSize /* receives size of object */
++);
++#endif
++
++
++/* C_GetAttributeValue obtains the value of one or more object
++ * attributes. */
++CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_SetAttributeValue modifies the value of one or more object
++ * attributes */
++CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_FindObjectsInit initializes a search for token and session
++ * objects that match a template. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
++ CK_ULONG ulCount /* attrs in search template */
++);
++#endif
++
++
++/* C_FindObjects continues a search for token and session
++ * objects that match a template, obtaining additional object
++ * handles. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjects)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
++ CK_ULONG ulMaxObjectCount, /* max handles to get */
++ CK_ULONG_PTR pulObjectCount /* actual # returned */
++);
++#endif
++
++
++/* C_FindObjectsFinal finishes a search for token and session
++ * objects. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Encryption and decryption */
++
++/* C_EncryptInit initializes an encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of encryption key */
++);
++#endif
++
++
++/* C_Encrypt encrypts single-part data. */
++CK_PKCS11_FUNCTION_INFO(C_Encrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pData, /* the plaintext data */
++ CK_ULONG ulDataLen, /* bytes of plaintext */
++ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptUpdate continues a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext data len */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptFinal finishes a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session handle */
++ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
++ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
++);
++#endif
++
++
++/* C_DecryptInit initializes a decryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of decryption key */
++);
++#endif
++
++
++/* C_Decrypt decrypts encrypted data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Decrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedData, /* ciphertext */
++ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
++ CK_BYTE_PTR pData, /* gets plaintext */
++ CK_ULONG_PTR pulDataLen /* gets p-text size */
++);
++#endif
++
++
++/* C_DecryptUpdate continues a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
++ CK_ULONG ulEncryptedPartLen, /* input length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* p-text size */
++);
++#endif
++
++
++/* C_DecryptFinal finishes a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pLastPart, /* gets plaintext */
++ CK_ULONG_PTR pulLastPartLen /* p-text size */
++);
++#endif
++
++
++
++/* Message digesting */
++
++/* C_DigestInit initializes a message-digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
++);
++#endif
++
++
++/* C_Digest digests data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Digest)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* data to be digested */
++ CK_ULONG ulDataLen, /* bytes of data to digest */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets digest length */
++);
++#endif
++
++
++/* C_DigestUpdate continues a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* data to be digested */
++ CK_ULONG ulPartLen /* bytes of data to be digested */
++);
++#endif
++
++
++/* C_DigestKey continues a multi-part message-digesting
++ * operation, by digesting the value of a secret key as part of
++ * the data already digested. */
++CK_PKCS11_FUNCTION_INFO(C_DigestKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hKey /* secret key to digest */
++);
++#endif
++
++
++/* C_DigestFinal finishes a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
++);
++#endif
++
++
++
++/* Signing and MACing */
++
++/* C_SignInit initializes a signature (private key encryption)
++ * operation, where the signature is (will be) an appendix to
++ * the data, and plaintext cannot be recovered from the
++ *signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of signature key */
++);
++#endif
++
++
++/* C_Sign signs (encrypts with private key) data in a single
++ * part, where the signature is (will be) an appendix to the
++ * data, and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Sign)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignUpdate continues a multiple-part signature operation,
++ * where the signature is (will be) an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* the data to sign */
++ CK_ULONG ulPartLen /* count of bytes to sign */
++);
++#endif
++
++
++/* C_SignFinal finishes a multiple-part signature operation,
++ * returning the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignRecoverInit initializes a signature operation, where
++ * the data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of the signature key */
++);
++#endif
++
++
++/* C_SignRecover signs data in a single operation, where the
++ * data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++
++/* Verifying signatures and MACs */
++
++/* C_VerifyInit initializes a verification operation, where the
++ * signature is an appendix to the data, and plaintext cannot
++ * cannot be recovered from the signature (e.g. DSA). */
++CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_Verify verifies a signature in a single-part operation,
++ * where the signature is an appendix to the data, and plaintext
++ * cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Verify)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* signed data */
++ CK_ULONG ulDataLen, /* length of signed data */
++ CK_BYTE_PTR pSignature, /* signature */
++ CK_ULONG ulSignatureLen /* signature length*/
++);
++#endif
++
++
++/* C_VerifyUpdate continues a multiple-part verification
++ * operation, where the signature is an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* signed data */
++ CK_ULONG ulPartLen /* length of signed data */
++);
++#endif
++
++
++/* C_VerifyFinal finishes a multiple-part verification
++ * operation, checking the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen /* signature length */
++);
++#endif
++
++
++/* C_VerifyRecoverInit initializes a signature verification
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_VerifyRecover verifies a signature in a single-part
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen, /* signature length */
++ CK_BYTE_PTR pData, /* gets signed data */
++ CK_ULONG_PTR pulDataLen /* gets signed data len */
++);
++#endif
++
++
++
++/* Dual-function cryptographic operations */
++
++/* C_DigestEncryptUpdate continues a multiple-part digesting
++ * and encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptDigestUpdate continues a multiple-part decryption and
++ * digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets plaintext len */
++);
++#endif
++
++
++/* C_SignEncryptUpdate continues a multiple-part signing and
++ * encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptVerifyUpdate continues a multiple-part decryption and
++ * verify operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets p-text length */
++);
++#endif
++
++
++
++/* Key management */
++
++/* C_GenerateKey generates a secret key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
++ CK_ULONG ulCount, /* # of attrs in template */
++ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
++);
++#endif
++
++
++/* C_GenerateKeyPair generates a public-key/private-key pair,
++ * creating new key objects. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session
++ * handle */
++ CK_MECHANISM_PTR pMechanism, /* key-gen
++ * mech. */
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
++ * for pub.
++ * key */
++ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
++ * attrs. */
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
++ * for priv.
++ * key */
++ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
++ * attrs. */
++ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
++ * key
++ * handle */
++ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
++ * priv. key
++ * handle */
++);
++#endif
++
++
++/* C_WrapKey wraps (i.e., encrypts) a key. */
++CK_PKCS11_FUNCTION_INFO(C_WrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
++ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
++ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
++ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
++ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
++);
++#endif
++
++
++/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
++ * key object. */
++CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
++ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
++ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
++ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++/* C_DeriveKey derives a key from a base key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
++ CK_OBJECT_HANDLE hBaseKey, /* base key */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++
++/* Random number generation */
++
++/* C_SeedRandom mixes additional seed material into the token's
++ * random number generator. */
++CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSeed, /* the seed material */
++ CK_ULONG ulSeedLen /* length of seed material */
++);
++#endif
++
++
++/* C_GenerateRandom generates random data. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR RandomData, /* receives the random data */
++ CK_ULONG ulRandomLen /* # of bytes to generate */
++);
++#endif
++
++
++
++/* Parallel function management */
++
++/* C_GetFunctionStatus is a legacy function; it obtains an
++ * updated status of a function running in parallel with an
++ * application. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CancelFunction is a legacy function; it cancels a function
++ * running in parallel. */
++CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Functions added in for Cryptoki Version 2.01 or later */
++
++/* C_WaitForSlotEvent waits for a slot event (token insertion,
++ * removal, etc.) to occur. */
++CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FLAGS flags, /* blocking/nonblocking flag */
++ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
++ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
++);
++#endif
+Index: openssl/crypto/engine/pkcs11t.h
+diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2
+--- /dev/null Wed Dec 23 16:49:06 2015
++++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008
+@@ -0,0 +1,1885 @@
++/* pkcs11t.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* See top of pkcs11.h for information about the macros that
++ * must be defined and the structure-packing conventions that
++ * must be set before including this file. */
++
++#ifndef _PKCS11T_H_
++#define _PKCS11T_H_ 1
++
++#define CRYPTOKI_VERSION_MAJOR 2
++#define CRYPTOKI_VERSION_MINOR 20
++#define CRYPTOKI_VERSION_AMENDMENT 3
++
++#define CK_TRUE 1
++#define CK_FALSE 0
++
++#ifndef CK_DISABLE_TRUE_FALSE
++#ifndef FALSE
++#define FALSE CK_FALSE
++#endif
++
++#ifndef TRUE
++#define TRUE CK_TRUE
++#endif
++#endif
++
++/* an unsigned 8-bit value */
++typedef unsigned char CK_BYTE;
++
++/* an unsigned 8-bit character */
++typedef CK_BYTE CK_CHAR;
++
++/* an 8-bit UTF-8 character */
++typedef CK_BYTE CK_UTF8CHAR;
++
++/* a BYTE-sized Boolean flag */
++typedef CK_BYTE CK_BBOOL;
++
++/* an unsigned value, at least 32 bits long */
++typedef unsigned long int CK_ULONG;
++
++/* a signed value, the same size as a CK_ULONG */
++/* CK_LONG is new for v2.0 */
++typedef long int CK_LONG;
++
++/* at least 32 bits; each bit is a Boolean flag */
++typedef CK_ULONG CK_FLAGS;
++
++
++/* some special values for certain CK_ULONG variables */
++#define CK_UNAVAILABLE_INFORMATION (~0UL)
++#define CK_EFFECTIVELY_INFINITE 0
++
++
++typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++typedef CK_CHAR CK_PTR CK_CHAR_PTR;
++typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
++typedef CK_ULONG CK_PTR CK_ULONG_PTR;
++typedef void CK_PTR CK_VOID_PTR;
++
++/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
++typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
++
++
++/* The following value is always invalid if used as a session */
++/* handle or object handle */
++#define CK_INVALID_HANDLE 0
++
++
++typedef struct CK_VERSION {
++ CK_BYTE major; /* integer portion of version number */
++ CK_BYTE minor; /* 1/100ths portion of version number */
++} CK_VERSION;
++
++typedef CK_VERSION CK_PTR CK_VERSION_PTR;
++
++
++typedef struct CK_INFO {
++ /* manufacturerID and libraryDecription have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags; /* must be zero */
++
++ /* libraryDescription and libraryVersion are new for v2.0 */
++ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
++ CK_VERSION libraryVersion; /* version of library */
++} CK_INFO;
++
++typedef CK_INFO CK_PTR CK_INFO_PTR;
++
++
++/* CK_NOTIFICATION enumerates the types of notifications that
++ * Cryptoki provides to an application */
++/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_NOTIFICATION;
++#define CKN_SURRENDER 0
++
++/* The following notification is new for PKCS #11 v2.20 amendment 3 */
++#define CKN_OTP_CHANGED 1
++
++
++typedef CK_ULONG CK_SLOT_ID;
++
++typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
++
++
++/* CK_SLOT_INFO provides information about a slot */
++typedef struct CK_SLOT_INFO {
++ /* slotDescription and manufacturerID have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR slotDescription[64]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags;
++
++ /* hardwareVersion and firmwareVersion are new for v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++} CK_SLOT_INFO;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
++#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
++#define CKF_HW_SLOT 0x00000004 /* hardware slot */
++
++typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
++
++
++/* CK_TOKEN_INFO provides information about a token */
++typedef struct CK_TOKEN_INFO {
++ /* label, manufacturerID, and model have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR label[32]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_UTF8CHAR model[16]; /* blank padded */
++ CK_CHAR serialNumber[16]; /* blank padded */
++ CK_FLAGS flags; /* see below */
++
++ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
++ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
++ * changed from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulMaxSessionCount; /* max open sessions */
++ CK_ULONG ulSessionCount; /* sess. now open */
++ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
++ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
++ CK_ULONG ulMaxPinLen; /* in bytes */
++ CK_ULONG ulMinPinLen; /* in bytes */
++ CK_ULONG ulTotalPublicMemory; /* in bytes */
++ CK_ULONG ulFreePublicMemory; /* in bytes */
++ CK_ULONG ulTotalPrivateMemory; /* in bytes */
++ CK_ULONG ulFreePrivateMemory; /* in bytes */
++
++ /* hardwareVersion, firmwareVersion, and time are new for
++ * v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++ CK_CHAR utcTime[16]; /* time */
++} CK_TOKEN_INFO;
++
++/* The flags parameter is defined as follows:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RNG 0x00000001 /* has random #
++ * generator */
++#define CKF_WRITE_PROTECTED 0x00000002 /* token is
++ * write-
++ * protected */
++#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
++ * login */
++#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
++ * PIN is set */
++
++/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
++ * that means that *every* time the state of cryptographic
++ * operations of a session is successfully saved, all keys
++ * needed to continue those operations are stored in the state */
++#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
++
++/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
++ * that the token has some sort of clock. The time on that
++ * clock is returned in the token info structure */
++#define CKF_CLOCK_ON_TOKEN 0x00000040
++
++/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
++ * set, that means that there is some way for the user to login
++ * without sending a PIN through the Cryptoki library itself */
++#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
++
++/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
++ * that means that a single session with the token can perform
++ * dual simultaneous cryptographic operations (digest and
++ * encrypt; decrypt and digest; sign and encrypt; and decrypt
++ * and sign) */
++#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
++
++/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
++ * token has been initialized using C_InitializeToken or an
++ * equivalent mechanism outside the scope of PKCS #11.
++ * Calling C_InitializeToken when this flag is set will cause
++ * the token to be reinitialized. */
++#define CKF_TOKEN_INITIALIZED 0x00000400
++
++/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
++ * true, the token supports secondary authentication for
++ * private key objects. This flag is deprecated in v2.11 and
++ onwards. */
++#define CKF_SECONDARY_AUTHENTICATION 0x00000800
++
++/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect user login PIN has been entered at least once
++ * since the last successful authentication. */
++#define CKF_USER_PIN_COUNT_LOW 0x00010000
++
++/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect user PIN will it to become locked. */
++#define CKF_USER_PIN_FINAL_TRY 0x00020000
++
++/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
++ * user PIN has been locked. User login to the token is not
++ * possible. */
++#define CKF_USER_PIN_LOCKED 0x00040000
++
++/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the user PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
++
++/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect SO login PIN has been entered at least once since
++ * the last successful authentication. */
++#define CKF_SO_PIN_COUNT_LOW 0x00100000
++
++/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect SO PIN will it to become locked. */
++#define CKF_SO_PIN_FINAL_TRY 0x00200000
++
++/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
++ * PIN has been locked. SO login to the token is not possible.
++ */
++#define CKF_SO_PIN_LOCKED 0x00400000
++
++/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the SO PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
++
++typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
++
++
++/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
++ * identifies a session */
++typedef CK_ULONG CK_SESSION_HANDLE;
++
++typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
++
++
++/* CK_USER_TYPE enumerates the types of Cryptoki users */
++/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_USER_TYPE;
++/* Security Officer */
++#define CKU_SO 0
++/* Normal user */
++#define CKU_USER 1
++/* Context specific (added in v2.20) */
++#define CKU_CONTEXT_SPECIFIC 2
++
++/* CK_STATE enumerates the session states */
++/* CK_STATE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_STATE;
++#define CKS_RO_PUBLIC_SESSION 0
++#define CKS_RO_USER_FUNCTIONS 1
++#define CKS_RW_PUBLIC_SESSION 2
++#define CKS_RW_USER_FUNCTIONS 3
++#define CKS_RW_SO_FUNCTIONS 4
++
++
++/* CK_SESSION_INFO provides information about a session */
++typedef struct CK_SESSION_INFO {
++ CK_SLOT_ID slotID;
++ CK_STATE state;
++ CK_FLAGS flags; /* see below */
++
++ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulDeviceError; /* device-dependent error code */
++} CK_SESSION_INFO;
++
++/* The flags are defined in the following table:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RW_SESSION 0x00000002 /* session is r/w */
++#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
++
++typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
++
++
++/* CK_OBJECT_HANDLE is a token-specific identifier for an
++ * object */
++typedef CK_ULONG CK_OBJECT_HANDLE;
++
++typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
++
++
++/* CK_OBJECT_CLASS is a value that identifies the classes (or
++ * types) of objects that Cryptoki recognizes. It is defined
++ * as follows: */
++/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_OBJECT_CLASS;
++
++/* The following classes of objects are defined: */
++/* CKO_HW_FEATURE is new for v2.10 */
++/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
++/* CKO_MECHANISM is new for v2.20 */
++#define CKO_DATA 0x00000000
++#define CKO_CERTIFICATE 0x00000001
++#define CKO_PUBLIC_KEY 0x00000002
++#define CKO_PRIVATE_KEY 0x00000003
++#define CKO_SECRET_KEY 0x00000004
++#define CKO_HW_FEATURE 0x00000005
++#define CKO_DOMAIN_PARAMETERS 0x00000006
++#define CKO_MECHANISM 0x00000007
++
++/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */
++#define CKO_OTP_KEY 0x00000008
++
++#define CKO_VENDOR_DEFINED 0x80000000
++
++typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
++
++/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
++ * value that identifies the hardware feature type of an object
++ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
++typedef CK_ULONG CK_HW_FEATURE_TYPE;
++
++/* The following hardware feature types are defined */
++/* CKH_USER_INTERFACE is new for v2.20 */
++#define CKH_MONOTONIC_COUNTER 0x00000001
++#define CKH_CLOCK 0x00000002
++#define CKH_USER_INTERFACE 0x00000003
++#define CKH_VENDOR_DEFINED 0x80000000
++
++/* CK_KEY_TYPE is a value that identifies a key type */
++/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_KEY_TYPE;
++
++/* the following key types are defined: */
++#define CKK_RSA 0x00000000
++#define CKK_DSA 0x00000001
++#define CKK_DH 0x00000002
++
++/* CKK_ECDSA and CKK_KEA are new for v2.0 */
++/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
++#define CKK_ECDSA 0x00000003
++#define CKK_EC 0x00000003
++#define CKK_X9_42_DH 0x00000004
++#define CKK_KEA 0x00000005
++
++#define CKK_GENERIC_SECRET 0x00000010
++#define CKK_RC2 0x00000011
++#define CKK_RC4 0x00000012
++#define CKK_DES 0x00000013
++#define CKK_DES2 0x00000014
++#define CKK_DES3 0x00000015
++
++/* all these key types are new for v2.0 */
++#define CKK_CAST 0x00000016
++#define CKK_CAST3 0x00000017
++/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
++#define CKK_CAST5 0x00000018
++#define CKK_CAST128 0x00000018
++#define CKK_RC5 0x00000019
++#define CKK_IDEA 0x0000001A
++#define CKK_SKIPJACK 0x0000001B
++#define CKK_BATON 0x0000001C
++#define CKK_JUNIPER 0x0000001D
++#define CKK_CDMF 0x0000001E
++#define CKK_AES 0x0000001F
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKK_BLOWFISH 0x00000020
++#define CKK_TWOFISH 0x00000021
++
++/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */
++#define CKK_SECURID 0x00000022
++#define CKK_HOTP 0x00000023
++#define CKK_ACTI 0x00000024
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_CAMELLIA 0x00000025
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_ARIA 0x00000026
++
++
++#define CKK_VENDOR_DEFINED 0x80000000
++
++
++/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
++ * type */
++/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_CERTIFICATE_TYPE;
++
++/* The following certificate types are defined: */
++/* CKC_X_509_ATTR_CERT is new for v2.10 */
++/* CKC_WTLS is new for v2.20 */
++#define CKC_X_509 0x00000000
++#define CKC_X_509_ATTR_CERT 0x00000001
++#define CKC_WTLS 0x00000002
++#define CKC_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
++ * type */
++/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_ATTRIBUTE_TYPE;
++
++/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
++ consists of an array of values. */
++#define CKF_ARRAY_ATTRIBUTE 0x40000000
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_FORMAT attribute */
++#define CK_OTP_FORMAT_DECIMAL 0
++#define CK_OTP_FORMAT_HEXADECIMAL 1
++#define CK_OTP_FORMAT_ALPHANUMERIC 2
++#define CK_OTP_FORMAT_BINARY 3
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_..._REQUIREMENT attributes */
++#define CK_OTP_PARAM_IGNORED 0
++#define CK_OTP_PARAM_OPTIONAL 1
++#define CK_OTP_PARAM_MANDATORY 2
++
++/* The following attribute types are defined: */
++#define CKA_CLASS 0x00000000
++#define CKA_TOKEN 0x00000001
++#define CKA_PRIVATE 0x00000002
++#define CKA_LABEL 0x00000003
++#define CKA_APPLICATION 0x00000010
++#define CKA_VALUE 0x00000011
++
++/* CKA_OBJECT_ID is new for v2.10 */
++#define CKA_OBJECT_ID 0x00000012
++
++#define CKA_CERTIFICATE_TYPE 0x00000080
++#define CKA_ISSUER 0x00000081
++#define CKA_SERIAL_NUMBER 0x00000082
++
++/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
++ * for v2.10 */
++#define CKA_AC_ISSUER 0x00000083
++#define CKA_OWNER 0x00000084
++#define CKA_ATTR_TYPES 0x00000085
++
++/* CKA_TRUSTED is new for v2.11 */
++#define CKA_TRUSTED 0x00000086
++
++/* CKA_CERTIFICATE_CATEGORY ...
++ * CKA_CHECK_VALUE are new for v2.20 */
++#define CKA_CERTIFICATE_CATEGORY 0x00000087
++#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
++#define CKA_URL 0x00000089
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
++#define CKA_CHECK_VALUE 0x00000090
++
++#define CKA_KEY_TYPE 0x00000100
++#define CKA_SUBJECT 0x00000101
++#define CKA_ID 0x00000102
++#define CKA_SENSITIVE 0x00000103
++#define CKA_ENCRYPT 0x00000104
++#define CKA_DECRYPT 0x00000105
++#define CKA_WRAP 0x00000106
++#define CKA_UNWRAP 0x00000107
++#define CKA_SIGN 0x00000108
++#define CKA_SIGN_RECOVER 0x00000109
++#define CKA_VERIFY 0x0000010A
++#define CKA_VERIFY_RECOVER 0x0000010B
++#define CKA_DERIVE 0x0000010C
++#define CKA_START_DATE 0x00000110
++#define CKA_END_DATE 0x00000111
++#define CKA_MODULUS 0x00000120
++#define CKA_MODULUS_BITS 0x00000121
++#define CKA_PUBLIC_EXPONENT 0x00000122
++#define CKA_PRIVATE_EXPONENT 0x00000123
++#define CKA_PRIME_1 0x00000124
++#define CKA_PRIME_2 0x00000125
++#define CKA_EXPONENT_1 0x00000126
++#define CKA_EXPONENT_2 0x00000127
++#define CKA_COEFFICIENT 0x00000128
++#define CKA_PRIME 0x00000130
++#define CKA_SUBPRIME 0x00000131
++#define CKA_BASE 0x00000132
++
++/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
++#define CKA_PRIME_BITS 0x00000133
++#define CKA_SUBPRIME_BITS 0x00000134
++#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
++/* (To retain backwards-compatibility) */
++
++#define CKA_VALUE_BITS 0x00000160
++#define CKA_VALUE_LEN 0x00000161
++
++/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
++ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
++ * and CKA_EC_POINT are new for v2.0 */
++#define CKA_EXTRACTABLE 0x00000162
++#define CKA_LOCAL 0x00000163
++#define CKA_NEVER_EXTRACTABLE 0x00000164
++#define CKA_ALWAYS_SENSITIVE 0x00000165
++
++/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
++#define CKA_KEY_GEN_MECHANISM 0x00000166
++
++#define CKA_MODIFIABLE 0x00000170
++
++/* CKA_ECDSA_PARAMS is deprecated in v2.11,
++ * CKA_EC_PARAMS is preferred. */
++#define CKA_ECDSA_PARAMS 0x00000180
++#define CKA_EC_PARAMS 0x00000180
++
++#define CKA_EC_POINT 0x00000181
++
++/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
++ * are new for v2.10. Deprecated in v2.11 and onwards. */
++#define CKA_SECONDARY_AUTH 0x00000200
++#define CKA_AUTH_PIN_FLAGS 0x00000201
++
++/* CKA_ALWAYS_AUTHENTICATE ...
++ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
++#define CKA_ALWAYS_AUTHENTICATE 0x00000202
++
++#define CKA_WRAP_WITH_TRUSTED 0x00000210
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++
++/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */
++#define CKA_OTP_FORMAT 0x00000220
++#define CKA_OTP_LENGTH 0x00000221
++#define CKA_OTP_TIME_INTERVAL 0x00000222
++#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
++#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
++#define CKA_OTP_TIME_REQUIREMENT 0x00000225
++#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
++#define CKA_OTP_PIN_REQUIREMENT 0x00000227
++#define CKA_OTP_COUNTER 0x0000022E
++#define CKA_OTP_TIME 0x0000022F
++#define CKA_OTP_USER_IDENTIFIER 0x0000022A
++#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
++#define CKA_OTP_SERVICE_LOGO 0x0000022C
++#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
++
++
++/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
++ * are new for v2.10 */
++#define CKA_HW_FEATURE_TYPE 0x00000300
++#define CKA_RESET_ON_INIT 0x00000301
++#define CKA_HAS_RESET 0x00000302
++
++/* The following attributes are new for v2.20 */
++#define CKA_PIXEL_X 0x00000400
++#define CKA_PIXEL_Y 0x00000401
++#define CKA_RESOLUTION 0x00000402
++#define CKA_CHAR_ROWS 0x00000403
++#define CKA_CHAR_COLUMNS 0x00000404
++#define CKA_COLOR 0x00000405
++#define CKA_BITS_PER_PIXEL 0x00000406
++#define CKA_CHAR_SETS 0x00000480
++#define CKA_ENCODING_METHODS 0x00000481
++#define CKA_MIME_TYPES 0x00000482
++#define CKA_MECHANISM_TYPE 0x00000500
++#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
++#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
++#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
++#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
++
++#define CKA_VENDOR_DEFINED 0x80000000
++
++/* CK_ATTRIBUTE is a structure that includes the type, length
++ * and value of an attribute */
++typedef struct CK_ATTRIBUTE {
++ CK_ATTRIBUTE_TYPE type;
++ CK_VOID_PTR pValue;
++
++ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulValueLen; /* in bytes */
++} CK_ATTRIBUTE;
++
++typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
++
++
++/* CK_DATE is a structure that defines a date */
++typedef struct CK_DATE{
++ CK_CHAR year[4]; /* the year ("1900" - "9999") */
++ CK_CHAR month[2]; /* the month ("01" - "12") */
++ CK_CHAR day[2]; /* the day ("01" - "31") */
++} CK_DATE;
++
++
++/* CK_MECHANISM_TYPE is a value that identifies a mechanism
++ * type */
++/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_MECHANISM_TYPE;
++
++/* the following mechanism types are defined: */
++#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
++#define CKM_RSA_PKCS 0x00000001
++#define CKM_RSA_9796 0x00000002
++#define CKM_RSA_X_509 0x00000003
++
++/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
++ * are new for v2.0. They are mechanisms which hash and sign */
++#define CKM_MD2_RSA_PKCS 0x00000004
++#define CKM_MD5_RSA_PKCS 0x00000005
++#define CKM_SHA1_RSA_PKCS 0x00000006
++
++/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
++ * CKM_RSA_PKCS_OAEP are new for v2.10 */
++#define CKM_RIPEMD128_RSA_PKCS 0x00000007
++#define CKM_RIPEMD160_RSA_PKCS 0x00000008
++#define CKM_RSA_PKCS_OAEP 0x00000009
++
++/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
++ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
++#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
++#define CKM_RSA_X9_31 0x0000000B
++#define CKM_SHA1_RSA_X9_31 0x0000000C
++#define CKM_RSA_PKCS_PSS 0x0000000D
++#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
++
++#define CKM_DSA_KEY_PAIR_GEN 0x00000010
++#define CKM_DSA 0x00000011
++#define CKM_DSA_SHA1 0x00000012
++#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
++#define CKM_DH_PKCS_DERIVE 0x00000021
++
++/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
++ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
++ * v2.11 */
++#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
++#define CKM_X9_42_DH_DERIVE 0x00000031
++#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
++#define CKM_X9_42_MQV_DERIVE 0x00000033
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_RSA_PKCS 0x00000040
++#define CKM_SHA384_RSA_PKCS 0x00000041
++#define CKM_SHA512_RSA_PKCS 0x00000042
++#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
++#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
++#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
++
++/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_RSA_PKCS 0x00000046
++#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
++
++#define CKM_RC2_KEY_GEN 0x00000100
++#define CKM_RC2_ECB 0x00000101
++#define CKM_RC2_CBC 0x00000102
++#define CKM_RC2_MAC 0x00000103
++
++/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
++#define CKM_RC2_MAC_GENERAL 0x00000104
++#define CKM_RC2_CBC_PAD 0x00000105
++
++#define CKM_RC4_KEY_GEN 0x00000110
++#define CKM_RC4 0x00000111
++#define CKM_DES_KEY_GEN 0x00000120
++#define CKM_DES_ECB 0x00000121
++#define CKM_DES_CBC 0x00000122
++#define CKM_DES_MAC 0x00000123
++
++/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
++#define CKM_DES_MAC_GENERAL 0x00000124
++#define CKM_DES_CBC_PAD 0x00000125
++
++#define CKM_DES2_KEY_GEN 0x00000130
++#define CKM_DES3_KEY_GEN 0x00000131
++#define CKM_DES3_ECB 0x00000132
++#define CKM_DES3_CBC 0x00000133
++#define CKM_DES3_MAC 0x00000134
++
++/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
++ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
++ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
++#define CKM_DES3_MAC_GENERAL 0x00000135
++#define CKM_DES3_CBC_PAD 0x00000136
++#define CKM_CDMF_KEY_GEN 0x00000140
++#define CKM_CDMF_ECB 0x00000141
++#define CKM_CDMF_CBC 0x00000142
++#define CKM_CDMF_MAC 0x00000143
++#define CKM_CDMF_MAC_GENERAL 0x00000144
++#define CKM_CDMF_CBC_PAD 0x00000145
++
++/* the following four DES mechanisms are new for v2.20 */
++#define CKM_DES_OFB64 0x00000150
++#define CKM_DES_OFB8 0x00000151
++#define CKM_DES_CFB64 0x00000152
++#define CKM_DES_CFB8 0x00000153
++
++#define CKM_MD2 0x00000200
++
++/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD2_HMAC 0x00000201
++#define CKM_MD2_HMAC_GENERAL 0x00000202
++
++#define CKM_MD5 0x00000210
++
++/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD5_HMAC 0x00000211
++#define CKM_MD5_HMAC_GENERAL 0x00000212
++
++#define CKM_SHA_1 0x00000220
++
++/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
++#define CKM_SHA_1_HMAC 0x00000221
++#define CKM_SHA_1_HMAC_GENERAL 0x00000222
++
++/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
++ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
++ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
++#define CKM_RIPEMD128 0x00000230
++#define CKM_RIPEMD128_HMAC 0x00000231
++#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
++#define CKM_RIPEMD160 0x00000240
++#define CKM_RIPEMD160_HMAC 0x00000241
++#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256 0x00000250
++#define CKM_SHA256_HMAC 0x00000251
++#define CKM_SHA256_HMAC_GENERAL 0x00000252
++
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224 0x00000255
++#define CKM_SHA224_HMAC 0x00000256
++#define CKM_SHA224_HMAC_GENERAL 0x00000257
++
++#define CKM_SHA384 0x00000260
++#define CKM_SHA384_HMAC 0x00000261
++#define CKM_SHA384_HMAC_GENERAL 0x00000262
++#define CKM_SHA512 0x00000270
++#define CKM_SHA512_HMAC 0x00000271
++#define CKM_SHA512_HMAC_GENERAL 0x00000272
++
++/* SecurID is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_SECURID_KEY_GEN 0x00000280
++#define CKM_SECURID 0x00000282
++
++/* HOTP is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_HOTP_KEY_GEN 0x00000290
++#define CKM_HOTP 0x00000291
++
++/* ACTI is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_ACTI 0x000002A0
++#define CKM_ACTI_KEY_GEN 0x000002A1
++
++/* All of the following mechanisms are new for v2.0 */
++/* Note that CAST128 and CAST5 are the same algorithm */
++#define CKM_CAST_KEY_GEN 0x00000300
++#define CKM_CAST_ECB 0x00000301
++#define CKM_CAST_CBC 0x00000302
++#define CKM_CAST_MAC 0x00000303
++#define CKM_CAST_MAC_GENERAL 0x00000304
++#define CKM_CAST_CBC_PAD 0x00000305
++#define CKM_CAST3_KEY_GEN 0x00000310
++#define CKM_CAST3_ECB 0x00000311
++#define CKM_CAST3_CBC 0x00000312
++#define CKM_CAST3_MAC 0x00000313
++#define CKM_CAST3_MAC_GENERAL 0x00000314
++#define CKM_CAST3_CBC_PAD 0x00000315
++#define CKM_CAST5_KEY_GEN 0x00000320
++#define CKM_CAST128_KEY_GEN 0x00000320
++#define CKM_CAST5_ECB 0x00000321
++#define CKM_CAST128_ECB 0x00000321
++#define CKM_CAST5_CBC 0x00000322
++#define CKM_CAST128_CBC 0x00000322
++#define CKM_CAST5_MAC 0x00000323
++#define CKM_CAST128_MAC 0x00000323
++#define CKM_CAST5_MAC_GENERAL 0x00000324
++#define CKM_CAST128_MAC_GENERAL 0x00000324
++#define CKM_CAST5_CBC_PAD 0x00000325
++#define CKM_CAST128_CBC_PAD 0x00000325
++#define CKM_RC5_KEY_GEN 0x00000330
++#define CKM_RC5_ECB 0x00000331
++#define CKM_RC5_CBC 0x00000332
++#define CKM_RC5_MAC 0x00000333
++#define CKM_RC5_MAC_GENERAL 0x00000334
++#define CKM_RC5_CBC_PAD 0x00000335
++#define CKM_IDEA_KEY_GEN 0x00000340
++#define CKM_IDEA_ECB 0x00000341
++#define CKM_IDEA_CBC 0x00000342
++#define CKM_IDEA_MAC 0x00000343
++#define CKM_IDEA_MAC_GENERAL 0x00000344
++#define CKM_IDEA_CBC_PAD 0x00000345
++#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
++#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
++#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
++#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
++#define CKM_XOR_BASE_AND_DATA 0x00000364
++#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
++#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
++#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
++#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
++
++/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
++ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
++ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
++#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
++#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
++#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
++#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
++#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
++
++/* CKM_TLS_PRF is new for v2.20 */
++#define CKM_TLS_PRF 0x00000378
++
++#define CKM_SSL3_MD5_MAC 0x00000380
++#define CKM_SSL3_SHA1_MAC 0x00000381
++#define CKM_MD5_KEY_DERIVATION 0x00000390
++#define CKM_MD2_KEY_DERIVATION 0x00000391
++#define CKM_SHA1_KEY_DERIVATION 0x00000392
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_KEY_DERIVATION 0x00000393
++#define CKM_SHA384_KEY_DERIVATION 0x00000394
++#define CKM_SHA512_KEY_DERIVATION 0x00000395
++
++/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_KEY_DERIVATION 0x00000396
++
++#define CKM_PBE_MD2_DES_CBC 0x000003A0
++#define CKM_PBE_MD5_DES_CBC 0x000003A1
++#define CKM_PBE_MD5_CAST_CBC 0x000003A2
++#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
++#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
++#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
++#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
++#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
++#define CKM_PBE_SHA1_RC4_128 0x000003A6
++#define CKM_PBE_SHA1_RC4_40 0x000003A7
++#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
++#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
++#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
++#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
++
++/* CKM_PKCS5_PBKD2 is new for v2.10 */
++#define CKM_PKCS5_PBKD2 0x000003B0
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
++
++/* WTLS mechanisms are new for v2.20 */
++#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
++#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
++#define CKM_WTLS_PRF 0x000003D3
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
++
++#define CKM_KEY_WRAP_LYNKS 0x00000400
++#define CKM_KEY_WRAP_SET_OAEP 0x00000401
++
++/* CKM_CMS_SIG is new for v2.20 */
++#define CKM_CMS_SIG 0x00000500
++
++/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */
++#define CKM_KIP_DERIVE 0x00000510
++#define CKM_KIP_WRAP 0x00000511
++#define CKM_KIP_MAC 0x00000512
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_CAMELLIA_KEY_GEN 0x00000550
++#define CKM_CAMELLIA_ECB 0x00000551
++#define CKM_CAMELLIA_CBC 0x00000552
++#define CKM_CAMELLIA_MAC 0x00000553
++#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
++#define CKM_CAMELLIA_CBC_PAD 0x00000555
++#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
++#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
++#define CKM_CAMELLIA_CTR 0x00000558
++
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_ARIA_KEY_GEN 0x00000560
++#define CKM_ARIA_ECB 0x00000561
++#define CKM_ARIA_CBC 0x00000562
++#define CKM_ARIA_MAC 0x00000563
++#define CKM_ARIA_MAC_GENERAL 0x00000564
++#define CKM_ARIA_CBC_PAD 0x00000565
++#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
++#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
++
++/* Fortezza mechanisms */
++#define CKM_SKIPJACK_KEY_GEN 0x00001000
++#define CKM_SKIPJACK_ECB64 0x00001001
++#define CKM_SKIPJACK_CBC64 0x00001002
++#define CKM_SKIPJACK_OFB64 0x00001003
++#define CKM_SKIPJACK_CFB64 0x00001004
++#define CKM_SKIPJACK_CFB32 0x00001005
++#define CKM_SKIPJACK_CFB16 0x00001006
++#define CKM_SKIPJACK_CFB8 0x00001007
++#define CKM_SKIPJACK_WRAP 0x00001008
++#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
++#define CKM_SKIPJACK_RELAYX 0x0000100a
++#define CKM_KEA_KEY_PAIR_GEN 0x00001010
++#define CKM_KEA_KEY_DERIVE 0x00001011
++#define CKM_FORTEZZA_TIMESTAMP 0x00001020
++#define CKM_BATON_KEY_GEN 0x00001030
++#define CKM_BATON_ECB128 0x00001031
++#define CKM_BATON_ECB96 0x00001032
++#define CKM_BATON_CBC128 0x00001033
++#define CKM_BATON_COUNTER 0x00001034
++#define CKM_BATON_SHUFFLE 0x00001035
++#define CKM_BATON_WRAP 0x00001036
++
++/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
++ * CKM_EC_KEY_PAIR_GEN is preferred */
++#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
++#define CKM_EC_KEY_PAIR_GEN 0x00001040
++
++#define CKM_ECDSA 0x00001041
++#define CKM_ECDSA_SHA1 0x00001042
++
++/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
++ * are new for v2.11 */
++#define CKM_ECDH1_DERIVE 0x00001050
++#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
++#define CKM_ECMQV_DERIVE 0x00001052
++
++#define CKM_JUNIPER_KEY_GEN 0x00001060
++#define CKM_JUNIPER_ECB128 0x00001061
++#define CKM_JUNIPER_CBC128 0x00001062
++#define CKM_JUNIPER_COUNTER 0x00001063
++#define CKM_JUNIPER_SHUFFLE 0x00001064
++#define CKM_JUNIPER_WRAP 0x00001065
++#define CKM_FASTHASH 0x00001070
++
++/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
++ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
++ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
++ * new for v2.11 */
++#define CKM_AES_KEY_GEN 0x00001080
++#define CKM_AES_ECB 0x00001081
++#define CKM_AES_CBC 0x00001082
++#define CKM_AES_MAC 0x00001083
++#define CKM_AES_MAC_GENERAL 0x00001084
++#define CKM_AES_CBC_PAD 0x00001085
++
++/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_AES_CTR 0x00001086
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKM_BLOWFISH_KEY_GEN 0x00001090
++#define CKM_BLOWFISH_CBC 0x00001091
++#define CKM_TWOFISH_KEY_GEN 0x00001092
++#define CKM_TWOFISH_CBC 0x00001093
++
++
++/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
++#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
++#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
++#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
++#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
++#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
++#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
++
++#define CKM_DSA_PARAMETER_GEN 0x00002000
++#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
++#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
++
++#define CKM_VENDOR_DEFINED 0x80000000
++
++typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
++
++
++/* CK_MECHANISM is a structure that specifies a particular
++ * mechanism */
++typedef struct CK_MECHANISM {
++ CK_MECHANISM_TYPE mechanism;
++ CK_VOID_PTR pParameter;
++
++ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulParameterLen; /* in bytes */
++} CK_MECHANISM;
++
++typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
++
++
++/* CK_MECHANISM_INFO provides information about a particular
++ * mechanism */
++typedef struct CK_MECHANISM_INFO {
++ CK_ULONG ulMinKeySize;
++ CK_ULONG ulMaxKeySize;
++ CK_FLAGS flags;
++} CK_MECHANISM_INFO;
++
++/* The flags are defined as follows:
++ * Bit Flag Mask Meaning */
++#define CKF_HW 0x00000001 /* performed by HW */
++
++/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
++ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
++ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
++ * and CKF_DERIVE are new for v2.0. They specify whether or not
++ * a mechanism can be used for a particular task */
++#define CKF_ENCRYPT 0x00000100
++#define CKF_DECRYPT 0x00000200
++#define CKF_DIGEST 0x00000400
++#define CKF_SIGN 0x00000800
++#define CKF_SIGN_RECOVER 0x00001000
++#define CKF_VERIFY 0x00002000
++#define CKF_VERIFY_RECOVER 0x00004000
++#define CKF_GENERATE 0x00008000
++#define CKF_GENERATE_KEY_PAIR 0x00010000
++#define CKF_WRAP 0x00020000
++#define CKF_UNWRAP 0x00040000
++#define CKF_DERIVE 0x00080000
++
++/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
++ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
++ * describe a token's EC capabilities not available in mechanism
++ * information. */
++#define CKF_EC_F_P 0x00100000
++#define CKF_EC_F_2M 0x00200000
++#define CKF_EC_ECPARAMETERS 0x00400000
++#define CKF_EC_NAMEDCURVE 0x00800000
++#define CKF_EC_UNCOMPRESS 0x01000000
++#define CKF_EC_COMPRESS 0x02000000
++
++#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
++
++typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
++
++
++/* CK_RV is a value that identifies the return value of a
++ * Cryptoki function */
++/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_RV;
++
++#define CKR_OK 0x00000000
++#define CKR_CANCEL 0x00000001
++#define CKR_HOST_MEMORY 0x00000002
++#define CKR_SLOT_ID_INVALID 0x00000003
++
++/* CKR_FLAGS_INVALID was removed for v2.0 */
++
++/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
++#define CKR_GENERAL_ERROR 0x00000005
++#define CKR_FUNCTION_FAILED 0x00000006
++
++/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
++ * and CKR_CANT_LOCK are new for v2.01 */
++#define CKR_ARGUMENTS_BAD 0x00000007
++#define CKR_NO_EVENT 0x00000008
++#define CKR_NEED_TO_CREATE_THREADS 0x00000009
++#define CKR_CANT_LOCK 0x0000000A
++
++#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
++#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
++#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
++#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
++#define CKR_DATA_INVALID 0x00000020
++#define CKR_DATA_LEN_RANGE 0x00000021
++#define CKR_DEVICE_ERROR 0x00000030
++#define CKR_DEVICE_MEMORY 0x00000031
++#define CKR_DEVICE_REMOVED 0x00000032
++#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
++#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
++#define CKR_FUNCTION_CANCELED 0x00000050
++#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
++
++/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
++#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
++
++#define CKR_KEY_HANDLE_INVALID 0x00000060
++
++/* CKR_KEY_SENSITIVE was removed for v2.0 */
++
++#define CKR_KEY_SIZE_RANGE 0x00000062
++#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
++
++/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
++ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
++ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
++ * v2.0 */
++#define CKR_KEY_NOT_NEEDED 0x00000064
++#define CKR_KEY_CHANGED 0x00000065
++#define CKR_KEY_NEEDED 0x00000066
++#define CKR_KEY_INDIGESTIBLE 0x00000067
++#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
++#define CKR_KEY_NOT_WRAPPABLE 0x00000069
++#define CKR_KEY_UNEXTRACTABLE 0x0000006A
++
++#define CKR_MECHANISM_INVALID 0x00000070
++#define CKR_MECHANISM_PARAM_INVALID 0x00000071
++
++/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
++ * were removed for v2.0 */
++#define CKR_OBJECT_HANDLE_INVALID 0x00000082
++#define CKR_OPERATION_ACTIVE 0x00000090
++#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
++#define CKR_PIN_INCORRECT 0x000000A0
++#define CKR_PIN_INVALID 0x000000A1
++#define CKR_PIN_LEN_RANGE 0x000000A2
++
++/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
++#define CKR_PIN_EXPIRED 0x000000A3
++#define CKR_PIN_LOCKED 0x000000A4
++
++#define CKR_SESSION_CLOSED 0x000000B0
++#define CKR_SESSION_COUNT 0x000000B1
++#define CKR_SESSION_HANDLE_INVALID 0x000000B3
++#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
++#define CKR_SESSION_READ_ONLY 0x000000B5
++#define CKR_SESSION_EXISTS 0x000000B6
++
++/* CKR_SESSION_READ_ONLY_EXISTS and
++ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
++#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
++#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
++
++#define CKR_SIGNATURE_INVALID 0x000000C0
++#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
++#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
++#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
++#define CKR_TOKEN_NOT_PRESENT 0x000000E0
++#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
++#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
++#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
++#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
++#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
++#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
++#define CKR_USER_NOT_LOGGED_IN 0x00000101
++#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
++#define CKR_USER_TYPE_INVALID 0x00000103
++
++/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
++ * are new to v2.01 */
++#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
++#define CKR_USER_TOO_MANY_TYPES 0x00000105
++
++#define CKR_WRAPPED_KEY_INVALID 0x00000110
++#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
++#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
++#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
++#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
++#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
++
++/* These are new to v2.0 */
++#define CKR_RANDOM_NO_RNG 0x00000121
++
++/* These are new to v2.11 */
++#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
++
++/* These are new to v2.0 */
++#define CKR_BUFFER_TOO_SMALL 0x00000150
++#define CKR_SAVED_STATE_INVALID 0x00000160
++#define CKR_INFORMATION_SENSITIVE 0x00000170
++#define CKR_STATE_UNSAVEABLE 0x00000180
++
++/* These are new to v2.01 */
++#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
++#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
++#define CKR_MUTEX_BAD 0x000001A0
++#define CKR_MUTEX_NOT_LOCKED 0x000001A1
++
++/* The following return values are new for PKCS #11 v2.20 amendment 3 */
++#define CKR_NEW_PIN_MODE 0x000001B0
++#define CKR_NEXT_OTP 0x000001B1
++
++/* This is new to v2.20 */
++#define CKR_FUNCTION_REJECTED 0x00000200
++
++#define CKR_VENDOR_DEFINED 0x80000000
++
++
++/* CK_NOTIFY is an application callback that processes events */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication /* passed to C_OpenSession */
++);
++
++
++/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
++ * version and pointers of appropriate types to all the
++ * Cryptoki functions */
++/* CK_FUNCTION_LIST is new for v2.0 */
++typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
++
++typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
++
++typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
++
++
++/* CK_CREATEMUTEX is an application callback for creating a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
++ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
++);
++
++
++/* CK_DESTROYMUTEX is an application callback for destroying a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_LOCKMUTEX is an application callback for locking a mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_UNLOCKMUTEX is an application callback for unlocking a
++ * mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_C_INITIALIZE_ARGS provides the optional arguments to
++ * C_Initialize */
++typedef struct CK_C_INITIALIZE_ARGS {
++ CK_CREATEMUTEX CreateMutex;
++ CK_DESTROYMUTEX DestroyMutex;
++ CK_LOCKMUTEX LockMutex;
++ CK_UNLOCKMUTEX UnlockMutex;
++ CK_FLAGS flags;
++ CK_VOID_PTR pReserved;
++} CK_C_INITIALIZE_ARGS;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
++#define CKF_OS_LOCKING_OK 0x00000002
++
++typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
++
++
++/* additional flags for parameters to functions */
++
++/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
++#define CKF_DONT_BLOCK 1
++
++/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
++ * Generation Function (MGF) applied to a message block when
++ * formatting a message block for the PKCS #1 OAEP encryption
++ * scheme. */
++typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
++
++typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
++
++/* The following MGFs are defined */
++/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
++ * are new for v2.20 */
++#define CKG_MGF1_SHA1 0x00000001
++#define CKG_MGF1_SHA256 0x00000002
++#define CKG_MGF1_SHA384 0x00000003
++#define CKG_MGF1_SHA512 0x00000004
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKG_MGF1_SHA224 0x00000005
++
++/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
++ * of the encoding parameter when formatting a message block
++ * for the PKCS #1 OAEP encryption scheme. */
++typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
++
++typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
++
++/* The following encoding parameter sources are defined */
++#define CKZ_DATA_SPECIFIED 0x00000001
++
++/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
++ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_OAEP mechanism. */
++typedef struct CK_RSA_PKCS_OAEP_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
++ CK_VOID_PTR pSourceData;
++ CK_ULONG ulSourceDataLen;
++} CK_RSA_PKCS_OAEP_PARAMS;
++
++typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
++
++/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
++ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_PSS mechanism(s). */
++typedef struct CK_RSA_PKCS_PSS_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_ULONG sLen;
++} CK_RSA_PKCS_PSS_PARAMS;
++
++typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
++
++/* CK_EC_KDF_TYPE is new for v2.11. */
++typedef CK_ULONG CK_EC_KDF_TYPE;
++
++/* The following EC Key Derivation Functions are defined */
++#define CKD_NULL 0x00000001
++#define CKD_SHA1_KDF 0x00000002
++
++/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
++ * where each party contributes one key pair.
++ */
++typedef struct CK_ECDH1_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_ECDH1_DERIVE_PARAMS;
++
++typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
++
++
++/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
++typedef struct CK_ECDH2_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_ECDH2_DERIVE_PARAMS;
++
++typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_ECMQV_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_ECMQV_DERIVE_PARAMS;
++
++typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
++
++/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
++ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
++typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
++typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
++
++/* The following X9.42 DH key derivation functions are defined
++ (besides CKD_NULL already defined : */
++#define CKD_SHA1_KDF_ASN1 0x00000003
++#define CKD_SHA1_KDF_CONCATENATE 0x00000004
++
++/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
++ * contributes one key pair */
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_X9_42_DH1_DERIVE_PARAMS;
++
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
++
++/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
++ * mechanisms, where each party contributes two key pairs */
++typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_X9_42_DH2_DERIVE_PARAMS;
++
++typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_X9_42_MQV_DERIVE_PARAMS;
++
++typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
++
++/* CK_KEA_DERIVE_PARAMS provides the parameters to the
++ * CKM_KEA_DERIVE mechanism */
++/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
++typedef struct CK_KEA_DERIVE_PARAMS {
++ CK_BBOOL isSender;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pRandomB;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_KEA_DERIVE_PARAMS;
++
++typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
++
++
++/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
++ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
++ * holds the effective keysize */
++typedef CK_ULONG CK_RC2_PARAMS;
++
++typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
++
++
++/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
++ * mechanism */
++typedef struct CK_RC2_CBC_PARAMS {
++ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++
++ CK_BYTE iv[8]; /* IV for CBC mode */
++} CK_RC2_CBC_PARAMS;
++
++typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
++
++
++/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC2_MAC_GENERAL mechanism */
++/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC2_MAC_GENERAL_PARAMS {
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC2_MAC_GENERAL_PARAMS;
++
++typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC2_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
++ * CKM_RC5_MAC mechanisms */
++/* CK_RC5_PARAMS is new for v2.0 */
++typedef struct CK_RC5_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++} CK_RC5_PARAMS;
++
++typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
++
++
++/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
++ * mechanism */
++/* CK_RC5_CBC_PARAMS is new for v2.0 */
++typedef struct CK_RC5_CBC_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_BYTE_PTR pIv; /* pointer to IV */
++ CK_ULONG ulIvLen; /* length of IV in bytes */
++} CK_RC5_CBC_PARAMS;
++
++typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
++
++
++/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC5_MAC_GENERAL mechanism */
++/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC5_MAC_GENERAL_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC5_MAC_GENERAL_PARAMS;
++
++typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC5_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
++ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
++ * the MAC */
++/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
++
++typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
++
++/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
++typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[8];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pPassword;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPAndGLen;
++ CK_ULONG ulQLen;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pPrimeP;
++ CK_BYTE_PTR pBaseG;
++ CK_BYTE_PTR pSubprimeQ;
++} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
++
++typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
++ CK_SKIPJACK_PRIVATE_WRAP_PTR;
++
++
++/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_RELAYX mechanism */
++/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_RELAYX_PARAMS {
++ CK_ULONG ulOldWrappedXLen;
++ CK_BYTE_PTR pOldWrappedX;
++ CK_ULONG ulOldPasswordLen;
++ CK_BYTE_PTR pOldPassword;
++ CK_ULONG ulOldPublicDataLen;
++ CK_BYTE_PTR pOldPublicData;
++ CK_ULONG ulOldRandomLen;
++ CK_BYTE_PTR pOldRandomA;
++ CK_ULONG ulNewPasswordLen;
++ CK_BYTE_PTR pNewPassword;
++ CK_ULONG ulNewPublicDataLen;
++ CK_BYTE_PTR pNewPublicData;
++ CK_ULONG ulNewRandomLen;
++ CK_BYTE_PTR pNewRandomA;
++} CK_SKIPJACK_RELAYX_PARAMS;
++
++typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
++ CK_SKIPJACK_RELAYX_PARAMS_PTR;
++
++
++typedef struct CK_PBE_PARAMS {
++ CK_BYTE_PTR pInitVector;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pSalt;
++ CK_ULONG ulSaltLen;
++ CK_ULONG ulIteration;
++} CK_PBE_PARAMS;
++
++typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
++
++
++/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
++ * CKM_KEY_WRAP_SET_OAEP mechanism */
++/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
++typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
++ CK_BYTE bBC; /* block contents byte */
++ CK_BYTE_PTR pX; /* extra data */
++ CK_ULONG ulXLen; /* length of extra data in bytes */
++} CK_KEY_WRAP_SET_OAEP_PARAMS;
++
++typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
++ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_SSL3_RANDOM_DATA;
++
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_VERSION_PTR pVersion;
++} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hClientMacSecret;
++ CK_OBJECT_HANDLE hServerMacSecret;
++ CK_OBJECT_HANDLE hClientKey;
++ CK_OBJECT_HANDLE hServerKey;
++ CK_BYTE_PTR pIVClient;
++ CK_BYTE_PTR pIVServer;
++} CK_SSL3_KEY_MAT_OUT;
++
++typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_PARAMS {
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_BBOOL bIsExport;
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_SSL3_KEY_MAT_PARAMS;
++
++typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
++
++/* CK_TLS_PRF_PARAMS is new for version 2.20 */
++typedef struct CK_TLS_PRF_PARAMS {
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_TLS_PRF_PARAMS;
++
++typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
++
++/* WTLS is new for version 2.20 */
++typedef struct CK_WTLS_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_WTLS_RANDOM_DATA;
++
++typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
++
++typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_BYTE_PTR pVersion;
++} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
++
++typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++typedef struct CK_WTLS_PRF_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_WTLS_PRF_PARAMS;
++
++typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hMacSecret;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pIV;
++} CK_WTLS_KEY_MAT_OUT;
++
++typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_ULONG ulSequenceNumber;
++ CK_BBOOL bIsExport;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_WTLS_KEY_MAT_PARAMS;
++
++typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
++
++/* CMS is new for version 2.20 */
++typedef struct CK_CMS_SIG_PARAMS {
++ CK_OBJECT_HANDLE certificateHandle;
++ CK_MECHANISM_PTR pSigningMechanism;
++ CK_MECHANISM_PTR pDigestMechanism;
++ CK_UTF8CHAR_PTR pContentType;
++ CK_BYTE_PTR pRequestedAttributes;
++ CK_ULONG ulRequestedAttributesLen;
++ CK_BYTE_PTR pRequiredAttributes;
++ CK_ULONG ulRequiredAttributesLen;
++} CK_CMS_SIG_PARAMS;
++
++typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
++
++typedef struct CK_KEY_DERIVATION_STRING_DATA {
++ CK_BYTE_PTR pData;
++ CK_ULONG ulLen;
++} CK_KEY_DERIVATION_STRING_DATA;
++
++typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
++ CK_KEY_DERIVATION_STRING_DATA_PTR;
++
++
++/* The CK_EXTRACT_PARAMS is used for the
++ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
++ * of the base key should be used as the first bit of the
++ * derived key */
++/* CK_EXTRACT_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_EXTRACT_PARAMS;
++
++typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
++
++/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
++ * indicate the Pseudo-Random Function (PRF) used to generate
++ * key bits using PKCS #5 PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
++
++typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
++
++/* The following PRFs are defined in PKCS #5 v2.0. */
++#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
++
++
++/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
++ * source of the salt value when deriving a key using PKCS #5
++ * PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
++
++typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
++
++/* The following salt value sources are defined in PKCS #5 v2.0. */
++#define CKZ_SALT_SPECIFIED 0x00000001
++
++/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
++ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
++ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
++typedef struct CK_PKCS5_PBKD2_PARAMS {
++ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ CK_VOID_PTR pSaltSourceData;
++ CK_ULONG ulSaltSourceDataLen;
++ CK_ULONG iterations;
++ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ CK_VOID_PTR pPrfData;
++ CK_ULONG ulPrfDataLen;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG_PTR ulPasswordLen;
++} CK_PKCS5_PBKD2_PARAMS;
++
++typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
++
++/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */
++
++typedef CK_ULONG CK_OTP_PARAM_TYPE;
++typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */
++
++typedef struct CK_OTP_PARAM {
++ CK_OTP_PARAM_TYPE type;
++ CK_VOID_PTR pValue;
++ CK_ULONG ulValueLen;
++} CK_OTP_PARAM;
++
++typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
++
++typedef struct CK_OTP_PARAMS {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_PARAMS;
++
++typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
++
++typedef struct CK_OTP_SIGNATURE_INFO {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_SIGNATURE_INFO;
++
++typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CK_OTP_VALUE 0
++#define CK_OTP_PIN 1
++#define CK_OTP_CHALLENGE 2
++#define CK_OTP_TIME 3
++#define CK_OTP_COUNTER 4
++#define CK_OTP_FLAGS 5
++#define CK_OTP_OUTPUT_LENGTH 6
++#define CK_OTP_OUTPUT_FORMAT 7
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CKF_NEXT_OTP 0x00000001
++#define CKF_EXCLUDE_TIME 0x00000002
++#define CKF_EXCLUDE_COUNTER 0x00000004
++#define CKF_EXCLUDE_CHALLENGE 0x00000008
++#define CKF_EXCLUDE_PIN 0x00000010
++#define CKF_USER_FRIENDLY_OTP 0x00000020
++
++/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */
++typedef struct CK_KIP_PARAMS {
++ CK_MECHANISM_PTR pMechanism;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++} CK_KIP_PARAMS;
++
++typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
++
++/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_AES_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_AES_CTR_PARAMS;
++
++typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_CAMELLIA_CTR_PARAMS;
++
++typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++#endif
+Index: openssl/util/libeay.num
+diff -u openssl/util/libeay.num:1.7.6.1.4.1.2.1.4.1 openssl/util/libeay.num:1.7.2.3
+--- openssl/util/libeay.num:1.7.6.1.4.1.2.1.4.1 Wed Mar 4 13:46:38 2015
++++ openssl/util/libeay.num Wed Mar 4 13:57:56 2015
+@@ -3731,4 +3731,6 @@
+ pqueue_size 4114 EXIST::FUNCTION:
+ OPENSSL_uni2asc 4115 EXIST:NETWARE:FUNCTION:
+ OPENSSL_asc2uni 4116 EXIST:NETWARE:FUNCTION:
++ENGINE_load_pk11ca 4117 EXIST::FUNCTION:HW_PKCS11CA,ENGINE
++ENGINE_load_pk11so 4117 EXIST::FUNCTION:HW_PKCS11SO,ENGINE
+ ASN1_TYPE_cmp 4428 EXIST::FUNCTION:
+Index: openssl/util/mk1mf.pl
+diff -u openssl/util/mk1mf.pl:1.8.6.1.10.1 openssl/util/mk1mf.pl:1.8.2.1
+--- openssl/util/mk1mf.pl:1.8.6.1.10.1 Wed Mar 4 13:46:38 2015
++++ openssl/util/mk1mf.pl Wed Mar 4 13:57:57 2015
+@@ -87,6 +87,8 @@
+ no-ecdh - No ECDH
+ no-engine - No engine
+ no-hw - No hw
++ no-hw-pkcs11ca - No hw PKCS#11 CA flavor
++ no-hw-pkcs11so - No hw PKCS#11 SO flavor
+ nasm - Use NASM for x86 asm
+ nw-nasm - Use NASM x86 asm for NetWare
+ nw-mwasm - Use Metrowerks x86 asm for NetWare
+@@ -242,6 +244,8 @@
+ $cflags.=" -DOPENSSL_NO_ECDH" if $no_ecdh;
+ $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine;
+ $cflags.=" -DOPENSSL_NO_HW" if $no_hw;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so;
+ $cflags.=" -DOPENSSL_FIPS" if $fips;
+ $cflags.= " -DZLIB" if $zlib_opt;
+ $cflags.= " -DZLIB_SHARED" if $zlib_opt == 2;
+@@ -316,6 +320,9 @@
+ $dir=$val;
+ }
+
++ if ($key eq "PK11_LIB_LOCATION")
++ { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";}
++
+ if ($key eq "KRB5_INCLUDES")
+ { $cflags .= " $val";}
+
+@@ -1295,6 +1302,8 @@
+ "no-ecdh" => \$no_ecdh,
+ "no-engine" => \$no_engine,
+ "no-hw" => \$no_hw,
++ "no-hw-pkcs11ca" => \$no_hw_pkcs11ca,
++ "no-hw-pkcs11so" => \$no_hw_pkcs11so,
+ "just-ssl" =>
+ [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast,
+ \$no_md2, \$no_sha, \$no_mdc2, \$no_dsa, \$no_dh,
+Index: openssl/util/mkdef.pl
+diff -u openssl/util/mkdef.pl:1.6.6.1 openssl/util/mkdef.pl:1.6
+--- openssl/util/mkdef.pl:1.6.6.1 Sun Jan 15 15:45:40 2012
++++ openssl/util/mkdef.pl Mon Jun 13 14:25:25 2011
+@@ -93,7 +93,7 @@
+ # External "algorithms"
+ "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM",
+ # Engines
+- "STATIC_ENGINE", "ENGINE", "HW", "GMP",
++ "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO",
+ # RFC3779 support
+ "RFC3779",
+ # TLS extension support
+@@ -122,6 +122,7 @@
+ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
+ my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
+ my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw; my $no_camellia;
++my $no_pkcs11ca; my $no_pkcs11so;
+ my $no_seed;
+ my $no_fp_api; my $no_static_engine; my $no_gmp; my $no_deprecated;
+ my $no_rfc3779; my $no_tlsext; my $no_cms; my $no_capieng; my $no_jpake;
+@@ -214,6 +215,8 @@
+ elsif (/^no-cms$/) { $no_cms=1; }
+ elsif (/^no-capieng$/) { $no_capieng=1; }
+ elsif (/^no-jpake$/) { $no_jpake=1; }
++ elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; }
++ elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; }
+ }
+
+
+@@ -1155,6 +1158,8 @@
+ if ($keyword eq "KRB5" && $no_krb5) { return 0; }
+ if ($keyword eq "ENGINE" && $no_engine) { return 0; }
+ if ($keyword eq "HW" && $no_hw) { return 0; }
++ if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; }
++ if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; }
+ if ($keyword eq "FP_API" && $no_fp_api) { return 0; }
+ if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; }
+ if ($keyword eq "GMP" && $no_gmp) { return 0; }
+Index: openssl/util/pl/VC-32.pl
+diff -u openssl/util/pl/VC-32.pl:1.6.6.1.2.1.4.1 openssl/util/pl/VC-32.pl:1.6.2.2
+--- openssl/util/pl/VC-32.pl:1.6.6.1.2.1.4.1 Thu Jul 3 12:12:38 2014
++++ openssl/util/pl/VC-32.pl Thu Jul 3 12:32:04 2014
+@@ -52,7 +52,7 @@
+ my $f = $shlib || $fips ?' /MD':' /MT';
+ $lib_cflag='/Zl' if (!$shlib); # remove /DEFAULTLIBs from static lib
+ $opt_cflags=$f.' /Ox';
+- $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG';
++ $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG';
+ $lflags="/nologo /subsystem:console /opt:ref";
+ }
+ elsif ($FLAVOR =~ /CE/)
diff --git a/bin/pkcs11/openssl-1.0.0t-patch b/bin/pkcs11/openssl-1.0.0t-patch
new file mode 100644
index 0000000..03465fe
--- /dev/null
+++ b/bin/pkcs11/openssl-1.0.0t-patch
@@ -0,0 +1,15889 @@
+Index: openssl/Configure
+diff -u openssl/Configure:1.9.2.1.2.1.4.1.2.1 openssl/Configure:1.11.2.2
+--- openssl/Configure:1.9.2.1.2.1.4.1.2.1 Tue Jan 7 09:25:41 2014
++++ openssl/Configure Tue Jan 7 09:28:47 2014
+@@ -10,7 +10,7 @@
+
+ # see INSTALL for instructions.
+
+-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
++my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+
+ # Options:
+ #
+@@ -23,6 +23,12 @@
+ # default). This needn't be set in advance, you can
+ # just as well use "make INSTALL_PREFIX=/whatever install".
+ #
++# --pk11-libname PKCS#11 library name.
++# (No default)
++#
++# --pk11-flavor either crypto-accelerator or sign-only
++# (No default)
++#
+ # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected
+ # to live in the subdirectory lib/ and the header files in
+ # include/. A value is required.
+@@ -344,7 +350,7 @@
+ "linux-armv4", "gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ #### IA-32 targets...
+ "linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out",
+ ####
+ "linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+@@ -352,7 +358,7 @@
+ "linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ "linux-s390x", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ #### SPARC Linux setups
+ # Ray Miller <ray.miller@computing-services.oxford.ac.uk> has patiently
+@@ -623,6 +629,10 @@
+ my $idx_arflags = $idx++;
+ my $idx_multilib = $idx++;
+
++# PKCS#11 engine patch
++my $pk11_libname="";
++my $pk11_flavor="";
++
+ my $prefix="";
+ my $libdir="";
+ my $openssldir="";
+@@ -825,6 +835,14 @@
+ {
+ $flags.=$_." ";
+ }
++ elsif (/^--pk11-libname=(.*)$/)
++ {
++ $pk11_libname=$1;
++ }
++ elsif (/^--pk11-flavor=(.*)$/)
++ {
++ $pk11_flavor=$1;
++ }
+ elsif (/^--prefix=(.*)$/)
+ {
+ $prefix=$1;
+@@ -962,6 +980,22 @@
+ exit 0;
+ }
+
++if (! $pk11_libname)
++ {
++ print STDERR "You must set --pk11-libname for PKCS#11 library.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
++if (! $pk11_flavor
++ || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only"))
++ {
++ print STDERR "You must set --pk11-flavor.\n";
++ print STDERR "Choices are crypto-accelerator and sign-only.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
+ if ($target =~ m/^CygWin32(-.*)$/) {
+ $target = "Cygwin".$1;
+ }
+@@ -1039,6 +1073,25 @@
+ $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO";
+ }
+
++if ($pk11_flavor eq "crypto-accelerator")
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $options .= " no-hw-pkcs11so";
++ print " no-hw-pkcs11so [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11SO\n";
++ }
++else
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $options .= " no-hw-pkcs11ca";
++ print " no-hw-pkcs11ca [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11CA\n";
++}
++
+ my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds;
+
+ $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target =~ /^mingw/);
+@@ -1126,6 +1179,8 @@
+ if ($flags ne "") { $cflags="$flags$cflags"; }
+ else { $no_user_cflags=1; }
+
++$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags";
++
+ # Kerberos settings. The flavor must be provided from outside, either through
+ # the script "config" or manually.
+ if (!$no_krb5)
+@@ -1495,6 +1550,7 @@
+ s/^VERSION=.*/VERSION=$version/;
+ s/^MAJOR=.*/MAJOR=$major/;
+ s/^MINOR=.*/MINOR=$minor/;
++ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/;
+ s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/;
+ s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/;
+ s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/;
+Index: openssl/Makefile.org
+diff -u openssl/Makefile.org:1.5.2.1.2.1.14.1 openssl/Makefile.org:1.6.2.1
+--- openssl/Makefile.org:1.5.2.1.2.1.14.1 Wed Dec 23 17:25:07 2015
++++ openssl/Makefile.org Wed Dec 23 17:43:50 2015
+@@ -26,6 +26,9 @@
+ INSTALL_PREFIX=
+ INSTALLTOP=/usr/local/ssl
+
++# You must set this through --pk11-libname configure option.
++PK11_LIB_LOCATION=
++
+ # Do not edit this manually. Use Configure --openssldir=DIR do change this!
+ OPENSSLDIR=/usr/local/ssl
+
+Index: openssl/README.pkcs11
+diff -u /dev/null openssl/README.pkcs11:1.7.4.1
+--- /dev/null Wed Dec 23 17:47:10 2015
++++ openssl/README.pkcs11 Fri Oct 4 14:33:56 2013
+@@ -0,0 +1,266 @@
++ISC modified
++============
++
++The previous key naming scheme was kept for backward compatibility.
++
++The PKCS#11 engine exists in two flavors, crypto-accelerator and
++sign-only. The first one is from the Solaris patch and uses the
++PKCS#11 device for all crypto operations it supports. The second
++is a stripped down version which provides only the useful
++function (i.e., signature with a RSA private key in the device
++protected key store and key loading).
++
++As a hint PKCS#11 boards should use the crypto-accelerator flavor,
++external PKCS#11 devices the sign-only. SCA 6000 is an example
++of the first, AEP Keyper of the second.
++
++Note it is mandatory to set a pk11-flavor (and only one) in
++config/Configure.
++
++It is highly recommended to compile in (vs. as a DSO) the engine.
++The way to configure this is system dependent, on Unixes it is no-shared
++(and is in general the default), on WIN32 it is enable-static-engine
++(and still enable to build the OpenSSL libraries as DLLs).
++
++PKCS#11 engine support for OpenSSL 0.9.8l
++=========================================
++
++[Nov 19, 2009]
++
++Contents:
++
++Overview
++Revisions of the patch for 0.9.8 branch
++FAQs
++Feedback
++
++Overview
++========
++
++This patch containing code available in OpenSolaris adds support for PKCS#11
++engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against
++OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system
++must provide PKCS#11 backend otherwise the patch is useless. You provide the
++PKCS#11 library name during the build configuration phase, see below.
++
++Patch can be applied like this:
++
++ # NOTE: use gtar if on Solaris
++ tar xfzv openssl-0.9.8l.tar.gz
++ # now download the patch to the current directory
++ # ...
++ cd openssl-0.9.8l
++ # NOTE: must use gpatch if on Solaris (is part of the system)
++ patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19
++
++It is designed to support pure acceleration for RSA, DSA, DH and all the
++symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share
++except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA.
++
++According to the PKCS#11 providers installed on your machine, it can support
++following mechanisms:
++
++ RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4,
++ AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB,
++ AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224,
++ SHA256, SHA384, SHA512
++
++Note that for AES counter mode the application must provide their own EVP
++functions since OpenSSL doesn't support counter mode through EVP yet. You may
++see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an
++example of code that uses the PKCS#11 engine and deals with the fork-safety
++problem (see engine.c and packet.c files if interested).
++
++You must provide the location of PKCS#11 library in your system to the
++configure script. You will be instructed to do that when you try to run the
++config script:
++
++ $ ./config
++ Operating system: i86pc-whatever-solaris2
++ Configuring for solaris-x86-cc
++ You must set --pk11-libname for PKCS#11 library.
++ See README.pkcs11 for more information.
++
++Taking openCryptoki project on Linux AMD64 box as an example, you would run
++configure script like this:
++
++ ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so
++
++To check whether newly built openssl really supports PKCS#11 it's enough to run
++"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the
++output. If you see no PKCS#11 engine support check that the built openssl binary
++and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits.
++
++The patch, during various phases of development, was tested on Solaris against
++PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and
++OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project
++(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more
++information). Some Linux distributions even ship those libraries with the
++system. The patch should work on any system that is supported by OpenSSL itself
++and has functional PKCS#11 library.
++
++The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are
++copyrighted by RSA Security Inc., see pkcs11.h for more information.
++
++Other added/modified code in this patch is copyrighted by Sun Microsystems,
++Inc. and is released under the OpenSSL license (see LICENSE file for more
++information).
++
++Revisions of the patch for 0.9.8 branch
++=======================================
++
++2009-11-19
++- adjusted for OpenSSL version 0.9.8l
++
++- bugs and RFEs:
++
++ 6479874 OpenSSL should support RSA key by reference/hardware keystores
++ 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split
++ 6732677 make check to trigger Solaris specific code automatic in the
++ PKCS#11 engine
++
++2009-03-11
++- adjusted for OpenSSL version 0.9.8j
++
++- README.pkcs11 moved out of the patch, and is shipped together with it in a
++ tarball instead so that it can be read before the patch is applied.
++
++- fixed bugs:
++
++ 6804216 pkcs#11 engine should support a key length range for RC4
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-12-02
++- fixed bugs and RFEs (most of the work done by Vladimir Kotal)
++
++ 6723504 more granular locking in PKCS#11 engine
++ 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true
++ 6710420 PKCS#11 engine source should be lint clean
++ 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take
++ it seriously
++ 6746712 PKCS#11 engine source code should be cstyle clean
++ 6731380 return codes of several functions are not checked in the PKCS#11
++ engine code
++ 6746735 PKCS#11 engine should use extended FILE space API
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-08-01
++- fixed bug
++
++ 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers
++ and digests
++
++- Solaris specific code for slot selection made automatic
++
++2008-07-29
++- update the patch to OpenSSL 0.9.8h version
++- pkcs11t.h updated to the latest version:
++
++ 6545665 make CKM_AES_CTR available to non-kernel users
++
++- fixed bugs in the engine code:
++
++ 6602801 PK11_SESSION cache has to employ reference counting scheme for
++ asymmetric key operations
++ 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called
++ atomically
++ 6607307 pkcs#11 engine can't read RSA private keys
++ 6652362 pk11_RSA_finish() is cutting corners
++ 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in
++ suboptimal way
++ 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more
++ resilient to destroy failures
++ 6667273 OpenSSL engine should not use free() but OPENSSL_free()
++ 6670363 PKCS#11 engine fails to reuse existing symmetric keys
++ 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine
++ 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size
++ of big numbers leading to failures
++ 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of
++ -1
++ 6706622 pk11_load_{pub,priv}key create corrupted RSA key references
++ 6707129 return values from BN_new() in pk11_DH_generate_key() are not
++ checked
++ 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to
++ structure reuse
++ 6707782 OpenSSL PKCS#11 engine pretends to be aware of
++ OPENSSL_NO_{RSA,DSA,DH}
++ defines but fails miserably
++ 6709966 make check_new_*() to return values to indicate cache hit/miss
++ 6705200 pk11_dh struct initialization in PKCS#11 engine is missing
++ generate_params parameter
++ 6709513 PKCS#11 engine sets IV length even for ECB modes
++ 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the
++ PKCS#11 engine
++ 6728871 PKCS#11 engine must reset global_session in pk11_finish()
++
++- new features and enhancements:
++
++ 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512
++ 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes
++ 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric
++ ciphers and digests
++
++2007-10-15
++- update for 0.9.8f version
++- update for "6607670 teach pkcs#11 engine how to use keys be reference"
++
++2007-10-02
++- draft for "6607670 teach pkcs#11 engine how to use keys be reference"
++- draft for "6607307 pkcs#11 engine can't read RSA private keys"
++
++2007-09-26
++- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes
++ significant performance drop
++- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine
++
++2007-05-25
++- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers
++
++2007-05-19
++- initial patch for 0.9.8e using latest OpenSolaris code
++
++FAQs
++====
++
++(1) my build failed on Linux distro with this error:
++
++../libcrypto.a(hw_pk11.o): In function `pk11_library_init':
++hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork'
++
++Answer:
++
++ - don't use "no-threads" when configuring
++ - if you didn't then OpenSSL failed to create a threaded library by
++ default. You may manually edit Configure and try again. Look for the
++ architecture that Configure printed, for example:
++
++Configured for linux-elf.
++
++ - then edit Configure, find string "linux-elf" (inluding the quotes),
++ and add flags to support threads to the 4th column of the 2nd string.
++ If you build with GCC then adding "-pthread" should be enough. With
++ "linux-elf" as an example, you would add " -pthread" right after
++ "-D_REENTRANT", like this:
++
++....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:.....
++
++(2) I'm using MinGW/MSYS environment and get undeclared reference error for
++pthread_atfork() function when trying to build OpenSSL with the patch.
++
++Answer:
++
++ Sorry, pthread_atfork() is not implemented in the current pthread-win32
++ (as of Nov 2009). You can not use the patch there.
++
++
++Feedback
++========
++
++Please send feedback to security-discuss@opensolaris.org. The patch was
++created by Jan.Pechanec@Sun.COM from code available in OpenSolaris.
++
++Latest version should be always available on http://blogs.sun.com/janp.
++
+Index: openssl/crypto/opensslconf.h
+diff -u openssl/crypto/opensslconf.h:1.6.2.1.16.1 openssl/crypto/opensslconf.h:1.6.4.1
+--- openssl/crypto/opensslconf.h:1.6.2.1.16.1 Wed Dec 23 17:25:17 2015
++++ openssl/crypto/opensslconf.h Wed Dec 23 17:44:01 2015
+@@ -29,6 +29,9 @@
+
+ #endif /* OPENSSL_DOING_MAKEDEPEND */
+
++#ifndef OPENSSL_THREADS
++# define OPENSSL_THREADS
++#endif
+ #ifndef OPENSSL_NO_DYNAMIC_ENGINE
+ # define OPENSSL_NO_DYNAMIC_ENGINE
+ #endif
+@@ -61,6 +64,8 @@
+ # endif
+ #endif
+
++#define OPENSSL_CPUID_OBJ
++
+ /* crypto/opensslconf.h.in */
+
+ /* Generate 80386 code? */
+@@ -107,7 +112,7 @@
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+-#undef RC4_CHUNK
++#define RC4_CHUNK unsigned long
+ #endif
+ #endif
+
+@@ -115,7 +120,7 @@
+ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+ #ifndef DES_LONG
+-#define DES_LONG unsigned long
++#define DES_LONG unsigned int
+ #endif
+ #endif
+
+@@ -126,9 +131,9 @@
+ /* Should we define BN_DIV2W here? */
+
+ /* Only one for the following should be defined */
+-#undef SIXTY_FOUR_BIT_LONG
++#define SIXTY_FOUR_BIT_LONG
+ #undef SIXTY_FOUR_BIT
+-#define THIRTY_TWO_BIT
++#undef THIRTY_TWO_BIT
+ #endif
+
+ #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+@@ -140,7 +145,7 @@
+
+ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+ #define CONFIG_HEADER_BF_LOCL_H
+-#undef BF_PTR
++#define BF_PTR2
+ #endif /* HEADER_BF_LOCL_H */
+
+ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+@@ -170,7 +175,7 @@
+ /* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+ #ifndef DES_UNROLL
+-#undef DES_UNROLL
++#define DES_UNROLL
+ #endif
+
+ /* These default values were supplied by
+Index: openssl/crypto/bio/bss_file.c
+diff -u openssl/crypto/bio/bss_file.c:1.6.2.1.30.1 openssl/crypto/bio/bss_file.c:1.6.4.1
+--- openssl/crypto/bio/bss_file.c:1.6.2.1.30.1 Wed Dec 23 17:25:30 2015
++++ openssl/crypto/bio/bss_file.c Wed Dec 23 17:44:14 2015
+@@ -167,7 +167,7 @@
+ if (file == NULL) {
+ SYSerr(SYS_F_FOPEN, get_last_sys_error());
+ ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
+- if (errno == ENOENT)
++ if ((errno == ENOENT) || ((*mode == 'r') && (errno == EACCES)))
+ BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
+ else
+ BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
+Index: openssl/crypto/engine/Makefile
+diff -u openssl/crypto/engine/Makefile:1.8.2.1.16.1 openssl/crypto/engine/Makefile:1.8.4.1
+--- openssl/crypto/engine/Makefile:1.8.2.1.16.1 Wed Dec 23 17:25:54 2015
++++ openssl/crypto/engine/Makefile Wed Dec 23 17:44:39 2015
+@@ -21,12 +21,14 @@
+ eng_table.c eng_pkey.c eng_fat.c eng_all.c \
+ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \
+ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \
+- eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c
++ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \
++ hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c
+ LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
+ eng_table.o eng_pkey.o eng_fat.o eng_all.o \
+ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \
+ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \
+- eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o
++ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \
++ hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o
+
+ SRC= $(LIBSRC)
+
+@@ -266,6 +268,83 @@
+ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+ eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+ eng_table.o: eng_table.c
++hw_pk11.o: ../../e_os.h ../../include/openssl/aes.h
++hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
++hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h
++hw_pk11.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h
++hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
++hw_pk11.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
++hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/err.h
++hw_pk11.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
++hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/obj_mac.h
++hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
++hw_pk11.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
++hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
++hw_pk11.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
++hw_pk11.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
++hw_pk11.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
++hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
++hw_pk11.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h hw_pk11.c
++hw_pk11.o: hw_pk11_err.c hw_pk11_err.h hw_pk11ca.h pkcs11.h pkcs11f.h pkcs11t.h
++hw_pk11_pub.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
++hw_pk11_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
++hw_pk11_pub.o: ../../include/openssl/objects.h
++hw_pk11_pub.o: ../../include/openssl/opensslconf.h
++hw_pk11_pub.o: ../../include/openssl/opensslv.h
++hw_pk11_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
++hw_pk11_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
++hw_pk11_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
++hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
++hw_pk11_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
++hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
++hw_pk11_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11_pub.c hw_pk11ca.h
++hw_pk11_pub.o: pkcs11.h pkcs11f.h pkcs11t.h
++hw_pk11so.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11so.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11so.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11so.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11so.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11so.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11so.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/md5.h
++hw_pk11so.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
++hw_pk11so.o: ../../include/openssl/opensslconf.h
++hw_pk11so.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
++hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
++hw_pk11so.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
++hw_pk11so.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
++hw_pk11so.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
++hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
++hw_pk11so.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h
++hw_pk11so.o: hw_pk11_err.c hw_pk11_err.h hw_pk11so.c hw_pk11so.h pkcs11.h
++hw_pk11so.o: pkcs11f.h pkcs11t.h
++hw_pk11so_pub.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11so_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11so_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11so_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11so_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11so_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11so_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
++hw_pk11so_pub.o: ../../include/openssl/objects.h
++hw_pk11so_pub.o: ../../include/openssl/opensslconf.h
++hw_pk11so_pub.o: ../../include/openssl/opensslv.h
++hw_pk11so_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
++hw_pk11so_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
++hw_pk11so_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
++hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
++hw_pk11so_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
++hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
++hw_pk11so_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11so.h
++hw_pk11so_pub.o: hw_pk11so_pub.c pkcs11.h pkcs11f.h pkcs11t.h
+ tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h
+ tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+ tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+Index: openssl/crypto/engine/cryptoki.h
+diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008
+@@ -0,0 +1,103 @@
++/*
++ * CDDL HEADER START
++ *
++ * The contents of this file are subject to the terms of the
++ * Common Development and Distribution License, Version 1.0 only
++ * (the "License"). You may not use this file except in compliance
++ * with the License.
++ *
++ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
++ * or http://www.opensolaris.org/os/licensing.
++ * See the License for the specific language governing permissions
++ * and limitations under the License.
++ *
++ * When distributing Covered Code, include this CDDL HEADER in each
++ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
++ * If applicable, add the following below this CDDL HEADER, with the
++ * fields enclosed by brackets "[]" replaced with your own identifying
++ * information: Portions Copyright [yyyy] [name of copyright owner]
++ *
++ * CDDL HEADER END
++ */
++/*
++ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _CRYPTOKI_H
++#define _CRYPTOKI_H
++
++/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef CK_PTR
++#define CK_PTR *
++#endif
++
++#ifndef CK_DEFINE_FUNCTION
++#define CK_DEFINE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION
++#define CK_DECLARE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION_POINTER
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
++#endif
++
++#ifndef CK_CALLBACK_FUNCTION
++#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
++#endif
++
++#ifndef NULL_PTR
++#include <unistd.h> /* For NULL */
++#define NULL_PTR NULL
++#endif
++
++/*
++ * pkcs11t.h defines TRUE and FALSE in a way that upsets lint
++ */
++#ifndef CK_DISABLE_TRUE_FALSE
++#define CK_DISABLE_TRUE_FALSE
++#ifndef TRUE
++#define TRUE 1
++#endif /* TRUE */
++#ifndef FALSE
++#define FALSE 0
++#endif /* FALSE */
++#endif /* CK_DISABLE_TRUE_FALSE */
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++#include "pkcs11.h"
++
++/* Solaris specific functions */
++
++#include <stdlib.h>
++
++/*
++ * SUNW_C_GetMechSession will initialize the framework and do all
++ * the necessary PKCS#11 calls to create a session capable of
++ * providing operations on the requested mechanism
++ */
++CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech,
++ CK_SESSION_HANDLE_PTR hSession);
++
++/*
++ * SUNW_C_KeyToObject will create a secret key object for the given
++ * mechanism from the rawkey data.
++ */
++CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len,
++ CK_OBJECT_HANDLE_PTR obj);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _CRYPTOKI_H */
+Index: openssl/crypto/engine/eng_all.c
+diff -u openssl/crypto/engine/eng_all.c:1.5.2.1.16.1 openssl/crypto/engine/eng_all.c:1.5.4.1
+--- openssl/crypto/engine/eng_all.c:1.5.2.1.16.1 Wed Dec 23 17:25:54 2015
++++ openssl/crypto/engine/eng_all.c Wed Dec 23 17:44:39 2015
+@@ -114,6 +114,14 @@
+ # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
+ ENGINE_load_capi();
+ # endif
++# ifndef OPENSSL_NO_HW_PKCS11
++# ifndef OPENSSL_NO_HW_PKCS11CA
++ ENGINE_load_pk11ca();
++# endif
++# ifndef OPENSSL_NO_HW_PKCS11SO
++ ENGINE_load_pk11so();
++# endif
++# endif
+ #endif
+ }
+
+Index: openssl/crypto/engine/engine.h
+diff -u openssl/crypto/engine/engine.h:1.5.2.1.16.1 openssl/crypto/engine/engine.h:1.5.4.1
+--- openssl/crypto/engine/engine.h:1.5.2.1.16.1 Wed Dec 23 17:25:55 2015
++++ openssl/crypto/engine/engine.h Wed Dec 23 17:44:40 2015
+@@ -406,6 +406,12 @@
+ # endif
+ void ENGINE_load_cryptodev(void);
+ void ENGINE_load_builtin_engines(void);
++# ifndef OPENSSL_NO_HW_PKCS11CA
++void ENGINE_load_pk11ca(void);
++# endif
++# ifndef OPENSSL_NO_HW_PKCS11SO
++void ENGINE_load_pk11so(void);
++# endif
+
+ /*
+ * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+Index: openssl/crypto/engine/hw_pk11.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.30.4.2
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:33:56 2013
+@@ -0,0 +1,4116 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++#include <openssl/aes.h>
++#include <openssl/des.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/* #undef DEBUG_SLOT_SELECTION */
++/*
++ * Solaris specific code. See comment at check_hw_mechanisms() for more
++ * information.
++ */
++#if defined(__SVR4) && defined(__sun)
++#undef SOLARIS_HW_SLOT_SELECTION
++#endif
++
++/*
++ * AES counter mode is not supported in the OpenSSL EVP API yet and neither
++ * there are official OIDs for mechanisms based on this mode. With our changes,
++ * an application can define its own EVP calls for AES counter mode and then
++ * it can make use of hardware acceleration through this engine. However, it's
++ * better if we keep AES CTR support code under ifdef's.
++ */
++#define SOLARIS_AES_CTR
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.c"
++
++#ifdef SOLARIS_AES_CTR
++/*
++ * NIDs for AES counter mode that will be defined during the engine
++ * initialization.
++ */
++static int NID_aes_128_ctr = NID_undef;
++static int NID_aes_192_ctr = NID_undef;
++static int NID_aes_256_ctr = NID_undef;
++#endif /* SOLARIS_AES_CTR */
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel
++ * library. See comment at check_hw_mechanisms() for more information.
++ */
++static int *hw_cnids;
++static int *hw_dnids;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++#ifndef OPENSSL_NO_RSA
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DSA
++int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DH
++int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock);
++#endif
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++/* Symmetric cipher and digest support functions */
++static int cipher_nid_to_pk11(int nid);
++#ifdef SOLARIS_AES_CTR
++static int pk11_add_NID(char *sn, char *ln);
++static int pk11_add_aes_ctr_NIDs(void);
++#endif /* SOLARIS_AES_CTR */
++static int pk11_usable_ciphers(const int **nids);
++static int pk11_usable_digests(const int **nids);
++static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc);
++static int pk11_cipher_final(PK11_SESSION *sp);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl);
++#else
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl);
++#endif
++static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx);
++static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid);
++static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid);
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp);
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len);
++static int md_nid_to_pk11(int nid);
++static int pk11_digest_init(EVP_MD_CTX *ctx);
++static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data,
++ size_t count);
++static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md);
++static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
++static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
++
++static int pk11_choose_slots(int *any_slot_found);
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher,
++ int *local_cipher_nids);
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest,
++ int *local_digest_nids);
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids,
++ int id);
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++static int check_hw_mechanisms(void);
++static int nid_in_table(int nid, int *nid_table);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* Index for the supported ciphers */
++enum pk11_cipher_id {
++ PK11_DES_CBC,
++ PK11_DES3_CBC,
++ PK11_DES_ECB,
++ PK11_DES3_ECB,
++ PK11_RC4,
++ PK11_AES_128_CBC,
++ PK11_AES_192_CBC,
++ PK11_AES_256_CBC,
++ PK11_AES_128_ECB,
++ PK11_AES_192_ECB,
++ PK11_AES_256_ECB,
++ PK11_BLOWFISH_CBC,
++#ifdef SOLARIS_AES_CTR
++ PK11_AES_128_CTR,
++ PK11_AES_192_CTR,
++ PK11_AES_256_CTR,
++#endif /* SOLARIS_AES_CTR */
++ PK11_CIPHER_MAX
++};
++
++/* Index for the supported digests */
++enum pk11_digest_id {
++ PK11_MD5,
++ PK11_SHA1,
++ PK11_SHA224,
++ PK11_SHA256,
++ PK11_SHA384,
++ PK11_SHA512,
++ PK11_DIGEST_MAX
++};
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static int cipher_nids[PK11_CIPHER_MAX];
++static int digest_nids[PK11_DIGEST_MAX];
++static int cipher_count = 0;
++static int digest_count = 0;
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_recover = CK_FALSE;
++static CK_BBOOL pk11_have_dsa = CK_FALSE;
++static CK_BBOOL pk11_have_dh = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++typedef struct PK11_CIPHER_st
++ {
++ enum pk11_cipher_id id;
++ int nid;
++ int iv_len;
++ int min_key_len;
++ int max_key_len;
++ CK_KEY_TYPE key_type;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_CIPHER;
++
++static PK11_CIPHER ciphers[] =
++ {
++ { PK11_DES_CBC, NID_des_cbc, 8, 8, 8,
++ CKK_DES, CKM_DES_CBC, },
++ { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24,
++ CKK_DES3, CKM_DES3_CBC, },
++ { PK11_DES_ECB, NID_des_ecb, 0, 8, 8,
++ CKK_DES, CKM_DES_ECB, },
++ { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24,
++ CKK_DES3, CKM_DES3_ECB, },
++ { PK11_RC4, NID_rc4, 0, 16, 256,
++ CKK_RC4, CKM_RC4, },
++ { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16,
++ CKK_BLOWFISH, CKM_BLOWFISH_CBC, },
++#ifdef SOLARIS_AES_CTR
++ /* we don't know the correct NIDs until the engine is initialized */
++ { PK11_AES_128_CTR, NID_undef, 16, 16, 16,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_192_CTR, NID_undef, 16, 24, 24,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_256_CTR, NID_undef, 16, 32, 32,
++ CKK_AES, CKM_AES_CTR, },
++#endif /* SOLARIS_AES_CTR */
++ };
++
++typedef struct PK11_DIGEST_st
++ {
++ enum pk11_digest_id id;
++ int nid;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_DIGEST;
++
++static PK11_DIGEST digests[] =
++ {
++ {PK11_MD5, NID_md5, CKM_MD5, },
++ {PK11_SHA1, NID_sha1, CKM_SHA_1, },
++ {PK11_SHA224, NID_sha224, CKM_SHA224, },
++ {PK11_SHA256, NID_sha256, CKM_SHA256, },
++ {PK11_SHA384, NID_sha384, CKM_SHA384, },
++ {PK11_SHA512, NID_sha512, CKM_SHA512, },
++ {0, NID_undef, 0xFFFF, },
++ };
++
++/*
++ * Structure to be used for the cipher_data/md_data in
++ * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11
++ * session in multiple cipher_update calls
++ */
++typedef struct PK11_CIPHER_STATE_st
++ {
++ PK11_SESSION *sp;
++ } PK11_CIPHER_STATE;
++
++
++/*
++ * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets
++ * called when libcrypto requests a cipher NID.
++ *
++ * Note how the PK11_CIPHER_STATE is used here.
++ */
++
++/* DES CBC EVP */
++static const EVP_CIPHER pk11_des_cbc =
++ {
++ NID_des_cbc,
++ 8, 8, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/* 3DES CBC EVP */
++static const EVP_CIPHER pk11_3des_cbc =
++ {
++ NID_des_ede3_cbc,
++ 8, 24, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and
++ * get_asn1_parameters fields are set to NULL.
++ */
++static const EVP_CIPHER pk11_des_ecb =
++ {
++ NID_des_ecb,
++ 8, 8, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_3des_ecb =
++ {
++ NID_des_ede3_ecb,
++ 8, 24, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++
++static const EVP_CIPHER pk11_aes_128_cbc =
++ {
++ NID_aes_128_cbc,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_cbc =
++ {
++ NID_aes_192_cbc,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_cbc =
++ {
++ NID_aes_256_cbc,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use IV so that's why set_asn1_parameters and
++ * get_asn1_parameters are set to NULL.
++ */
++static const EVP_CIPHER pk11_aes_128_ecb =
++ {
++ NID_aes_128_ecb,
++ 16, 16, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_ecb =
++ {
++ NID_aes_192_ecb,
++ 16, 24, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_ecb =
++ {
++ NID_aes_256_ecb,
++ 16, 32, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++#ifdef SOLARIS_AES_CTR
++/*
++ * NID_undef's will be changed to the AES counter mode NIDs as soon they are
++ * created in pk11_library_init(). Note that the need to change these structures
++ * is the reason why we don't define them with the const keyword.
++ */
++static EVP_CIPHER pk11_aes_128_ctr =
++ {
++ NID_undef,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static EVP_CIPHER pk11_aes_192_ctr =
++ {
++ NID_undef,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static EVP_CIPHER pk11_aes_256_ctr =
++ {
++ NID_undef,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++#endif /* SOLARIS_AES_CTR */
++
++static const EVP_CIPHER pk11_bf_cbc =
++ {
++ NID_bf_cbc,
++ 8, 16, 8,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_rc4 =
++ {
++ NID_rc4,
++ 1, 16, 0,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_MD pk11_md5 =
++ {
++ NID_md5,
++ NID_md5WithRSAEncryption,
++ MD5_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ MD5_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha1 =
++ {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha224 =
++ {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-224 uses the same cblock size as SHA-256 */
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha256 =
++ {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha384 =
++ {
++ NID_sha384,
++ NID_sha384WithRSAEncryption,
++ SHA384_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-384 uses the same cblock size as SHA-512 */
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha512 =
++ {
++ NID_sha512,
++ NID_sha512WithRSAEncryption,
++ SHA512_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11SO
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name =
++ "PKCS #11 engine support (crypto accelerator)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++#ifndef OPENSSL_NO_RSA
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DSA], &attr);
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DH] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DH], &attr);
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++#ifndef OPENSSL_NO_RSA
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (find_lock[OP_DSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DSA]);
++ OPENSSL_free(find_lock[OP_DSA]);
++ find_lock[OP_DSA] = NULL;
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (find_lock[OP_DH] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DH]);
++ OPENSSL_free(find_lock[OP_DH]);
++ find_lock[OP_DH] = NULL;
++ }
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++#ifndef OPENSSL_NO_RSA
++ const RSA_METHOD *rsa = NULL;
++ RSA_METHOD *pk11_rsa = PK11_RSA();
++#endif /* OPENSSL_NO_RSA */
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name) ||
++ !ENGINE_set_ciphers(e, pk11_engine_ciphers) ||
++ !ENGINE_set_digests(e, pk11_engine_digests))
++ return (0);
++#ifndef OPENSSL_NO_RSA
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (pk11_have_dsa == CK_TRUE)
++ {
++ if (!ENGINE_set_DSA(e, PK11_DSA()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (pk11_have_dh == CK_TRUE)
++ {
++ if (!ENGINE_set_DH(e, PK11_DH()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DH\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DH */
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++/*
++ * Apache calls OpenSSL function RSA_blinding_on() once during startup
++ * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp
++ * here, we wire it back to the OpenSSL software implementation.
++ * Since it is used only once, performance is not a concern.
++ */
++#ifndef OPENSSL_NO_RSA
++ rsa = RSA_PKCS1_SSLeay();
++ pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp;
++ pk11_rsa->bn_mod_exp = rsa->bn_mod_exp;
++ if (pk11_have_recover != CK_TRUE)
++ pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec;
++#endif /* OPENSSL_NO_RSA */
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ LOCK_OBJSTORE(OP_DSA);
++ LOCK_OBJSTORE(OP_DH);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ CK_ULONG ul_state_len;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++#ifdef SOLARIS_AES_CTR
++ /*
++ * We must do this before we start working with slots since we need all
++ * NIDs there.
++ */
++ if (pk11_add_aes_ctr_NIDs() == 0)
++ goto err;
++#endif /* SOLARIS_AES_CTR */
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ /*
++ * Disable digest if C_GetOperationState is not supported since
++ * this function is required by OpenSSL digest copy function
++ */
++ /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */
++ if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len)
++ != CKR_OK) {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: C_GetOperationState() not supported, "
++ "setting digest_count to 0\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ digest_count = 0;
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ break;
++#endif
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++#ifndef OPENSSL_NO_RSA
++ (void) pk11_destroy_rsa_key_objects(NULL);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ (void) pk11_destroy_dsa_key_objects(NULL);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ (void) pk11_destroy_dh_key_objects(NULL);
++#endif /* OPENSSL_NO_DH */
++ (void) pk11_destroy_cipher_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ case OP_DIGEST:
++ case OP_CIPHER:
++ myslot = SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ break;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ sp->opdata_dsa_pub_num = NULL;
++ sp->opdata_dsa_priv = NULL;
++ sp->opdata_dsa_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ sp->opdata_dh_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DH */
++ case OP_CIPHER:
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ sp->opdata_encrypt = -1;
++ break;
++ default:
++ break;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++/* Destroy DSA public key from single session. */
++int
++pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key,
++ ret, uselock, OP_DSA, CK_FALSE);
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy DSA private key from single session. */
++int
++pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key,
++ ret, uselock, OP_DSA, CK_TRUE);
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv = NULL;
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_dsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_dsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++/* Destroy DH key from single session. */
++int
++pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dh_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dh_key,
++ ret, uselock, OP_DH, CK_TRUE);
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DH key object wrapper.
++ *
++ * arg0: pointer to PKCS#11 engine session structure
++ * if session is NULL, try to destroy all objects in the free list
++ */
++int
++pk11_destroy_dh_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DH].head;
++ uselock = FALSE;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dh_object(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DH */
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/* Symmetric ciphers and digests support functions */
++
++static int
++cipher_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; i++)
++ if (ciphers[i].nid == nid)
++ return (ciphers[i].id);
++ return (-1);
++ }
++
++static int
++pk11_usable_ciphers(const int **nids)
++ {
++ if (cipher_count > 0)
++ *nids = cipher_nids;
++ else
++ *nids = NULL;
++ return (cipher_count);
++ }
++
++static int
++pk11_usable_digests(const int **nids)
++ {
++ if (digest_count > 0)
++ *nids = digest_nids;
++ else
++ *nids = NULL;
++ return (digest_count);
++ }
++
++/*
++ * Init context for encryption or decryption using a symmetric key.
++ */
++static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher,
++ PK11_SESSION *sp, CK_MECHANISM_PTR pmech)
++ {
++ CK_RV rv;
++#ifdef SOLARIS_AES_CTR
++ CK_AES_CTR_PARAMS ctr_params;
++#endif /* SOLARIS_AES_CTR */
++
++ /*
++ * We expect pmech->mechanism to be already set and
++ * pParameter/ulParameterLen initialized to NULL/0 before
++ * pk11_init_symetric() is called.
++ */
++ OPENSSL_assert(pmech->mechanism != 0);
++ OPENSSL_assert(pmech->pParameter == NULL);
++ OPENSSL_assert(pmech->ulParameterLen == 0);
++
++#ifdef SOLARIS_AES_CTR
++ if (ctx->cipher->nid == NID_aes_128_ctr ||
++ ctx->cipher->nid == NID_aes_192_ctr ||
++ ctx->cipher->nid == NID_aes_256_ctr)
++ {
++ pmech->pParameter = (void *)(&ctr_params);
++ pmech->ulParameterLen = sizeof (ctr_params);
++ /*
++ * For now, we are limited to the fixed length of the counter,
++ * it covers the whole counter block. That's what RFC 4344
++ * needs. For more information on internal structure of the
++ * counter block, see RFC 3686. If needed in the future, we can
++ * add code so that the counter length can be set via
++ * ENGINE_ctrl() function.
++ */
++ ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8;
++ OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE);
++ (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE);
++ }
++ else
++#endif /* SOLARIS_AES_CTR */
++ {
++ if (pcipher->iv_len > 0)
++ {
++ pmech->pParameter = (void *)ctx->iv;
++ pmech->ulParameterLen = pcipher->iv_len;
++ }
++ }
++
++ /* if we get here, the encryption needs to be reinitialized */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++ else
++ rv = pFuncList->C_DecryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ?
++ PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/* ARGSUSED */
++static int
++pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc)
++ {
++ CK_MECHANISM mech;
++ int index;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ PK11_CIPHER *p_ciph_table_row;
++
++ state->sp = NULL;
++
++ index = cipher_nid_to_pk11(ctx->cipher->nid);
++ if (index < 0 || index >= PK11_CIPHER_MAX)
++ return (0);
++
++ p_ciph_table_row = &ciphers[index];
++ /*
++ * iv_len in the ctx->cipher structure is the maximum IV length for the
++ * current cipher and it must be less or equal to the IV length in our
++ * ciphers table. The key length must be in the allowed interval. From
++ * all cipher modes that the PKCS#11 engine supports only RC4 allows a
++ * key length to be in some range, all other NIDs have a precise key
++ * length. Every application can define its own EVP functions so this
++ * code serves as a sanity check.
++ *
++ * Note that the reason why the IV length in ctx->cipher might be
++ * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs
++ * macro to define functions that return EVP structures for all DES
++ * modes. So, even ECB modes get 8 byte IV.
++ */
++ if (ctx->cipher->iv_len < p_ciph_table_row->iv_len ||
++ ctx->key_len < p_ciph_table_row->min_key_len ||
++ ctx->key_len > p_ciph_table_row->max_key_len) {
++ PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM);
++ return (0);
++ }
++
++ if ((sp = pk11_get_session(OP_CIPHER)) == NULL)
++ return (0);
++
++ /* if applicable, the mechanism parameter is used for IV */
++ mech.mechanism = p_ciph_table_row->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ /* The key object is destroyed here if it is not the current key. */
++ (void) check_new_cipher_key(sp, key, ctx->key_len);
++
++ /*
++ * If the key is the same and the encryption is also the same, then
++ * just reuse it. However, we must not forget to reinitialize the
++ * context that was finalized in pk11_cipher_cleanup().
++ */
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE &&
++ sp->opdata_encrypt == ctx->encrypt)
++ {
++ state->sp = sp;
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ return (1);
++ }
++
++ /*
++ * Check if the key has been invalidated. If so, a new key object
++ * needs to be created.
++ */
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ sp->opdata_cipher_key = pk11_get_cipher_key(
++ ctx, key, p_ciph_table_row->key_type, sp);
++ }
++
++ if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1)
++ {
++ /*
++ * The previous encryption/decryption is different. Need to
++ * terminate the previous * active encryption/decryption here.
++ */
++ if (!pk11_cipher_final(sp))
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++ }
++
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ /* now initialize the context with a new key */
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ sp->opdata_encrypt = ctx->encrypt;
++ state->sp = sp;
++
++ return (1);
++ }
++
++/*
++ * When reusing the same key in an encryption/decryption session for a
++ * decryption/encryption session, we need to close the active session
++ * and recreate a new one. Note that the key is in the global session so
++ * that it needs not be recreated.
++ *
++ * It is more appropriate to use C_En/DecryptFinish here. At the time of this
++ * development, these two functions in the PKCS#11 libraries used return
++ * unexpected errors when passing in 0 length output. It may be a good
++ * idea to try them again if performance is a problem here and fix
++ * C_En/DecryptFinial if there are bugs there causing the problem.
++ */
++static int
++pk11_cipher_final(PK11_SESSION *sp)
++ {
++ CK_RV rv;
++
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * An engine interface function. The calling function allocates sufficient
++ * memory for the output buffer "out" to hold the results.
++ */
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl)
++#else
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl)
++#endif
++ {
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ CK_RV rv;
++ unsigned long outl = inl;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ sp = (PK11_SESSION *) state->sp;
++
++ if (!inl)
++ return (1);
++
++ /* RC4 is the only stream cipher we support */
++ if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0)
++ return (0);
++
++ if (ctx->encrypt)
++ {
++ rv = pFuncList->C_EncryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_ENCRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++ else
++ {
++ rv = pFuncList->C_DecryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_DECRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++
++ /*
++ * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always
++ * the same size of input.
++ * The application has guaranteed to call the block ciphers with
++ * correctly aligned buffers.
++ */
++ if (inl != outl)
++ return (0);
++
++ return (1);
++ }
++
++/*
++ * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal()
++ * here is the right thing because in EVP_DecryptFinal_ex(), engine's
++ * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but
++ * the engine can't find out that it's the finalizing call. We wouldn't
++ * necessarily have to finalize the context here since reinitializing it with
++ * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness,
++ * let's do it. Some implementations might leak memory if the previously used
++ * context is initialized without finalizing it first.
++ */
++static int
++pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_ULONG len = EVP_MAX_BLOCK_LENGTH;
++ CK_BYTE buf[EVP_MAX_BLOCK_LENGTH];
++ PK11_CIPHER_STATE *state = ctx->cipher_data;
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * We are not interested in the data here, we just need to get
++ * rid of the context.
++ */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptFinal(
++ state->sp->session, buf, &len);
++ else
++ rv = pFuncList->C_DecryptFinal(
++ state->sp->session, buf, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ?
++ PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv);
++ pk11_return_session(state->sp, OP_CIPHER);
++ return (0);
++ }
++
++ pk11_return_session(state->sp, OP_CIPHER);
++ state->sp = NULL;
++ }
++
++ return (1);
++ }
++
++/*
++ * Registered by the ENGINE when used to find out how to deal with
++ * a particular NID in the ENGINE. This says what we'll do at the
++ * top level - note, that list is restricted by what we answer with
++ */
++/* ARGSUSED */
++static int
++pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid)
++ {
++ if (!cipher)
++ return (pk11_usable_ciphers(nids));
++
++ switch (nid)
++ {
++ case NID_des_ede3_cbc:
++ *cipher = &pk11_3des_cbc;
++ break;
++ case NID_des_cbc:
++ *cipher = &pk11_des_cbc;
++ break;
++ case NID_des_ede3_ecb:
++ *cipher = &pk11_3des_ecb;
++ break;
++ case NID_des_ecb:
++ *cipher = &pk11_des_ecb;
++ break;
++ case NID_aes_128_cbc:
++ *cipher = &pk11_aes_128_cbc;
++ break;
++ case NID_aes_192_cbc:
++ *cipher = &pk11_aes_192_cbc;
++ break;
++ case NID_aes_256_cbc:
++ *cipher = &pk11_aes_256_cbc;
++ break;
++ case NID_aes_128_ecb:
++ *cipher = &pk11_aes_128_ecb;
++ break;
++ case NID_aes_192_ecb:
++ *cipher = &pk11_aes_192_ecb;
++ break;
++ case NID_aes_256_ecb:
++ *cipher = &pk11_aes_256_ecb;
++ break;
++ case NID_bf_cbc:
++ *cipher = &pk11_bf_cbc;
++ break;
++ case NID_rc4:
++ *cipher = &pk11_rc4;
++ break;
++ default:
++#ifdef SOLARIS_AES_CTR
++ /*
++ * These can't be in separated cases because the NIDs
++ * here are not constants.
++ */
++ if (nid == NID_aes_128_ctr)
++ *cipher = &pk11_aes_128_ctr;
++ else if (nid == NID_aes_192_ctr)
++ *cipher = &pk11_aes_192_ctr;
++ else if (nid == NID_aes_256_ctr)
++ *cipher = &pk11_aes_256_ctr;
++ else
++#endif /* SOLARIS_AES_CTR */
++ *cipher = NULL;
++ break;
++ }
++ return (*cipher != NULL);
++ }
++
++/* ARGSUSED */
++static int
++pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid)
++ {
++ if (!digest)
++ return (pk11_usable_digests(nids));
++
++ switch (nid)
++ {
++ case NID_md5:
++ *digest = &pk11_md5;
++ break;
++ case NID_sha1:
++ *digest = &pk11_sha1;
++ break;
++ case NID_sha224:
++ *digest = &pk11_sha224;
++ break;
++ case NID_sha256:
++ *digest = &pk11_sha256;
++ break;
++ case NID_sha384:
++ *digest = &pk11_sha384;
++ break;
++ case NID_sha512:
++ *digest = &pk11_sha512;
++ break;
++ default:
++ *digest = NULL;
++ break;
++ }
++ return (*digest != NULL);
++ }
++
++
++/* Create a secret key object in a PKCS#11 session */
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY;
++ CK_ULONG ul_key_attr_count = 6;
++ unsigned char key_buf[PK11_KEY_LEN_MAX];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VALUE, (void*) NULL, 0},
++ };
++
++ /*
++ * Create secret key object in global_session. All other sessions
++ * can use the key handles. Here is why:
++ * OpenSSL will call EncryptInit and EncryptUpdate using a secret key.
++ * It may then call DecryptInit and DecryptUpdate using the same key.
++ * To use the same key object, we need to call EncryptFinal with
++ * a 0 length message. Currently, this does not work for 3DES
++ * mechanism. To get around this problem, we close the session and
++ * then create a new session to use the same key object. When a session
++ * is closed, all the object handles will be invalid. Thus, create key
++ * objects in a global session, an individual session may be closed to
++ * terminate the active operation.
++ */
++ CK_SESSION_HANDLE session = global_session;
++ a_key_template[0].pValue = &obj_key;
++ a_key_template[1].pValue = &key_type;
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ a_key_template[5].pValue = (void *) key;
++ }
++ else
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ memcpy(key_buf, key, ctx->key_len);
++ if ((key_type == CKK_DES) ||
++ (key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[0]);
++ if ((key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[8]);
++ if (key_type == CKK_DES3)
++ DES_fixup_key_parity((DES_cblock *) &key_buf[16]);
++ a_key_template[5].pValue = (void *) key_buf;
++ }
++ a_key_template[5].ulValueLen = (unsigned long) ctx->key_len;
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++
++ /*
++ * Save the key information used in this session.
++ * The max can be saved is PK11_KEY_LEN_MAX.
++ */
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ sp->opdata_key_len = PK11_KEY_LEN_MAX;
++ (void) memcpy(sp->opdata_key, key, sp->opdata_key_len);
++ }
++ else
++ {
++ sp->opdata_key_len = ctx->key_len;
++ (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len);
++ }
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++err:
++
++ return (h_key);
++ }
++
++static int
++md_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; i++)
++ if (digests[i].nid == nid)
++ return (digests[i].id);
++ return (-1);
++ }
++
++static int
++pk11_digest_init(EVP_MD_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_MECHANISM mech;
++ int index;
++ PK11_SESSION *sp;
++ PK11_DIGEST *pdp;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ state->sp = NULL;
++
++ index = md_nid_to_pk11(ctx->digest->type);
++ if (index < 0 || index >= PK11_DIGEST_MAX)
++ return (0);
++
++ pdp = &digests[index];
++ if ((sp = pk11_get_session(OP_DIGEST)) == NULL)
++ return (0);
++
++ /* at present, no parameter is needed for supported digests */
++ mech.mechanism = pdp->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ rv = pFuncList->C_DigestInit(sp->session, &mech);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv);
++ pk11_return_session(sp, OP_DIGEST);
++ return (0);
++ }
++
++ state->sp = sp;
++
++ return (1);
++ }
++
++static int
++pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
++ {
++ CK_RV rv;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ /* 0 length message will cause a failure in C_DigestFinal */
++ if (count == 0)
++ return (1);
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data,
++ count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ return (1);
++ }
++
++static int
++pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
++ {
++ CK_RV rv;
++ unsigned long len;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++ len = ctx->digest->md_size;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestFinal(state->sp->session, md, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ if (ctx->digest->md_size != len)
++ return (0);
++
++ /*
++ * Final is called and digest is returned, so return the session
++ * to the pool
++ */
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++
++ return (1);
++ }
++
++static int
++pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
++ {
++ CK_RV rv;
++ int ret = 0;
++ PK11_CIPHER_STATE *state, *state_to;
++ CK_BYTE_PTR pstate = NULL;
++ CK_ULONG ul_state_len;
++
++ /* The copy-from state */
++ state = (PK11_CIPHER_STATE *) from->md_data;
++ if (state == NULL || state->sp == NULL)
++ goto err;
++
++ /* Initialize the copy-to state */
++ if (!pk11_digest_init(to))
++ goto err;
++ state_to = (PK11_CIPHER_STATE *) to->md_data;
++
++ /* Get the size of the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, NULL,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++ if (ul_state_len == 0)
++ {
++ goto err;
++ }
++
++ pstate = OPENSSL_malloc(ul_state_len);
++ if (pstate == NULL)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, pstate,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++
++ /* Set the operation state of the copy-to session */
++ rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate,
++ ul_state_len, 0, 0);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY,
++ PK11_R_SET_OPERATION_STATE, rv);
++ goto err;
++ }
++
++ ret = 1;
++err:
++ if (pstate != NULL)
++ OPENSSL_free(pstate);
++
++ return (ret);
++ }
++
++/* Return any pending session state to the pool */
++static int
++pk11_digest_cleanup(EVP_MD_CTX *ctx)
++ {
++ PK11_CIPHER_STATE *state = ctx->md_data;
++ unsigned char buf[EVP_MAX_MD_SIZE];
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * If state->sp is not NULL then pk11_digest_final() has not
++ * been called yet. We must call it now to free any memory
++ * that might have been allocated in the token when
++ * pk11_digest_init() was called. pk11_digest_final()
++ * will return the session to the cache.
++ */
++ if (!pk11_digest_final(ctx, buf))
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * Check if the new key is the same as the key object in the session. If the key
++ * is the same, no need to create a new key object. Otherwise, the old key
++ * object needs to be destroyed and a new one will be created. Return 1 for
++ * cache hit, 0 for cache miss. Note that we must check the key length first
++ * otherwise we could end up reusing a different, longer key with the same
++ * prefix.
++ */
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len)
++ {
++ if (sp->opdata_key_len != key_len ||
++ memcmp(sp->opdata_key, key, key_len) != 0)
++ {
++ (void) pk11_destroy_cipher_key_objects(sp);
++ return (0);
++ }
++ return (1);
++ }
++
++/* Destroy one or more secret key objects. */
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_CIPHER].head;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE)
++ {
++ /*
++ * The secret key object is created in the
++ * global_session. See pk11_get_cipher_key().
++ */
++ if (pk11_destroy_object(global_session,
++ sp->opdata_cipher_key, CK_FALSE) == 0)
++ goto err;
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ }
++ }
++ ret = 1;
++err:
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_X_509
++ * CKM_RSA_PKCS
++ * CKM_DSA
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * Symmetric ciphers optionally supported
++ *
++ * CKM_DES3_CBC
++ * CKM_DES_CBC
++ * CKM_AES_CBC
++ * CKM_DES3_ECB
++ * CKM_DES_ECB
++ * CKM_AES_ECB
++ * CKM_AES_CTR
++ * CKM_RC4
++ * CKM_BLOWFISH_CBC
++ *
++ * Digests optionally supported
++ *
++ * CKM_MD5
++ * CKM_SHA_1
++ * CKM_SHA224
++ * CKM_SHA256
++ * CKM_SHA384
++ * CKM_SHA512
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ int slot_n_cipher = 0;
++ int slot_n_digest = 0;
++ CK_SLOT_ID current_slot = 0;
++ int current_slot_n_cipher = 0;
++ int current_slot_n_digest = 0;
++
++ int local_cipher_nids[PK11_CIPHER_MAX];
++ int local_digest_nids[PK11_DIGEST_MAX];
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ CK_BBOOL slot_has_recover = CK_FALSE;
++ CK_BBOOL slot_has_dsa = CK_FALSE;
++ CK_BBOOL slot_has_dh = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_RSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ /*
++ * Check if this slot is capable of encryption,
++ * decryption, sign, and verify with CKM_RSA_X_509.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_RSA_X_509, &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY) &&
++ (mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT)))
++ {
++ slot_has_rsa = CK_TRUE;
++ if (mech_info.flags & CKF_VERIFY_RECOVER)
++ {
++ slot_has_recover = CK_TRUE;
++ }
++ }
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_DSA.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
++ &mech_info);
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ slot_has_dsa = CK_TRUE;
++ }
++
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ /*
++ * Check if this slot is capable of DH key generataion and
++ * derivation.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
++
++ if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
++ {
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_DERIVE, &mech_info);
++ if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
++ {
++ slot_has_dh = CK_TRUE;
++ }
++ }
++#endif /* OPENSSL_NO_DH */
++
++ if (!found_candidate_slot &&
++ (slot_has_rsa || slot_has_dsa || slot_has_dh))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ pk11_have_recover = slot_has_recover;
++ pk11_have_dsa = slot_has_dsa;
++ pk11_have_dh = slot_has_dh;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa/dsa/dh\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ found_candidate_slot = CK_FALSE;
++ best_slot_sofar = 0;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ current_slot = pSlotList[i];
++ current_slot_n_cipher = 0;
++ current_slot_n_digest = 0;
++ (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
++ (void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
++
++ pk11_find_symmetric_ciphers(pFuncList, current_slot,
++ &current_slot_n_cipher, local_cipher_nids);
++
++ pk11_find_digests(pFuncList, current_slot,
++ &current_slot_n_digest, local_digest_nids);
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG,
++ current_slot_n_cipher);
++ fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG,
++ current_slot_n_digest);
++ fprintf(stderr, "%s: best so far cipher/digest slot: %d\n",
++ PK11_DBG, best_slot_sofar);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * If the current slot supports more ciphers/digests than
++ * the previous best one we change the current best to this one,
++ * otherwise leave it where it is.
++ */
++ if ((current_slot_n_cipher + current_slot_n_digest) >
++ (slot_n_cipher + slot_n_digest))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: changing best so far slot to %d\n",
++ PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = SLOTID = current_slot;
++ cipher_count = slot_n_cipher = current_slot_n_cipher;
++ digest_count = slot_n_digest = current_slot_n_digest;
++ (void) memcpy(cipher_nids, local_cipher_nids,
++ sizeof (local_cipher_nids));
++ (void) memcpy(digest_nids, local_digest_nids,
++ sizeof (local_digest_nids));
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover);
++ fprintf(stderr,
++ "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa);
++ fprintf(stderr,
++ "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++ fprintf(stderr,
++ "%s: cipher_count %d\n", PK11_DBG, cipher_count);
++ fprintf(stderr,
++ "%s: digest_count %d\n", PK11_DBG, digest_count);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ OPENSSL_free(hw_cnids);
++ OPENSSL_free(hw_dnids);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist,
++ int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher,
++ int *local_cipher_nids, int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if ((mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT))
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(ciphers[id].nid, hw_cnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_cipher_nids[(*current_slot_n_cipher)++] =
++ ciphers[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if (mech_info.flags & CKF_DIGEST)
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(digests[id].nid, hw_dnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_digest_nids[(*current_slot_n_digest)++] =
++ digests[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++#ifdef SOLARIS_AES_CTR
++/* create a new NID when we have no OID for that mechanism */
++static int pk11_add_NID(char *sn, char *ln)
++ {
++ ASN1_OBJECT *o;
++ int nid;
++
++ if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"",
++ 1, sn, ln)) == NULL)
++ {
++ return (0);
++ }
++
++ /* will return NID_undef on error */
++ nid = OBJ_add_object(o);
++ ASN1_OBJECT_free(o);
++
++ return (nid);
++ }
++
++/*
++ * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we
++ * have to help ourselves here.
++ */
++static int pk11_add_aes_ctr_NIDs(void)
++ {
++ /* are we already set? */
++ if (NID_aes_256_ctr != NID_undef)
++ return (1);
++
++ /*
++ * There are no official names for AES counter modes yet so we just
++ * follow the format of those that exist.
++ */
++ if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) ==
++ NID_undef)
++ goto err;
++ ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr;
++ if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) ==
++ NID_undef)
++ goto err;
++ ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr;
++ if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) ==
++ NID_undef)
++ goto err;
++ ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr;
++ return (1);
++
++err:
++ PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED);
++ return (0);
++ }
++#endif /* SOLARIS_AES_CTR */
++
++/* Find what symmetric ciphers this slot supports. */
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; ++i)
++ {
++ pk11_get_symmetric_cipher(pflist, current_slot,
++ ciphers[i].mech_type, current_slot_n_cipher,
++ local_cipher_nids, ciphers[i].id);
++ }
++ }
++
++/* Find what digest algorithms this slot supports. */
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; ++i)
++ {
++ pk11_get_digest(pflist, current_slot, digests[i].mech_type,
++ current_slot_n_digest, local_digest_nids, digests[i].id);
++ }
++ }
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * It would be great if we could use pkcs11_kernel directly since this library
++ * offers hardware slots only. That's the easiest way to achieve the situation
++ * where we use the hardware accelerators when present and OpenSSL native code
++ * otherwise. That presumes the fact that OpenSSL native code is faster than the
++ * code in the soft token. It's a logical assumption - Crypto Framework has some
++ * inherent overhead so going there for the software implementation of a
++ * mechanism should be logically slower in contrast to the OpenSSL native code,
++ * presuming that both implementations are of similar speed. For example, the
++ * soft token for AES is roughly three times slower than OpenSSL for 64 byte
++ * blocks and still 20% slower for 8KB blocks. So, if we want to ship products
++ * that use the PKCS#11 engine by default, we must somehow avoid that regression
++ * on machines without hardware acceleration. That's why switching to the
++ * pkcs11_kernel library seems like a very good idea.
++ *
++ * The problem is that OpenSSL built with SunStudio is roughly 2x slower for
++ * asymmetric operations (RSA/DSA/DH) than the soft token built with the same
++ * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11
++ * library, we would have had a performance regression on machines without
++ * hardware acceleration for asymmetric operations for all applications that use
++ * the PKCS#11 engine. There is one such application - Apache web server since
++ * it's shipped configured to use the PKCS#11 engine by default. Having said
++ * that, we can't switch to the pkcs11_kernel library now and have to come with
++ * a solution that, on non-accelerated machines, uses the OpenSSL native code
++ * for all symmetric ciphers and digests while it uses the soft token for
++ * asymmetric operations.
++ *
++ * This is the idea: dlopen() pkcs11_kernel directly and find out what
++ * mechanisms are there. We don't care about duplications (more slots can
++ * support the same mechanism), we just want to know what mechanisms can be
++ * possibly supported in hardware on that particular machine. As said before,
++ * pkcs11_kernel will show you hardware providers only.
++ *
++ * Then, we rely on the fact that since we use libpkcs11 library we will find
++ * the metaslot. When we go through the metaslot's mechanisms for symmetric
++ * ciphers and digests, we check that any found mechanism is in the table
++ * created using the pkcs11_kernel library. So, as a result we have two arrays
++ * of mechanisms that were advertised as supported in hardware which was the
++ * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token
++ * code for symmetric ciphers and digests. See pk11_choose_slots() for more
++ * information.
++ *
++ * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined
++ * the code won't be used.
++ */
++#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64)
++static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1";
++#else
++static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1";
++#endif
++
++/*
++ * Check hardware capabilities of the machines. The output are two lists,
++ * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware
++ * providers together. They are not sorted and may contain duplicate mechanisms.
++ */
++static int check_hw_mechanisms(void)
++ {
++ int i;
++ CK_RV rv;
++ void *handle;
++ CK_C_GetFunctionList p;
++ CK_TOKEN_INFO token_info;
++ CK_ULONG ulSlotCount = 0;
++ int n_cipher = 0, n_digest = 0;
++ CK_FUNCTION_LIST_PTR pflist = NULL;
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL;
++ int hw_ctable_size, hw_dtable_size;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n",
++ PK11_DBG);
++#endif
++ if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ if ((p = (CK_C_GetFunctionList)dlsym(handle,
++ PK11_GET_FUNCTION_LIST)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ if (p(&pflist) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /* no slots, set the hw mechanism tables as empty */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG);
++#endif
++ hw_cnids = OPENSSL_malloc(sizeof (int));
++ hw_dnids = OPENSSL_malloc(sizeof (int));
++ if (hw_cnids == NULL || hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ /* this means empty tables */
++ hw_cnids[0] = NID_undef;
++ hw_dnids[0] = NID_undef;
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the slot list for processing */
++ if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /*
++ * We don't care about duplicit mechanisms in multiple slots and also
++ * reserve one slot for the terminal NID_undef which we use to stop the
++ * search.
++ */
++ hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1;
++ hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1;
++ tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int));
++ tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int));
++ if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * Do not use memset since we should not rely on the fact that NID_undef
++ * is zero now.
++ */
++ for (i = 0; i < hw_ctable_size; ++i)
++ tmp_hw_cnids[i] = NID_undef;
++ for (i = 0; i < hw_dtable_size; ++i)
++ tmp_hw_dnids[i] = NID_undef;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel);
++ fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount);
++ fprintf(stderr, "%s: now looking for mechs supported in hw\n",
++ PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * We are filling the hw mech tables here. Global tables are
++ * still NULL so all mechanisms are put into tmp tables.
++ */
++ pk11_find_symmetric_ciphers(pflist, pSlotList[i],
++ &n_cipher, tmp_hw_cnids);
++ pk11_find_digests(pflist, pSlotList[i],
++ &n_digest, tmp_hw_dnids);
++ }
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects. Also, C_Finalize() is triggered by
++ * dlclose(3C).
++ */
++#if 0
++ pflist->C_Finalize(NULL);
++#endif
++ OPENSSL_free(pSlotList);
++ (void) dlclose(handle);
++ hw_cnids = tmp_hw_cnids;
++ hw_dnids = tmp_hw_dnids;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++
++err:
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++ if (tmp_hw_cnids != NULL)
++ OPENSSL_free(tmp_hw_cnids);
++ if (tmp_hw_dnids != NULL)
++ OPENSSL_free(tmp_hw_dnids);
++
++ return (0);
++ }
++
++/*
++ * Check presence of a NID in the table of NIDs. The table may be NULL (i.e.,
++ * non-existent).
++ */
++static int nid_in_table(int nid, int *nid_table)
++ {
++ int i = 0;
++
++ /*
++ * a special case. NULL means that we are initializing a new
++ * table.
++ */
++ if (nid_table == NULL)
++ return (1);
++
++ /*
++ * the table is never full, there is always at least one
++ * NID_undef.
++ */
++ while (nid_table[i] != NID_undef)
++ {
++ if (nid_table[i++] == nid)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++ }
++
++ return (0);
++ }
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11_err.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.5
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 00:43:26 2011
+@@ -0,0 +1,288 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_err.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <openssl/err.h>
++#include "hw_pk11_err.h"
++
++/* BEGIN ERROR CODES */
++#ifndef OPENSSL_NO_ERR
++static ERR_STRING_DATA pk11_str_functs[]=
++{
++{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"},
++{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"},
++{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"},
++{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"},
++{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"},
++{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"},
++{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"},
++{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"},
++{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"},
++{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"},
++{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"},
++{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"},
++{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"},
++{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"},
++{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"},
++{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"},
++{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"},
++{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"},
++{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"},
++{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"},
++{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"},
++{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"},
++{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"},
++{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"},
++{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"},
++{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"},
++{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"},
++{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"},
++{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"},
++{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"},
++{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"},
++{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"},
++{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"},
++{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"},
++{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"},
++{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"},
++{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"},
++{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"},
++{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"},
++{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"},
++{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"},
++{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"},
++{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"},
++{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"},
++{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"},
++{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"},
++{ 0, NULL}
++};
++
++static ERR_STRING_DATA pk11_str_reasons[]=
++{
++{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"},
++{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"},
++{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"},
++{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"},
++{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"},
++{ PK11_R_INITIALIZE, "C_Initialize failed"},
++{ PK11_R_FINALIZE, "C_Finalize failed"},
++{ PK11_R_GETINFO, "C_GetInfo faile"},
++{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"},
++{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"},
++{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"},
++{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"},
++{ PK11_R_NO_MODULUS, "no modulus"},
++{ PK11_R_NO_EXPONENT, "no exponent"},
++{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"},
++{ PK11_R_FINDOBJECTS, "C_FindObjects failed"},
++{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"},
++{ PK11_R_CREATEOBJECT, "C_CreateObject failed"},
++{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"},
++{ PK11_R_OPENSESSION, "C_OpenSession failed"},
++{ PK11_R_CLOSESESSION, "C_CloseSession failed"},
++{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"},
++{ PK11_R_ENCRYPT, "C_Encrypt failed"},
++{ PK11_R_SIGNINIT, "C_SignInit failed"},
++{ PK11_R_SIGN, "C_Sign failed"},
++{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"},
++{ PK11_R_DECRYPT, "C_Decrypt failed"},
++{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"},
++{ PK11_R_VERIFY, "C_Verify failed"},
++{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"},
++{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"},
++{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"},
++{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"},
++{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"},
++{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"},
++{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"},
++{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"},
++{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"},
++{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"},
++{ PK11_R_DIGEST_TOO_BIG, "digest too big"},
++{ PK11_R_MALLOC_FAILURE, "malloc failure"},
++{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"},
++{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"},
++{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"},
++{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"},
++{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"},
++{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"},
++{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"},
++{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"},
++{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"},
++{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"},
++{ PK11_R_DIGESTINIT, "C_DigestInit failed"},
++{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"},
++{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"},
++{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"},
++{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"},
++{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"},
++{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"},
++{ PK11_R_DERIVEKEY, "C_DeriveKey failed"},
++{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"},
++{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"},
++{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"},
++{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"},
++{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"},
++{ PK11_R_ADD_NID_FAILED, "failed to add NID" },
++{ PK11_R_ATFORK_FAILED, "atfork() failed" },
++{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" },
++{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" },
++{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" },
++{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" },
++{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" },
++{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" },
++{ PK11_R_PIPE_FAILED, "pipe() failed" },
++{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" },
++{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" },
++{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" },
++{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" },
++{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" },
++{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" },
++{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" },
++{ PK11_R_NO_OBJECT_FOUND, "specified object not found" },
++{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" },
++{ PK11_R_SYSCONF_FAILED, "sysconf() failed" },
++{ PK11_R_MMAP_FAILED, "mmap() failed" },
++{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" },
++{ PK11_R_MLOCK_FAILED, "mlock() failed" },
++{ PK11_R_FORK_FAILED, "fork() failed" },
++{ 0, NULL}
++};
++#endif /* OPENSSL_NO_ERR */
++
++static int pk11_lib_error_code = 0;
++static int pk11_error_init = 1;
++
++static void
++ERR_load_pk11_strings(void)
++ {
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++
++ if (pk11_error_init)
++ {
++ pk11_error_init = 0;
++#ifndef OPENSSL_NO_ERR
++ ERR_load_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_load_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ }
++}
++
++static void
++ERR_unload_pk11_strings(void)
++ {
++ if (pk11_error_init == 0)
++ {
++#ifndef OPENSSL_NO_ERR
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ pk11_error_init = 1;
++ }
++}
++
++void
++ERR_pk11_error(int function, int reason, char *file, int line)
++{
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++ ERR_PUT_error(pk11_lib_error_code, function, reason, file, line);
++}
++
++void
++PK11err_add_data(int function, int reason, CK_RV rv)
++{
++ char tmp_buf[20];
++
++ PK11err(function, reason);
++ (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++}
+Index: openssl/crypto/engine/hw_pk11_err.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.12.4.1
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:33:56 2013
+@@ -0,0 +1,440 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#ifndef HW_PK11_ERR_H
++#define HW_PK11_ERR_H
++
++void ERR_pk11_error(int function, int reason, char *file, int line);
++void PK11err_add_data(int function, int reason, CK_RV rv);
++#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__)
++
++/* Error codes for the PK11 functions. */
++
++/* Function codes. */
++
++#define PK11_F_INIT 100
++#define PK11_F_FINISH 101
++#define PK11_F_DESTROY 102
++#define PK11_F_CTRL 103
++#define PK11_F_RSA_INIT 104
++#define PK11_F_RSA_FINISH 105
++#define PK11_F_GET_PUB_RSA_KEY 106
++#define PK11_F_GET_PRIV_RSA_KEY 107
++#define PK11_F_RSA_GEN_KEY 108
++#define PK11_F_RSA_PUB_ENC 109
++#define PK11_F_RSA_PRIV_ENC 110
++#define PK11_F_RSA_PUB_DEC 111
++#define PK11_F_RSA_PRIV_DEC 112
++#define PK11_F_RSA_SIGN 113
++#define PK11_F_RSA_VERIFY 114
++#define PK11_F_RAND_ADD 115
++#define PK11_F_RAND_BYTES 116
++#define PK11_F_GET_SESSION 117
++#define PK11_F_FREE_SESSION 118
++#define PK11_F_LOAD_PUBKEY 119
++#define PK11_F_LOAD_PRIVKEY 120
++#define PK11_F_RSA_PUB_ENC_LOW 121
++#define PK11_F_RSA_PRIV_ENC_LOW 122
++#define PK11_F_RSA_PUB_DEC_LOW 123
++#define PK11_F_RSA_PRIV_DEC_LOW 124
++#define PK11_F_DSA_SIGN 125
++#define PK11_F_DSA_VERIFY 126
++#define PK11_F_DSA_INIT 127
++#define PK11_F_DSA_FINISH 128
++#define PK11_F_GET_PUB_DSA_KEY 129
++#define PK11_F_GET_PRIV_DSA_KEY 130
++#define PK11_F_DH_INIT 131
++#define PK11_F_DH_FINISH 132
++#define PK11_F_MOD_EXP_DH 133
++#define PK11_F_GET_DH_KEY 134
++#define PK11_F_FREE_ALL_SESSIONS 135
++#define PK11_F_SETUP_SESSION 136
++#define PK11_F_DESTROY_OBJECT 137
++#define PK11_F_CIPHER_INIT 138
++#define PK11_F_CIPHER_DO_CIPHER 139
++#define PK11_F_GET_CIPHER_KEY 140
++#define PK11_F_DIGEST_INIT 141
++#define PK11_F_DIGEST_UPDATE 142
++#define PK11_F_DIGEST_FINAL 143
++#define PK11_F_CHOOSE_SLOT 144
++#define PK11_F_CIPHER_FINAL 145
++#define PK11_F_LIBRARY_INIT 146
++#define PK11_F_LOAD 147
++#define PK11_F_DH_GEN_KEY 148
++#define PK11_F_DH_COMP_KEY 149
++#define PK11_F_DIGEST_COPY 150
++#define PK11_F_CIPHER_CLEANUP 151
++#define PK11_F_ACTIVE_ADD 152
++#define PK11_F_ACTIVE_DELETE 153
++#define PK11_F_CHECK_HW_MECHANISMS 154
++#define PK11_F_INIT_SYMMETRIC 155
++#define PK11_F_ADD_AES_CTR_NIDS 156
++#define PK11_F_INIT_ALL_LOCKS 157
++#define PK11_F_RETURN_SESSION 158
++#define PK11_F_GET_PIN 159
++#define PK11_F_FIND_ONE_OBJECT 160
++#define PK11_F_CHECK_TOKEN_ATTRS 161
++#define PK11_F_CACHE_PIN 162
++#define PK11_F_MLOCK_PIN_IN_MEMORY 163
++#define PK11_F_TOKEN_LOGIN 164
++#define PK11_F_TOKEN_RELOGIN 165
++#define PK11_F_RUN_ASKPASS 166
++
++/* Reason codes. */
++#define PK11_R_ALREADY_LOADED 100
++#define PK11_R_DSO_FAILURE 101
++#define PK11_R_NOT_LOADED 102
++#define PK11_R_PASSED_NULL_PARAMETER 103
++#define PK11_R_COMMAND_NOT_IMPLEMENTED 104
++#define PK11_R_INITIALIZE 105
++#define PK11_R_FINALIZE 106
++#define PK11_R_GETINFO 107
++#define PK11_R_GETSLOTLIST 108
++#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109
++#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110
++#define PK11_R_GETATTRIBUTVALUE 111
++#define PK11_R_NO_MODULUS 112
++#define PK11_R_NO_EXPONENT 113
++#define PK11_R_FINDOBJECTSINIT 114
++#define PK11_R_FINDOBJECTS 115
++#define PK11_R_FINDOBJECTSFINAL 116
++#define PK11_R_CREATEOBJECT 118
++#define PK11_R_DESTROYOBJECT 119
++#define PK11_R_OPENSESSION 120
++#define PK11_R_CLOSESESSION 121
++#define PK11_R_ENCRYPTINIT 122
++#define PK11_R_ENCRYPT 123
++#define PK11_R_SIGNINIT 124
++#define PK11_R_SIGN 125
++#define PK11_R_DECRYPTINIT 126
++#define PK11_R_DECRYPT 127
++#define PK11_R_VERIFYINIT 128
++#define PK11_R_VERIFY 129
++#define PK11_R_VERIFYRECOVERINIT 130
++#define PK11_R_VERIFYRECOVER 131
++#define PK11_R_GEN_KEY 132
++#define PK11_R_SEEDRANDOM 133
++#define PK11_R_GENERATERANDOM 134
++#define PK11_R_INVALID_MESSAGE_LENGTH 135
++#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136
++#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137
++#define PK11_R_UNKNOWN_PADDING_TYPE 138
++#define PK11_R_PADDING_CHECK_FAILED 139
++#define PK11_R_DIGEST_TOO_BIG 140
++#define PK11_R_MALLOC_FAILURE 141
++#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142
++#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143
++#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144
++#define PK11_R_MISSING_KEY_COMPONENT 145
++#define PK11_R_INVALID_SIGNATURE_LENGTH 146
++#define PK11_R_INVALID_DSA_SIGNATURE_R 147
++#define PK11_R_INVALID_DSA_SIGNATURE_S 148
++#define PK11_R_INCONSISTENT_KEY 149
++#define PK11_R_ENCRYPTUPDATE 150
++#define PK11_R_DECRYPTUPDATE 151
++#define PK11_R_DIGESTINIT 152
++#define PK11_R_DIGESTUPDATE 153
++#define PK11_R_DIGESTFINAL 154
++#define PK11_R_ENCRYPTFINAL 155
++#define PK11_R_DECRYPTFINAL 156
++#define PK11_R_NO_PRNG_SUPPORT 157
++#define PK11_R_GETTOKENINFO 158
++#define PK11_R_DERIVEKEY 159
++#define PK11_R_GET_OPERATION_STATE 160
++#define PK11_R_SET_OPERATION_STATE 161
++#define PK11_R_INVALID_HANDLE 162
++#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163
++#define PK11_R_INVALID_OPERATION_TYPE 164
++#define PK11_R_ADD_NID_FAILED 165
++#define PK11_R_ATFORK_FAILED 166
++
++#define PK11_R_TOKEN_LOGIN_FAILED 167
++#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168
++#define PK11_R_INVALID_PKCS11_URI 169
++#define PK11_R_COULD_NOT_READ_PIN 170
++#define PK11_R_COULD_NOT_OPEN_COMMAND 171
++#define PK11_R_PIPE_FAILED 172
++#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173
++#define PK11_R_BAD_PASSPHRASE_SPEC 174
++#define PK11_R_TOKEN_NOT_INITIALIZED 175
++#define PK11_R_TOKEN_PIN_NOT_SET 176
++#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177
++#define PK11_R_MISSING_OBJECT_LABEL 178
++#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179
++#define PK11_R_PRIV_KEY_NOT_FOUND 180
++#define PK11_R_NO_OBJECT_FOUND 181
++#define PK11_R_PIN_CACHING_POLICY_INVALID 182
++#define PK11_R_SYSCONF_FAILED 183
++#define PK11_R_MMAP_FAILED 183
++#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184
++#define PK11_R_MLOCK_FAILED 185
++#define PK11_R_FORK_FAILED 186
++
++/* max byte length of a symetric key we support */
++#define PK11_KEY_LEN_MAX 32
++
++#ifdef NOPTHREADS
++/*
++ * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the
++ * free_session list and active_list but generally serves as a global
++ * per-process lock for the whole engine.
++ *
++ * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as
++ * the global engine lock. This is not optimal w.r.t. performance but
++ * it's safe.
++ */
++#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC
++#endif
++
++/*
++ * This structure encapsulates all reusable information for a PKCS#11
++ * session. A list of these objects is created on behalf of the
++ * calling application using an on-demand method. Each operation
++ * type (see PK11_OPTYPE below) has its own per-process list.
++ * Each of the lists is basically a cache for faster PKCS#11 object
++ * access to avoid expensive C_Find{,Init,Final}Object() calls.
++ *
++ * When a new request comes in, an object will be taken from the list
++ * (if there is one) or a new one is created to handle the request
++ * (if the list is empty). See pk11_get_session() on how it is done.
++ */
++typedef struct PK11_st_SESSION
++ {
++ struct PK11_st_SESSION *next;
++ CK_SESSION_HANDLE session; /* PK11 session handle */
++ pid_t pid; /* Current process ID */
++ CK_BBOOL pub_persistent; /* is pub key in keystore? */
++ CK_BBOOL priv_persistent;/* is priv key in keystore? */
++ union
++ {
++#ifndef OPENSSL_NO_RSA
++ struct
++ {
++ CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */
++ RSA *rsa_pub; /* pub key addr */
++ BIGNUM *rsa_n_num; /* pub modulus */
++ BIGNUM *rsa_e_num; /* pub exponent */
++ RSA *rsa_priv; /* priv key addr */
++ BIGNUM *rsa_pn_num; /* pub modulus */
++ BIGNUM *rsa_pe_num; /* pub exponent */
++ BIGNUM *rsa_d_num; /* priv exponent */
++ } u_RSA;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ struct
++ {
++ CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */
++ DSA *dsa_pub; /* pub key addr */
++ BIGNUM *dsa_pub_num; /* pub key */
++ DSA *dsa_priv; /* priv key addr */
++ BIGNUM *dsa_priv_num; /* priv key */
++ } u_DSA;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ struct
++ {
++ CK_OBJECT_HANDLE dh_key; /* key handle */
++ DH *dh; /* dh key addr */
++ BIGNUM *dh_priv_num; /* priv dh key */
++ } u_DH;
++#endif /* OPENSSL_NO_DH */
++ struct
++ {
++ CK_OBJECT_HANDLE cipher_key; /* key handle */
++ unsigned char key[PK11_KEY_LEN_MAX];
++ int key_len; /* priv key len */
++ int encrypt; /* 1/0 enc/decr */
++ } u_cipher;
++ } opdata_u;
++ } PK11_SESSION;
++
++#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key
++#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key
++#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub
++#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv
++#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num
++#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num
++#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num
++#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num
++#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num
++#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key
++#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key
++#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub
++#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num
++#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv
++#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num
++#define opdata_dh_key opdata_u.u_DH.dh_key
++#define opdata_dh opdata_u.u_DH.dh
++#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num
++#define opdata_cipher_key opdata_u.u_cipher.cipher_key
++#define opdata_key opdata_u.u_cipher.key
++#define opdata_key_len opdata_u.u_cipher.key_len
++#define opdata_encrypt opdata_u.u_cipher.encrypt
++
++/*
++ * We have 3 different groups of operation types:
++ * 1) asymmetric operations
++ * 2) random operations
++ * 3) symmetric and digest operations
++ *
++ * This division into groups stems from the fact that it's common that hardware
++ * providers may support operations from one group only. For example, hardware
++ * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support
++ * only a single group of operations.
++ *
++ * For every group a different slot can be chosen. That means that we must have
++ * at least 3 different lists of cached PKCS#11 sessions since sessions from
++ * different groups may be initialized in different slots.
++ *
++ * To provide locking granularity in multithreaded environment, the groups are
++ * further splitted into types with each type having a separate session cache.
++ */
++typedef enum PK11_OPTYPE_ENUM
++ {
++ OP_RAND,
++ OP_RSA,
++ OP_DSA,
++ OP_DH,
++ OP_CIPHER,
++ OP_DIGEST,
++ OP_MAX
++ } PK11_OPTYPE;
++
++/*
++ * This structure contains the heads of the lists forming the object caches
++ * and locks associated with the lists.
++ */
++typedef struct PK11_st_CACHE
++ {
++ PK11_SESSION *head;
++#ifndef NOPTHREADS
++ pthread_mutex_t *lock;
++#endif
++ } PK11_CACHE;
++
++/* structure for tracking handles of asymmetric key objects */
++typedef struct PK11_active_st
++ {
++ CK_OBJECT_HANDLE h;
++ unsigned int refcnt;
++ struct PK11_active_st *prev;
++ struct PK11_active_st *next;
++ } PK11_active;
++
++#ifndef NOPTHREADS
++extern pthread_mutex_t *find_lock[];
++#endif
++extern PK11_active *active_list[];
++/*
++ * These variables are specific for the RSA keys by reference code. See
++ * hw_pk11_pub.c for explanation.
++ */
++extern CK_FLAGS pubkey_token_flags;
++
++#ifndef NOPTHREADS
++#define LOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0)
++#define UNLOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0)
++#else
++#define LOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE)
++#define UNLOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE)
++#endif
++
++extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++extern int pk11_token_relogin(CK_SESSION_HANDLE session);
++
++#ifndef OPENSSL_NO_RSA
++extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern RSA_METHOD *PK11_RSA(void);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DSA_METHOD *PK11_DSA(void);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++extern int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DH_METHOD *PK11_DH(void);
++#endif /* OPENSSL_NO_DH */
++
++extern CK_FUNCTION_LIST_PTR pFuncList;
++
++#endif /* HW_PK11_ERR_H */
+Index: openssl/crypto/engine/hw_pk11_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.38.2.3
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:33:56 2013
+@@ -0,0 +1,3556 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif /* OPENSSL_NO_DH */
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++#ifndef OPENSSL_NO_RSA
++/* RSA stuff */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_init(RSA *rsa);
++static int pk11_RSA_finish(RSA *rsa);
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#else
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#endif
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++#endif
++
++/* DSA stuff */
++#ifndef OPENSSL_NO_DSA
++static int pk11_DSA_init(DSA *dsa);
++static int pk11_DSA_finish(DSA *dsa);
++static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen,
++ DSA *dsa);
++static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len,
++ DSA_SIG *sig, DSA *dsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session);
++
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa);
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa);
++#endif
++
++/* DH stuff */
++#ifndef OPENSSL_NO_DH
++static int pk11_DH_init(DH *dh);
++static int pk11_DH_finish(DH *dh);
++static int pk11_DH_generate_key(DH *dh);
++static int pk11_DH_compute_key(unsigned char *key,
++ const BIGNUM *pub_key, DH *dh);
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr,
++ BIGNUM **priv_key, CK_SESSION_HANDLE session);
++
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh);
++#endif
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa =
++ {
++ "PKCS#11 RSA method",
++ pk11_RSA_public_encrypt, /* rsa_pub_encrypt */
++ pk11_RSA_public_decrypt, /* rsa_pub_decrypt */
++ pk11_RSA_private_encrypt, /* rsa_priv_encrypt */
++ pk11_RSA_private_decrypt, /* rsa_priv_decrypt */
++ NULL, /* rsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_RSA_init, /* init */
++ pk11_RSA_finish, /* finish */
++ RSA_FLAG_SIGN_VER, /* flags */
++ NULL, /* app_data */
++ pk11_RSA_sign, /* rsa_sign */
++ pk11_RSA_verify /* rsa_verify */
++ };
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ return (&pk11_rsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* Our internal DSA_METHOD that we provide pointers to */
++static DSA_METHOD pk11_dsa =
++ {
++ "PKCS#11 DSA method",
++ pk11_dsa_do_sign, /* dsa_do_sign */
++ NULL, /* dsa_sign_setup */
++ pk11_dsa_do_verify, /* dsa_do_verify */
++ NULL, /* dsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_DSA_init, /* init */
++ pk11_DSA_finish, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++ };
++
++DSA_METHOD *
++PK11_DSA(void)
++ {
++ return (&pk11_dsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DH
++/*
++ * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for
++ * output buffer may somewhat exceed the precise number of bytes needed, but
++ * should not exceed it by a large amount. That may be caused, for example, by
++ * rounding it up to multiple of X in the underlying bignum library. 8 should be
++ * enough.
++ */
++#define DH_BUF_RESERVE 8
++
++/* Our internal DH_METHOD that we provide pointers to */
++static DH_METHOD pk11_dh =
++ {
++ "PKCS#11 DH method",
++ pk11_DH_generate_key, /* generate_key */
++ pk11_DH_compute_key, /* compute_key */
++ NULL, /* bn_mod_exp */
++ pk11_DH_init, /* init */
++ pk11_DH_finish, /* finish */
++ 0, /* flags */
++ NULL, /* app_data */
++ NULL /* generate_params */
++ };
++
++DH_METHOD *
++PK11_DH(void)
++ {
++ return (&pk11_dh);
++ }
++#endif
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++/* Lengths of DSA data and signature */
++#define DSA_DATA_LEN 20
++#define DSA_SIGNATURE_LEN 40
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++#ifndef OPENSSL_NO_RSA
++/*
++ * Similiar to OpenSSL to take advantage of the paddings. The goal is to
++ * support all paddings in this engine although PK11 library does not
++ * support all the paddings used in OpenSSL.
++ * The input errors should have been checked in the padding functions.
++ */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ i = RSA_padding_add_SSLv23(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++
++/*
++ * Similar to Openssl to take advantage of the paddings. The input errors
++ * should be catched in the padding functions
++ */
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ case RSA_SSLV23_PADDING:
++ default:
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int j, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++
++ num = BN_num_bytes(rsa->n);
++
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ /* make data into a big number */
++ if (BN_bin2bn(from, (int)flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's paddings here.
++ */
++ for (j = 0; j < r; j++)
++ if (buf[j] != 0)
++ break;
++
++ p = buf + j;
++ j = r - j; /* j is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ r = RSA_padding_check_SSLv23(to, num, p, j, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, j, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int i, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++ num = BN_num_bytes(rsa->n);
++ buf = (unsigned char *)OPENSSL_malloc(num);
++ if (buf == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ if (BN_bin2bn(from, flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's here
++ */
++ for (i = 0; i < r; i++)
++ if (buf[i] != 0)
++ break;
++
++ p = buf + i;
++ i = r - i; /* i is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, i, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/*
++ * This function implements RSA public encryption using C_EncryptInit and
++ * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_encrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_EncryptInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Encrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_encrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_encrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private encryption using C_SignInit and
++ * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG ul_sig_len = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ {
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW,
++ PK11_R_SIGNINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char *)from, flen, to, &ul_sig_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN,
++ rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ retval = ul_sig_len;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private decryption using C_DecryptInit and
++ * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DecryptInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Decrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA public decryption using C_VerifyRecoverInit
++ * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyRecoverInit(sp->session,
++ p_mech, h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVERINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_VerifyRecover(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVER, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++static int pk11_RSA_init(RSA *rsa)
++ {
++ /*
++ * This flag in the RSA_METHOD enables the new rsa_sign,
++ * rsa_verify functions. See rsa.h for details.
++ */
++ rsa->flags |= RSA_FLAG_SIGN_VER;
++
++ return (1);
++ }
++
++static int pk11_RSA_finish(RSA *rsa)
++ {
++ /*
++ * Since we are overloading OpenSSL's native RSA_eay_finish() we need
++ * to do the same as in the original function, i.e. to free bignum
++ * structures.
++ */
++ if (rsa->_method_mod_n != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_n);
++ if (rsa->_method_mod_p != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_p);
++ if (rsa->_method_mod_q != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_q);
++
++ return (1);
++ }
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#else
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#endif
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto err;
++ }
++ rv = pFuncList->C_Verify(sp->session, s, i,
++ (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* The DSA function implementation */
++/* ARGSUSED */
++static int pk11_DSA_init(DSA *dsa)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DSA_finish(DSA *dsa)
++ {
++ return (1);
++ }
++
++
++static DSA_SIG *
++pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
++ {
++ BIGNUM *r = NULL, *s = NULL;
++ int i;
++ DSA_SIG *dsa_sig = NULL;
++
++ CK_RV rv;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_priv_key;
++
++ /*
++ * The signature is the concatenation of r and s,
++ * each is 20 bytes long
++ */
++ unsigned char sigret[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned int siglen2 = DSA_SIGNATURE_LEN / 2;
++
++ PK11_SESSION *sp = NULL;
++
++ if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_priv(sp, dsa);
++
++ h_priv_key = sp->opdata_dsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_dsa_priv_key =
++ pk11_get_private_dsa_key((DSA *)dsa,
++ &sp->opdata_dsa_priv,
++ &sp->opdata_dsa_priv_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto ret;
++ }
++
++ (void) memset(sigret, 0, siglen);
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char*) dgst, dlen, sigret,
++ (CK_ULONG_PTR) &siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv);
++ goto ret;
++ }
++ }
++
++
++ if ((s = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((r = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((dsa_sig = DSA_SIG_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if (BN_bin2bn(sigret, siglen2, r) == NULL ||
++ BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ dsa_sig->r = r;
++ dsa_sig->s = s;
++
++ret:
++ if (dsa_sig == NULL)
++ {
++ if (r != NULL)
++ BN_free(r);
++ if (s != NULL)
++ BN_free(s);
++ }
++
++ pk11_return_session(sp, OP_DSA);
++ return (dsa_sig);
++ }
++
++static int
++pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig,
++ DSA *dsa)
++ {
++ int i;
++ CK_RV rv;
++ int retval = 0;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_pub_key;
++
++ unsigned char sigbuf[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned long siglen2 = DSA_SIGNATURE_LEN/2;
++
++ PK11_SESSION *sp = NULL;
++
++ if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_R);
++ goto ret;
++ }
++
++ if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_S);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_pub(sp, dsa);
++
++ h_pub_key = sp->opdata_dsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_dsa_pub_key =
++ pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub,
++ &sp->opdata_dsa_pub_num, sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto ret;
++ }
++
++ /*
++ * The representation of each of the two big numbers could
++ * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need
++ * to act accordingly and shift if necessary.
++ */
++ (void) memset(sigbuf, 0, siglen);
++ BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r));
++ BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 -
++ BN_num_bytes(sig->s));
++
++ rv = pFuncList->C_Verify(sp->session,
++ (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv);
++ goto ret;
++ }
++ }
++
++ retval = 1;
++ret:
++
++ pk11_return_session(sp, OP_DSA);
++ return (retval);
++ }
++
++
++/*
++ * Create a public key object in a session from a given dsa structure.
++ * The *dsa_pub_num pointer is non-NULL for DSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ if (init_template_value(dsa->p, &a_key_template[4].pValue,
++ &a_key_template[4].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->pub_key, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_pub_num != NULL)
++ if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ for (i = 4; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given dsa structure
++ * The *dsa_priv_num pointer is non-NULL for DSA private keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ int i;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 9;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(dsa->p, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(dsa->priv_key, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_priv_num != NULL)
++ if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ /*
++ * 5 to 8 entries in the key template are key components.
++ * They need to be freed apon exit or error.
++ */
++ for (i = 5; i <= 8; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only public key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_pub != dsa) ||
++ (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only private key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_priv != dsa) ||
++ (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++
++#ifndef OPENSSL_NO_DH
++/* The DH function implementation */
++/* ARGSUSED */
++static int pk11_DH_init(DH *dh)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DH_finish(DH *dh)
++ {
++ return (1);
++ }
++
++/*
++ * Generate DH key-pair.
++ *
++ * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key
++ * and override it even if it is set. OpenSSL does not touch dh->priv_key
++ * if set and just computes dh->pub_key. It looks like PKCS#11 standard
++ * is not capable of providing this functionality. This could be a problem
++ * for applications relying on OpenSSL's semantics.
++ */
++static int pk11_DH_generate_key(DH *dh)
++ {
++ CK_ULONG i;
++ CK_RV rv, rv1;
++ int reuse_mem_len = 0, ret = 0;
++ PK11_SESSION *sp = NULL;
++ CK_BYTE_PTR reuse_mem;
++
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++
++ CK_ULONG ul_pub_key_attr_count = 3;
++ CK_ATTRIBUTE pub_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *)NULL, 0},
++ {CKA_BASE, (void *)NULL, 0}
++ };
++
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)}
++ };
++
++ CK_ULONG pub_key_attr_result_count = 1;
++ CK_ATTRIBUTE pub_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ pub_key_template[1].ulValueLen = BN_num_bytes(dh->p);
++ if (pub_key_template[1].ulValueLen > 0)
++ {
++ /*
++ * We must not increase ulValueLen by DH_BUF_RESERVE since that
++ * could cause the same rounding problem. See definition of
++ * DH_BUF_RESERVE above.
++ */
++ pub_key_template[1].pValue =
++ OPENSSL_malloc(pub_key_template[1].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[1].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->p, pub_key_template[1].pValue);
++ }
++ else
++ goto err;
++
++ pub_key_template[2].ulValueLen = BN_num_bytes(dh->g);
++ if (pub_key_template[2].ulValueLen > 0)
++ {
++ pub_key_template[2].pValue =
++ OPENSSL_malloc(pub_key_template[2].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[2].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->g, pub_key_template[2].pValue);
++ }
++ else
++ goto err;
++
++ /*
++ * Note: we are only using PK11_SESSION structure for getting
++ * a session handle. The objects created in this function are
++ * destroyed before return and thus not cached.
++ */
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ rv = pFuncList->C_GenerateKeyPair(sp->session,
++ &mechanism,
++ pub_key_template,
++ ul_pub_key_attr_count,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_pub_key,
++ &h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv);
++ goto err;
++ }
++
++ /*
++ * Reuse the larger memory allocated. We know the larger memory
++ * should be sufficient for reuse.
++ */
++ if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen)
++ {
++ reuse_mem = pub_key_template[1].pValue;
++ reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE;
++ }
++ else
++ {
++ reuse_mem = pub_key_template[2].pValue;
++ reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++ rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK || rv1 != CKR_OK)
++ {
++ rv = (rv != CKR_OK) ? rv : rv1;
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 ||
++ ((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++
++ /* Reuse the memory allocated */
++ pub_key_result[0].pValue = reuse_mem;
++ pub_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (pub_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->pub_key == NULL)
++ if ((dh->pub_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->pub_key = BN_bin2bn(pub_key_result[0].pValue,
++ pub_key_result[0].ulValueLen, dh->pub_key);
++ if (dh->pub_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ /* Reuse the memory allocated */
++ priv_key_result[0].pValue = reuse_mem;
++ priv_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->priv_key == NULL)
++ if ((dh->priv_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->priv_key = BN_bin2bn(priv_key_result[0].pValue,
++ priv_key_result[0].ulValueLen, dh->priv_key);
++ if (dh->priv_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ ret = 1;
++
++err:
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_pub_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ for (i = 1; i <= 2; i++)
++ {
++ if (pub_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(pub_key_template[i].pValue);
++ pub_key_template[i].pValue = NULL;
++ }
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key,
++ DH *dh)
++ {
++ unsigned int i;
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0};
++ CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
++ CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
++ CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++
++ CK_ULONG seclen;
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (key_class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_VALUE_LEN, &seclen, sizeof (seclen)},
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_RV rv;
++ int ret = -1;
++ PK11_SESSION *sp = NULL;
++
++ if (dh->priv_key == NULL)
++ goto err;
++
++ priv_key_template[0].pValue = &key_class;
++ priv_key_template[1].pValue = &key_type;
++ seclen = BN_num_bytes(dh->p);
++
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ mechanism.ulParameterLen = BN_num_bytes(pub_key);
++ mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen);
++ if (mechanism.pParameter == NULL)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ BN_bn2bin(pub_key, mechanism.pParameter);
++
++ (void) check_new_dh_key(sp, dh);
++
++ h_key = sp->opdata_dh_key;
++ if (h_key == CK_INVALID_HANDLE)
++ h_key = sp->opdata_dh_key =
++ pk11_get_dh_key((DH*) dh, &sp->opdata_dh,
++ &sp->opdata_dh_priv_num, sp->session);
++
++ if (h_key == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT);
++ goto err;
++ }
++
++ rv = pFuncList->C_DeriveKey(sp->session,
++ &mechanism,
++ h_key,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++ priv_key_result[0].pValue =
++ OPENSSL_malloc(priv_key_result[0].ulValueLen);
++ if (!priv_key_result[0].pValue)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ /*
++ * OpenSSL allocates the output buffer 'key' which is the same
++ * length of the public key. It is long enough for the derived key
++ */
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ /*
++ * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip
++ * leading zeros from a computed shared secret. However,
++ * OpenSSL always did it so we must do the same here. The
++ * vagueness of the spec regarding leading zero bytes was
++ * finally cleared with TLS 1.1 (RFC 4346) saying that leading
++ * zeros are stripped before the computed data is used as the
++ * pre-master secret.
++ */
++ for (i = 0; i < priv_key_result[0].ulValueLen; ++i)
++ {
++ if (((char *)priv_key_result[0].pValue)[i] != 0)
++ break;
++ }
++
++ (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i,
++ priv_key_result[0].ulValueLen - i);
++ ret = priv_key_result[0].ulValueLen - i;
++ }
++
++err:
++
++ if (h_derived_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++ if (priv_key_result[0].pValue)
++ {
++ OPENSSL_free(priv_key_result[0].pValue);
++ priv_key_result[0].pValue = NULL;
++ }
++
++ if (mechanism.pParameter)
++ {
++ OPENSSL_free(mechanism.pParameter);
++ mechanism.pParameter = NULL;
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh,
++ DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE key_type = CKK_DH;
++ CK_ULONG found;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ULONG ul_key_attr_count = 7;
++ CK_ATTRIBUTE key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)},
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *) NULL, 0},
++ {CKA_BASE, (void *) NULL, 0},
++ {CKA_VALUE, (void *) NULL, 0},
++ };
++
++ key_template[0].pValue = &class;
++ key_template[1].pValue = &key_type;
++
++ key_template[4].ulValueLen = BN_num_bytes(dh->p);
++ key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[4].ulValueLen);
++ if (key_template[4].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->p, key_template[4].pValue);
++
++ key_template[5].ulValueLen = BN_num_bytes(dh->g);
++ key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[5].ulValueLen);
++ if (key_template[5].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->g, key_template[5].pValue);
++
++ key_template[6].ulValueLen = BN_num_bytes(dh->priv_key);
++ key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[6].ulValueLen);
++ if (key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->priv_key, key_template[6].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DH);
++ rv = pFuncList->C_FindObjectsInit(session, key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL,
++ rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++ }
++
++ if (dh_priv_num != NULL)
++ if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dh;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DH);
++
++malloc_err:
++ for (i = 4; i <= 6; i++)
++ {
++ if (key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(key_template[i].pValue);
++ key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ *
++ * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh
++ * to CK_INVALID_HANDLE even when it fails to destroy the object.
++ */
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh)
++ {
++ /*
++ * Provide protection against DH structure reuse by making the
++ * check for cache hit stronger. Private key component of DH key
++ * is unique so it is sufficient to compare it with value cached
++ * in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dh != dh) ||
++ (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dh_object(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11ca.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.4
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:20 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */
++
++#define token_lock pk11ca_token_lock
++#define find_lock pk11ca_find_lock
++#define active_list pk11ca_active_list
++#define pubkey_token_flags pk11ca_pubkey_token_flags
++#define pubkey_SLOTID pk11ca_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11ca_error
++#define PK11err_add_data PK11CAerr_add_data
++#define pk11_get_session pk11ca_get_session
++#define pk11_return_session pk11ca_return_session
++#define pk11_active_add pk11ca_active_add
++#define pk11_active_delete pk11ca_active_delete
++#define pk11_active_remove pk11ca_active_remove
++#define pk11_free_active_list pk11ca_free_active_list
++#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv
++#define pk11_load_privkey pk11ca_load_privkey
++#define pk11_load_pubkey pk11ca_load_pubkey
++#define PK11_RSA PK11CA_RSA
++#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv
++#define PK11_DSA PK11CA_DSA
++#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11ca_destroy_dh_object
++#define PK11_DH PK11CA_DH
++#define pk11_token_relogin pk11ca_token_relogin
++#define pFuncList pk11ca_pFuncList
++#define pk11_pin pk11ca_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11ca
+Index: openssl/crypto/engine/hw_pk11so.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.7.4.1
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:33:56 2013
+@@ -0,0 +1,1775 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/*#undef DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_DSA
++#define OPENSSL_NO_DSA
++#endif
++#ifndef OPENSSL_NO_DH
++#define OPENSSL_NO_DH
++#endif
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.c"
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++static int pk11_choose_slots(int *any_slot_found);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11CA
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name = "PKCS #11 engine support (sign only)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name))
++ return (0);
++
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++ (void) pk11_destroy_rsa_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ if (optype == OP_RSA)
++ {
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_PKCS
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ CK_SLOT_ID current_slot = 0;
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * Check if this slot is capable of signing with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN)))
++ {
++ slot_has_rsa = CK_TRUE;
++ }
++
++ if (!found_candidate_slot && slot_has_rsa)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ /*SLOTID = pSlotList[0];*/
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11so.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.4
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:20 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */
++
++#define token_lock pk11so_token_lock
++#define find_lock pk11so_find_lock
++#define active_list pk11so_active_list
++#define pubkey_token_flags pk11so_pubkey_token_flags
++#define pubkey_SLOTID pk11so_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11so_error
++#define PK11err_add_data PK11SOerr_add_data
++#define pk11_get_session pk11so_get_session
++#define pk11_return_session pk11so_return_session
++#define pk11_active_add pk11so_active_add
++#define pk11_active_delete pk11so_active_delete
++#define pk11_active_remove pk11so_active_remove
++#define pk11_free_active_list pk11so_free_active_list
++#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv
++#define pk11_load_privkey pk11so_load_privkey
++#define pk11_load_pubkey pk11so_load_pubkey
++#define PK11_RSA PK11SO_RSA
++#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv
++#define PK11_DSA PK11SO_DSA
++#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11so_destroy_dh_object
++#define PK11_DH PK11SO_DH
++#define pk11_token_relogin pk11so_token_relogin
++#define pFuncList pk11so_pFuncList
++#define pk11_pin pk11so_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11so
+Index: openssl/crypto/engine/hw_pk11so_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.8.2.2
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:33:56 2013
+@@ -0,0 +1,1642 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++/* RSA stuff */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa;
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ const RSA_METHOD *rsa;
++
++ if (pk11_rsa.name == NULL)
++ {
++ rsa = RSA_PKCS1_SSLeay();
++ memcpy(&pk11_rsa, rsa, sizeof(*rsa));
++ pk11_rsa.name = "PKCS#11 RSA method";
++ pk11_rsa.rsa_sign = pk11_RSA_sign;
++ }
++ return (&pk11_rsa);
++ }
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/pkcs11.h
+diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,299 @@
++/* pkcs11.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++#ifndef _PKCS11_H_
++#define _PKCS11_H_ 1
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Before including this file (pkcs11.h) (or pkcs11t.h by
++ * itself), 6 platform-specific macros must be defined. These
++ * macros are described below, and typical definitions for them
++ * are also given. Be advised that these definitions can depend
++ * on both the platform and the compiler used (and possibly also
++ * on whether a Cryptoki library is linked statically or
++ * dynamically).
++ *
++ * In addition to defining these 6 macros, the packing convention
++ * for Cryptoki structures should be set. The Cryptoki
++ * convention on packing is that structures should be 1-byte
++ * aligned.
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, this might be done by using the following
++ * preprocessor directive before including pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(push, cryptoki, 1)
++ *
++ * and using the following preprocessor directive after including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(pop, cryptoki)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, this might be done by using
++ * the following preprocessor directive before including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(1)
++ *
++ * In a UNIX environment, you're on your own for this. You might
++ * not need to do (or be able to do!) anything.
++ *
++ *
++ * Now for the macros:
++ *
++ *
++ * 1. CK_PTR: The indirection string for making a pointer to an
++ * object. It can be used like this:
++ *
++ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, it might be defined by:
++ *
++ * #define CK_PTR far *
++ *
++ * In a typical UNIX environment, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ *
++ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
++ * an exportable Cryptoki library function definition out of a
++ * return type and a function name. It should be used in the
++ * following fashion to define the exposed Cryptoki functions in
++ * a Cryptoki library:
++ *
++ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * )
++ * {
++ * ...
++ * }
++ *
++ * If you're using Microsoft Developer Studio 5.0 to define a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllexport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to define a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
++ * an importable Cryptoki library function declaration out of a
++ * return type and a function name. It should be used in the
++ * following fashion:
++ *
++ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * );
++ *
++ * If you're using Microsoft Developer Studio 5.0 to declare a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllimport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to declare a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
++ * which makes a Cryptoki API function pointer declaration or
++ * function pointer type declaration out of a return type and a
++ * function name. It should be used in the following fashion:
++ *
++ * // Define funcPtr to be a pointer to a Cryptoki API function
++ * // taking arguments args and returning CK_RV.
++ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
++ *
++ * or
++ *
++ * // Define funcPtrType to be the type of a pointer to a
++ * // Cryptoki API function taking arguments args and returning
++ * // CK_RV, and then define funcPtr to be a variable of type
++ * // funcPtrType.
++ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
++ * funcPtrType funcPtr;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to access
++ * functions in a Win32 Cryptoki .dll, in might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __declspec(dllimport) (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to access functions in a Win16 Cryptoki .dll, it might
++ * be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __export _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
++ * a function pointer type for an application callback out of
++ * a return type for the callback and a name for the callback.
++ * It should be used in the following fashion:
++ *
++ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
++ *
++ * to declare a function pointer, myCallback, to a callback
++ * which takes arguments args and returns a CK_RV. It can also
++ * be used like this:
++ *
++ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
++ * myCallbackType myCallback;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to do Win32
++ * Cryptoki development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to do Win16 development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 6. NULL_PTR: This macro is the value of a NULL pointer.
++ *
++ * In any ANSI/ISO C environment (and in many others as well),
++ * this should best be defined by
++ *
++ * #ifndef NULL_PTR
++ * #define NULL_PTR 0
++ * #endif
++ */
++
++
++/* All the various Cryptoki types and #define'd values are in the
++ * file pkcs11t.h. */
++#include "pkcs11t.h"
++
++#define __PASTE(x,y) x##y
++
++
++/* ==============================================================
++ * Define the "extern" form of all the entry points.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ extern CK_DECLARE_FUNCTION(CK_RV, name)
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define the typedef form of all the entry points. That is, for
++ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
++ * a pointer to that kind of function.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define structed vector of entry points. A CK_FUNCTION_LIST
++ * contains a CK_VERSION indicating a library's Cryptoki version
++ * and then a whole slew of function pointers to the routines in
++ * the library. This type was declared, but not defined, in
++ * pkcs11t.h.
++ * ==============================================================
++ */
++
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ __PASTE(CK_,name) name;
++
++struct CK_FUNCTION_LIST {
++
++ CK_VERSION version; /* Cryptoki version */
++
++/* Pile all the function pointers into the CK_FUNCTION_LIST. */
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++};
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++#undef __PASTE
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+Index: openssl/crypto/engine/pkcs11f.h
+diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,912 @@
++/* pkcs11f.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This header file contains pretty much everything about all the */
++/* Cryptoki function prototypes. Because this information is */
++/* used for more than just declaring function prototypes, the */
++/* order of the functions appearing herein is important, and */
++/* should not be altered. */
++
++/* General-purpose */
++
++/* C_Initialize initializes the Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Initialize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
++ * cast to CK_C_INITIALIZE_ARGS_PTR
++ * and dereferenced */
++);
++#endif
++
++
++/* C_Finalize indicates that an application is done with the
++ * Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Finalize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
++);
++#endif
++
++
++/* C_GetInfo returns general information about Cryptoki. */
++CK_PKCS11_FUNCTION_INFO(C_GetInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_INFO_PTR pInfo /* location that receives information */
++);
++#endif
++
++
++/* C_GetFunctionList returns the function list. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
++ * function list */
++);
++#endif
++
++
++
++/* Slot and token management */
++
++/* C_GetSlotList obtains a list of slots in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_BBOOL tokenPresent, /* only slots with tokens? */
++ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
++ CK_ULONG_PTR pulCount /* receives number of slots */
++);
++#endif
++
++
++/* C_GetSlotInfo obtains information about a particular slot in
++ * the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the ID of the slot */
++ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
++);
++#endif
++
++
++/* C_GetTokenInfo obtains information about a particular token
++ * in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
++);
++#endif
++
++
++/* C_GetMechanismList obtains a list of mechanism types
++ * supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of token's slot */
++ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
++ CK_ULONG_PTR pulCount /* gets # of mechs. */
++);
++#endif
++
++
++/* C_GetMechanismInfo obtains information about a particular
++ * mechanism possibly supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_MECHANISM_TYPE type, /* type of mechanism */
++ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
++);
++#endif
++
++
++/* C_InitToken initializes a token. */
++CK_PKCS11_FUNCTION_INFO(C_InitToken)
++#ifdef CK_NEED_ARG_LIST
++/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
++ CK_ULONG ulPinLen, /* length in bytes of the PIN */
++ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
++);
++#endif
++
++
++/* C_InitPIN initializes the normal user's PIN. */
++CK_PKCS11_FUNCTION_INFO(C_InitPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
++ CK_ULONG ulPinLen /* length in bytes of the PIN */
++);
++#endif
++
++
++/* C_SetPIN modifies the PIN of the user who is logged in. */
++CK_PKCS11_FUNCTION_INFO(C_SetPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
++ CK_ULONG ulOldLen, /* length of the old PIN */
++ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
++ CK_ULONG ulNewLen /* length of the new PIN */
++);
++#endif
++
++
++
++/* Session management */
++
++/* C_OpenSession opens a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_OpenSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the slot's ID */
++ CK_FLAGS flags, /* from CK_SESSION_INFO */
++ CK_VOID_PTR pApplication, /* passed to callback */
++ CK_NOTIFY Notify, /* callback function */
++ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
++);
++#endif
++
++
++/* C_CloseSession closes a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CloseAllSessions closes all sessions with a token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID /* the token's slot */
++);
++#endif
++
++
++/* C_GetSessionInfo obtains information about the session. */
++CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_SESSION_INFO_PTR pInfo /* receives session info */
++);
++#endif
++
++
++/* C_GetOperationState obtains the state of the cryptographic operation
++ * in a session. */
++CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* gets state */
++ CK_ULONG_PTR pulOperationStateLen /* gets state length */
++);
++#endif
++
++
++/* C_SetOperationState restores the state of the cryptographic
++ * operation in a session. */
++CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* holds state */
++ CK_ULONG ulOperationStateLen, /* holds state length */
++ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
++ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
++);
++#endif
++
++
++/* C_Login logs a user into a token. */
++CK_PKCS11_FUNCTION_INFO(C_Login)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_USER_TYPE userType, /* the user type */
++ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
++ CK_ULONG ulPinLen /* the length of the PIN */
++);
++#endif
++
++
++/* C_Logout logs a user out from a token. */
++CK_PKCS11_FUNCTION_INFO(C_Logout)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Object management */
++
++/* C_CreateObject creates a new object. */
++CK_PKCS11_FUNCTION_INFO(C_CreateObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
++);
++#endif
++
++
++/* C_CopyObject copies an object, creating a new object for the
++ * copy. */
++CK_PKCS11_FUNCTION_INFO(C_CopyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
++);
++#endif
++
++
++/* C_DestroyObject destroys an object. */
++CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject /* the object's handle */
++);
++#endif
++
++
++/* C_GetObjectSize gets the size of an object in bytes. */
++CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ULONG_PTR pulSize /* receives size of object */
++);
++#endif
++
++
++/* C_GetAttributeValue obtains the value of one or more object
++ * attributes. */
++CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_SetAttributeValue modifies the value of one or more object
++ * attributes */
++CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_FindObjectsInit initializes a search for token and session
++ * objects that match a template. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
++ CK_ULONG ulCount /* attrs in search template */
++);
++#endif
++
++
++/* C_FindObjects continues a search for token and session
++ * objects that match a template, obtaining additional object
++ * handles. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjects)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
++ CK_ULONG ulMaxObjectCount, /* max handles to get */
++ CK_ULONG_PTR pulObjectCount /* actual # returned */
++);
++#endif
++
++
++/* C_FindObjectsFinal finishes a search for token and session
++ * objects. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Encryption and decryption */
++
++/* C_EncryptInit initializes an encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of encryption key */
++);
++#endif
++
++
++/* C_Encrypt encrypts single-part data. */
++CK_PKCS11_FUNCTION_INFO(C_Encrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pData, /* the plaintext data */
++ CK_ULONG ulDataLen, /* bytes of plaintext */
++ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptUpdate continues a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext data len */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptFinal finishes a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session handle */
++ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
++ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
++);
++#endif
++
++
++/* C_DecryptInit initializes a decryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of decryption key */
++);
++#endif
++
++
++/* C_Decrypt decrypts encrypted data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Decrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedData, /* ciphertext */
++ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
++ CK_BYTE_PTR pData, /* gets plaintext */
++ CK_ULONG_PTR pulDataLen /* gets p-text size */
++);
++#endif
++
++
++/* C_DecryptUpdate continues a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
++ CK_ULONG ulEncryptedPartLen, /* input length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* p-text size */
++);
++#endif
++
++
++/* C_DecryptFinal finishes a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pLastPart, /* gets plaintext */
++ CK_ULONG_PTR pulLastPartLen /* p-text size */
++);
++#endif
++
++
++
++/* Message digesting */
++
++/* C_DigestInit initializes a message-digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
++);
++#endif
++
++
++/* C_Digest digests data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Digest)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* data to be digested */
++ CK_ULONG ulDataLen, /* bytes of data to digest */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets digest length */
++);
++#endif
++
++
++/* C_DigestUpdate continues a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* data to be digested */
++ CK_ULONG ulPartLen /* bytes of data to be digested */
++);
++#endif
++
++
++/* C_DigestKey continues a multi-part message-digesting
++ * operation, by digesting the value of a secret key as part of
++ * the data already digested. */
++CK_PKCS11_FUNCTION_INFO(C_DigestKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hKey /* secret key to digest */
++);
++#endif
++
++
++/* C_DigestFinal finishes a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
++);
++#endif
++
++
++
++/* Signing and MACing */
++
++/* C_SignInit initializes a signature (private key encryption)
++ * operation, where the signature is (will be) an appendix to
++ * the data, and plaintext cannot be recovered from the
++ *signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of signature key */
++);
++#endif
++
++
++/* C_Sign signs (encrypts with private key) data in a single
++ * part, where the signature is (will be) an appendix to the
++ * data, and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Sign)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignUpdate continues a multiple-part signature operation,
++ * where the signature is (will be) an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* the data to sign */
++ CK_ULONG ulPartLen /* count of bytes to sign */
++);
++#endif
++
++
++/* C_SignFinal finishes a multiple-part signature operation,
++ * returning the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignRecoverInit initializes a signature operation, where
++ * the data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of the signature key */
++);
++#endif
++
++
++/* C_SignRecover signs data in a single operation, where the
++ * data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++
++/* Verifying signatures and MACs */
++
++/* C_VerifyInit initializes a verification operation, where the
++ * signature is an appendix to the data, and plaintext cannot
++ * cannot be recovered from the signature (e.g. DSA). */
++CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_Verify verifies a signature in a single-part operation,
++ * where the signature is an appendix to the data, and plaintext
++ * cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Verify)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* signed data */
++ CK_ULONG ulDataLen, /* length of signed data */
++ CK_BYTE_PTR pSignature, /* signature */
++ CK_ULONG ulSignatureLen /* signature length*/
++);
++#endif
++
++
++/* C_VerifyUpdate continues a multiple-part verification
++ * operation, where the signature is an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* signed data */
++ CK_ULONG ulPartLen /* length of signed data */
++);
++#endif
++
++
++/* C_VerifyFinal finishes a multiple-part verification
++ * operation, checking the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen /* signature length */
++);
++#endif
++
++
++/* C_VerifyRecoverInit initializes a signature verification
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_VerifyRecover verifies a signature in a single-part
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen, /* signature length */
++ CK_BYTE_PTR pData, /* gets signed data */
++ CK_ULONG_PTR pulDataLen /* gets signed data len */
++);
++#endif
++
++
++
++/* Dual-function cryptographic operations */
++
++/* C_DigestEncryptUpdate continues a multiple-part digesting
++ * and encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptDigestUpdate continues a multiple-part decryption and
++ * digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets plaintext len */
++);
++#endif
++
++
++/* C_SignEncryptUpdate continues a multiple-part signing and
++ * encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptVerifyUpdate continues a multiple-part decryption and
++ * verify operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets p-text length */
++);
++#endif
++
++
++
++/* Key management */
++
++/* C_GenerateKey generates a secret key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
++ CK_ULONG ulCount, /* # of attrs in template */
++ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
++);
++#endif
++
++
++/* C_GenerateKeyPair generates a public-key/private-key pair,
++ * creating new key objects. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session
++ * handle */
++ CK_MECHANISM_PTR pMechanism, /* key-gen
++ * mech. */
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
++ * for pub.
++ * key */
++ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
++ * attrs. */
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
++ * for priv.
++ * key */
++ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
++ * attrs. */
++ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
++ * key
++ * handle */
++ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
++ * priv. key
++ * handle */
++);
++#endif
++
++
++/* C_WrapKey wraps (i.e., encrypts) a key. */
++CK_PKCS11_FUNCTION_INFO(C_WrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
++ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
++ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
++ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
++ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
++);
++#endif
++
++
++/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
++ * key object. */
++CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
++ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
++ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
++ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++/* C_DeriveKey derives a key from a base key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
++ CK_OBJECT_HANDLE hBaseKey, /* base key */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++
++/* Random number generation */
++
++/* C_SeedRandom mixes additional seed material into the token's
++ * random number generator. */
++CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSeed, /* the seed material */
++ CK_ULONG ulSeedLen /* length of seed material */
++);
++#endif
++
++
++/* C_GenerateRandom generates random data. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR RandomData, /* receives the random data */
++ CK_ULONG ulRandomLen /* # of bytes to generate */
++);
++#endif
++
++
++
++/* Parallel function management */
++
++/* C_GetFunctionStatus is a legacy function; it obtains an
++ * updated status of a function running in parallel with an
++ * application. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CancelFunction is a legacy function; it cancels a function
++ * running in parallel. */
++CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Functions added in for Cryptoki Version 2.01 or later */
++
++/* C_WaitForSlotEvent waits for a slot event (token insertion,
++ * removal, etc.) to occur. */
++CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FLAGS flags, /* blocking/nonblocking flag */
++ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
++ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
++);
++#endif
+Index: openssl/crypto/engine/pkcs11t.h
+diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2
+--- /dev/null Wed Dec 23 17:47:11 2015
++++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008
+@@ -0,0 +1,1885 @@
++/* pkcs11t.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* See top of pkcs11.h for information about the macros that
++ * must be defined and the structure-packing conventions that
++ * must be set before including this file. */
++
++#ifndef _PKCS11T_H_
++#define _PKCS11T_H_ 1
++
++#define CRYPTOKI_VERSION_MAJOR 2
++#define CRYPTOKI_VERSION_MINOR 20
++#define CRYPTOKI_VERSION_AMENDMENT 3
++
++#define CK_TRUE 1
++#define CK_FALSE 0
++
++#ifndef CK_DISABLE_TRUE_FALSE
++#ifndef FALSE
++#define FALSE CK_FALSE
++#endif
++
++#ifndef TRUE
++#define TRUE CK_TRUE
++#endif
++#endif
++
++/* an unsigned 8-bit value */
++typedef unsigned char CK_BYTE;
++
++/* an unsigned 8-bit character */
++typedef CK_BYTE CK_CHAR;
++
++/* an 8-bit UTF-8 character */
++typedef CK_BYTE CK_UTF8CHAR;
++
++/* a BYTE-sized Boolean flag */
++typedef CK_BYTE CK_BBOOL;
++
++/* an unsigned value, at least 32 bits long */
++typedef unsigned long int CK_ULONG;
++
++/* a signed value, the same size as a CK_ULONG */
++/* CK_LONG is new for v2.0 */
++typedef long int CK_LONG;
++
++/* at least 32 bits; each bit is a Boolean flag */
++typedef CK_ULONG CK_FLAGS;
++
++
++/* some special values for certain CK_ULONG variables */
++#define CK_UNAVAILABLE_INFORMATION (~0UL)
++#define CK_EFFECTIVELY_INFINITE 0
++
++
++typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++typedef CK_CHAR CK_PTR CK_CHAR_PTR;
++typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
++typedef CK_ULONG CK_PTR CK_ULONG_PTR;
++typedef void CK_PTR CK_VOID_PTR;
++
++/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
++typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
++
++
++/* The following value is always invalid if used as a session */
++/* handle or object handle */
++#define CK_INVALID_HANDLE 0
++
++
++typedef struct CK_VERSION {
++ CK_BYTE major; /* integer portion of version number */
++ CK_BYTE minor; /* 1/100ths portion of version number */
++} CK_VERSION;
++
++typedef CK_VERSION CK_PTR CK_VERSION_PTR;
++
++
++typedef struct CK_INFO {
++ /* manufacturerID and libraryDecription have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags; /* must be zero */
++
++ /* libraryDescription and libraryVersion are new for v2.0 */
++ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
++ CK_VERSION libraryVersion; /* version of library */
++} CK_INFO;
++
++typedef CK_INFO CK_PTR CK_INFO_PTR;
++
++
++/* CK_NOTIFICATION enumerates the types of notifications that
++ * Cryptoki provides to an application */
++/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_NOTIFICATION;
++#define CKN_SURRENDER 0
++
++/* The following notification is new for PKCS #11 v2.20 amendment 3 */
++#define CKN_OTP_CHANGED 1
++
++
++typedef CK_ULONG CK_SLOT_ID;
++
++typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
++
++
++/* CK_SLOT_INFO provides information about a slot */
++typedef struct CK_SLOT_INFO {
++ /* slotDescription and manufacturerID have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR slotDescription[64]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags;
++
++ /* hardwareVersion and firmwareVersion are new for v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++} CK_SLOT_INFO;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
++#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
++#define CKF_HW_SLOT 0x00000004 /* hardware slot */
++
++typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
++
++
++/* CK_TOKEN_INFO provides information about a token */
++typedef struct CK_TOKEN_INFO {
++ /* label, manufacturerID, and model have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR label[32]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_UTF8CHAR model[16]; /* blank padded */
++ CK_CHAR serialNumber[16]; /* blank padded */
++ CK_FLAGS flags; /* see below */
++
++ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
++ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
++ * changed from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulMaxSessionCount; /* max open sessions */
++ CK_ULONG ulSessionCount; /* sess. now open */
++ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
++ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
++ CK_ULONG ulMaxPinLen; /* in bytes */
++ CK_ULONG ulMinPinLen; /* in bytes */
++ CK_ULONG ulTotalPublicMemory; /* in bytes */
++ CK_ULONG ulFreePublicMemory; /* in bytes */
++ CK_ULONG ulTotalPrivateMemory; /* in bytes */
++ CK_ULONG ulFreePrivateMemory; /* in bytes */
++
++ /* hardwareVersion, firmwareVersion, and time are new for
++ * v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++ CK_CHAR utcTime[16]; /* time */
++} CK_TOKEN_INFO;
++
++/* The flags parameter is defined as follows:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RNG 0x00000001 /* has random #
++ * generator */
++#define CKF_WRITE_PROTECTED 0x00000002 /* token is
++ * write-
++ * protected */
++#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
++ * login */
++#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
++ * PIN is set */
++
++/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
++ * that means that *every* time the state of cryptographic
++ * operations of a session is successfully saved, all keys
++ * needed to continue those operations are stored in the state */
++#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
++
++/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
++ * that the token has some sort of clock. The time on that
++ * clock is returned in the token info structure */
++#define CKF_CLOCK_ON_TOKEN 0x00000040
++
++/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
++ * set, that means that there is some way for the user to login
++ * without sending a PIN through the Cryptoki library itself */
++#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
++
++/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
++ * that means that a single session with the token can perform
++ * dual simultaneous cryptographic operations (digest and
++ * encrypt; decrypt and digest; sign and encrypt; and decrypt
++ * and sign) */
++#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
++
++/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
++ * token has been initialized using C_InitializeToken or an
++ * equivalent mechanism outside the scope of PKCS #11.
++ * Calling C_InitializeToken when this flag is set will cause
++ * the token to be reinitialized. */
++#define CKF_TOKEN_INITIALIZED 0x00000400
++
++/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
++ * true, the token supports secondary authentication for
++ * private key objects. This flag is deprecated in v2.11 and
++ onwards. */
++#define CKF_SECONDARY_AUTHENTICATION 0x00000800
++
++/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect user login PIN has been entered at least once
++ * since the last successful authentication. */
++#define CKF_USER_PIN_COUNT_LOW 0x00010000
++
++/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect user PIN will it to become locked. */
++#define CKF_USER_PIN_FINAL_TRY 0x00020000
++
++/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
++ * user PIN has been locked. User login to the token is not
++ * possible. */
++#define CKF_USER_PIN_LOCKED 0x00040000
++
++/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the user PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
++
++/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect SO login PIN has been entered at least once since
++ * the last successful authentication. */
++#define CKF_SO_PIN_COUNT_LOW 0x00100000
++
++/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect SO PIN will it to become locked. */
++#define CKF_SO_PIN_FINAL_TRY 0x00200000
++
++/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
++ * PIN has been locked. SO login to the token is not possible.
++ */
++#define CKF_SO_PIN_LOCKED 0x00400000
++
++/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the SO PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
++
++typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
++
++
++/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
++ * identifies a session */
++typedef CK_ULONG CK_SESSION_HANDLE;
++
++typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
++
++
++/* CK_USER_TYPE enumerates the types of Cryptoki users */
++/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_USER_TYPE;
++/* Security Officer */
++#define CKU_SO 0
++/* Normal user */
++#define CKU_USER 1
++/* Context specific (added in v2.20) */
++#define CKU_CONTEXT_SPECIFIC 2
++
++/* CK_STATE enumerates the session states */
++/* CK_STATE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_STATE;
++#define CKS_RO_PUBLIC_SESSION 0
++#define CKS_RO_USER_FUNCTIONS 1
++#define CKS_RW_PUBLIC_SESSION 2
++#define CKS_RW_USER_FUNCTIONS 3
++#define CKS_RW_SO_FUNCTIONS 4
++
++
++/* CK_SESSION_INFO provides information about a session */
++typedef struct CK_SESSION_INFO {
++ CK_SLOT_ID slotID;
++ CK_STATE state;
++ CK_FLAGS flags; /* see below */
++
++ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulDeviceError; /* device-dependent error code */
++} CK_SESSION_INFO;
++
++/* The flags are defined in the following table:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RW_SESSION 0x00000002 /* session is r/w */
++#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
++
++typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
++
++
++/* CK_OBJECT_HANDLE is a token-specific identifier for an
++ * object */
++typedef CK_ULONG CK_OBJECT_HANDLE;
++
++typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
++
++
++/* CK_OBJECT_CLASS is a value that identifies the classes (or
++ * types) of objects that Cryptoki recognizes. It is defined
++ * as follows: */
++/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_OBJECT_CLASS;
++
++/* The following classes of objects are defined: */
++/* CKO_HW_FEATURE is new for v2.10 */
++/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
++/* CKO_MECHANISM is new for v2.20 */
++#define CKO_DATA 0x00000000
++#define CKO_CERTIFICATE 0x00000001
++#define CKO_PUBLIC_KEY 0x00000002
++#define CKO_PRIVATE_KEY 0x00000003
++#define CKO_SECRET_KEY 0x00000004
++#define CKO_HW_FEATURE 0x00000005
++#define CKO_DOMAIN_PARAMETERS 0x00000006
++#define CKO_MECHANISM 0x00000007
++
++/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */
++#define CKO_OTP_KEY 0x00000008
++
++#define CKO_VENDOR_DEFINED 0x80000000
++
++typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
++
++/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
++ * value that identifies the hardware feature type of an object
++ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
++typedef CK_ULONG CK_HW_FEATURE_TYPE;
++
++/* The following hardware feature types are defined */
++/* CKH_USER_INTERFACE is new for v2.20 */
++#define CKH_MONOTONIC_COUNTER 0x00000001
++#define CKH_CLOCK 0x00000002
++#define CKH_USER_INTERFACE 0x00000003
++#define CKH_VENDOR_DEFINED 0x80000000
++
++/* CK_KEY_TYPE is a value that identifies a key type */
++/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_KEY_TYPE;
++
++/* the following key types are defined: */
++#define CKK_RSA 0x00000000
++#define CKK_DSA 0x00000001
++#define CKK_DH 0x00000002
++
++/* CKK_ECDSA and CKK_KEA are new for v2.0 */
++/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
++#define CKK_ECDSA 0x00000003
++#define CKK_EC 0x00000003
++#define CKK_X9_42_DH 0x00000004
++#define CKK_KEA 0x00000005
++
++#define CKK_GENERIC_SECRET 0x00000010
++#define CKK_RC2 0x00000011
++#define CKK_RC4 0x00000012
++#define CKK_DES 0x00000013
++#define CKK_DES2 0x00000014
++#define CKK_DES3 0x00000015
++
++/* all these key types are new for v2.0 */
++#define CKK_CAST 0x00000016
++#define CKK_CAST3 0x00000017
++/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
++#define CKK_CAST5 0x00000018
++#define CKK_CAST128 0x00000018
++#define CKK_RC5 0x00000019
++#define CKK_IDEA 0x0000001A
++#define CKK_SKIPJACK 0x0000001B
++#define CKK_BATON 0x0000001C
++#define CKK_JUNIPER 0x0000001D
++#define CKK_CDMF 0x0000001E
++#define CKK_AES 0x0000001F
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKK_BLOWFISH 0x00000020
++#define CKK_TWOFISH 0x00000021
++
++/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */
++#define CKK_SECURID 0x00000022
++#define CKK_HOTP 0x00000023
++#define CKK_ACTI 0x00000024
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_CAMELLIA 0x00000025
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_ARIA 0x00000026
++
++
++#define CKK_VENDOR_DEFINED 0x80000000
++
++
++/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
++ * type */
++/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_CERTIFICATE_TYPE;
++
++/* The following certificate types are defined: */
++/* CKC_X_509_ATTR_CERT is new for v2.10 */
++/* CKC_WTLS is new for v2.20 */
++#define CKC_X_509 0x00000000
++#define CKC_X_509_ATTR_CERT 0x00000001
++#define CKC_WTLS 0x00000002
++#define CKC_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
++ * type */
++/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_ATTRIBUTE_TYPE;
++
++/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
++ consists of an array of values. */
++#define CKF_ARRAY_ATTRIBUTE 0x40000000
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_FORMAT attribute */
++#define CK_OTP_FORMAT_DECIMAL 0
++#define CK_OTP_FORMAT_HEXADECIMAL 1
++#define CK_OTP_FORMAT_ALPHANUMERIC 2
++#define CK_OTP_FORMAT_BINARY 3
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_..._REQUIREMENT attributes */
++#define CK_OTP_PARAM_IGNORED 0
++#define CK_OTP_PARAM_OPTIONAL 1
++#define CK_OTP_PARAM_MANDATORY 2
++
++/* The following attribute types are defined: */
++#define CKA_CLASS 0x00000000
++#define CKA_TOKEN 0x00000001
++#define CKA_PRIVATE 0x00000002
++#define CKA_LABEL 0x00000003
++#define CKA_APPLICATION 0x00000010
++#define CKA_VALUE 0x00000011
++
++/* CKA_OBJECT_ID is new for v2.10 */
++#define CKA_OBJECT_ID 0x00000012
++
++#define CKA_CERTIFICATE_TYPE 0x00000080
++#define CKA_ISSUER 0x00000081
++#define CKA_SERIAL_NUMBER 0x00000082
++
++/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
++ * for v2.10 */
++#define CKA_AC_ISSUER 0x00000083
++#define CKA_OWNER 0x00000084
++#define CKA_ATTR_TYPES 0x00000085
++
++/* CKA_TRUSTED is new for v2.11 */
++#define CKA_TRUSTED 0x00000086
++
++/* CKA_CERTIFICATE_CATEGORY ...
++ * CKA_CHECK_VALUE are new for v2.20 */
++#define CKA_CERTIFICATE_CATEGORY 0x00000087
++#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
++#define CKA_URL 0x00000089
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
++#define CKA_CHECK_VALUE 0x00000090
++
++#define CKA_KEY_TYPE 0x00000100
++#define CKA_SUBJECT 0x00000101
++#define CKA_ID 0x00000102
++#define CKA_SENSITIVE 0x00000103
++#define CKA_ENCRYPT 0x00000104
++#define CKA_DECRYPT 0x00000105
++#define CKA_WRAP 0x00000106
++#define CKA_UNWRAP 0x00000107
++#define CKA_SIGN 0x00000108
++#define CKA_SIGN_RECOVER 0x00000109
++#define CKA_VERIFY 0x0000010A
++#define CKA_VERIFY_RECOVER 0x0000010B
++#define CKA_DERIVE 0x0000010C
++#define CKA_START_DATE 0x00000110
++#define CKA_END_DATE 0x00000111
++#define CKA_MODULUS 0x00000120
++#define CKA_MODULUS_BITS 0x00000121
++#define CKA_PUBLIC_EXPONENT 0x00000122
++#define CKA_PRIVATE_EXPONENT 0x00000123
++#define CKA_PRIME_1 0x00000124
++#define CKA_PRIME_2 0x00000125
++#define CKA_EXPONENT_1 0x00000126
++#define CKA_EXPONENT_2 0x00000127
++#define CKA_COEFFICIENT 0x00000128
++#define CKA_PRIME 0x00000130
++#define CKA_SUBPRIME 0x00000131
++#define CKA_BASE 0x00000132
++
++/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
++#define CKA_PRIME_BITS 0x00000133
++#define CKA_SUBPRIME_BITS 0x00000134
++#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
++/* (To retain backwards-compatibility) */
++
++#define CKA_VALUE_BITS 0x00000160
++#define CKA_VALUE_LEN 0x00000161
++
++/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
++ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
++ * and CKA_EC_POINT are new for v2.0 */
++#define CKA_EXTRACTABLE 0x00000162
++#define CKA_LOCAL 0x00000163
++#define CKA_NEVER_EXTRACTABLE 0x00000164
++#define CKA_ALWAYS_SENSITIVE 0x00000165
++
++/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
++#define CKA_KEY_GEN_MECHANISM 0x00000166
++
++#define CKA_MODIFIABLE 0x00000170
++
++/* CKA_ECDSA_PARAMS is deprecated in v2.11,
++ * CKA_EC_PARAMS is preferred. */
++#define CKA_ECDSA_PARAMS 0x00000180
++#define CKA_EC_PARAMS 0x00000180
++
++#define CKA_EC_POINT 0x00000181
++
++/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
++ * are new for v2.10. Deprecated in v2.11 and onwards. */
++#define CKA_SECONDARY_AUTH 0x00000200
++#define CKA_AUTH_PIN_FLAGS 0x00000201
++
++/* CKA_ALWAYS_AUTHENTICATE ...
++ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
++#define CKA_ALWAYS_AUTHENTICATE 0x00000202
++
++#define CKA_WRAP_WITH_TRUSTED 0x00000210
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++
++/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */
++#define CKA_OTP_FORMAT 0x00000220
++#define CKA_OTP_LENGTH 0x00000221
++#define CKA_OTP_TIME_INTERVAL 0x00000222
++#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
++#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
++#define CKA_OTP_TIME_REQUIREMENT 0x00000225
++#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
++#define CKA_OTP_PIN_REQUIREMENT 0x00000227
++#define CKA_OTP_COUNTER 0x0000022E
++#define CKA_OTP_TIME 0x0000022F
++#define CKA_OTP_USER_IDENTIFIER 0x0000022A
++#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
++#define CKA_OTP_SERVICE_LOGO 0x0000022C
++#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
++
++
++/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
++ * are new for v2.10 */
++#define CKA_HW_FEATURE_TYPE 0x00000300
++#define CKA_RESET_ON_INIT 0x00000301
++#define CKA_HAS_RESET 0x00000302
++
++/* The following attributes are new for v2.20 */
++#define CKA_PIXEL_X 0x00000400
++#define CKA_PIXEL_Y 0x00000401
++#define CKA_RESOLUTION 0x00000402
++#define CKA_CHAR_ROWS 0x00000403
++#define CKA_CHAR_COLUMNS 0x00000404
++#define CKA_COLOR 0x00000405
++#define CKA_BITS_PER_PIXEL 0x00000406
++#define CKA_CHAR_SETS 0x00000480
++#define CKA_ENCODING_METHODS 0x00000481
++#define CKA_MIME_TYPES 0x00000482
++#define CKA_MECHANISM_TYPE 0x00000500
++#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
++#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
++#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
++#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
++
++#define CKA_VENDOR_DEFINED 0x80000000
++
++/* CK_ATTRIBUTE is a structure that includes the type, length
++ * and value of an attribute */
++typedef struct CK_ATTRIBUTE {
++ CK_ATTRIBUTE_TYPE type;
++ CK_VOID_PTR pValue;
++
++ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulValueLen; /* in bytes */
++} CK_ATTRIBUTE;
++
++typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
++
++
++/* CK_DATE is a structure that defines a date */
++typedef struct CK_DATE{
++ CK_CHAR year[4]; /* the year ("1900" - "9999") */
++ CK_CHAR month[2]; /* the month ("01" - "12") */
++ CK_CHAR day[2]; /* the day ("01" - "31") */
++} CK_DATE;
++
++
++/* CK_MECHANISM_TYPE is a value that identifies a mechanism
++ * type */
++/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_MECHANISM_TYPE;
++
++/* the following mechanism types are defined: */
++#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
++#define CKM_RSA_PKCS 0x00000001
++#define CKM_RSA_9796 0x00000002
++#define CKM_RSA_X_509 0x00000003
++
++/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
++ * are new for v2.0. They are mechanisms which hash and sign */
++#define CKM_MD2_RSA_PKCS 0x00000004
++#define CKM_MD5_RSA_PKCS 0x00000005
++#define CKM_SHA1_RSA_PKCS 0x00000006
++
++/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
++ * CKM_RSA_PKCS_OAEP are new for v2.10 */
++#define CKM_RIPEMD128_RSA_PKCS 0x00000007
++#define CKM_RIPEMD160_RSA_PKCS 0x00000008
++#define CKM_RSA_PKCS_OAEP 0x00000009
++
++/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
++ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
++#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
++#define CKM_RSA_X9_31 0x0000000B
++#define CKM_SHA1_RSA_X9_31 0x0000000C
++#define CKM_RSA_PKCS_PSS 0x0000000D
++#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
++
++#define CKM_DSA_KEY_PAIR_GEN 0x00000010
++#define CKM_DSA 0x00000011
++#define CKM_DSA_SHA1 0x00000012
++#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
++#define CKM_DH_PKCS_DERIVE 0x00000021
++
++/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
++ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
++ * v2.11 */
++#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
++#define CKM_X9_42_DH_DERIVE 0x00000031
++#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
++#define CKM_X9_42_MQV_DERIVE 0x00000033
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_RSA_PKCS 0x00000040
++#define CKM_SHA384_RSA_PKCS 0x00000041
++#define CKM_SHA512_RSA_PKCS 0x00000042
++#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
++#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
++#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
++
++/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_RSA_PKCS 0x00000046
++#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
++
++#define CKM_RC2_KEY_GEN 0x00000100
++#define CKM_RC2_ECB 0x00000101
++#define CKM_RC2_CBC 0x00000102
++#define CKM_RC2_MAC 0x00000103
++
++/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
++#define CKM_RC2_MAC_GENERAL 0x00000104
++#define CKM_RC2_CBC_PAD 0x00000105
++
++#define CKM_RC4_KEY_GEN 0x00000110
++#define CKM_RC4 0x00000111
++#define CKM_DES_KEY_GEN 0x00000120
++#define CKM_DES_ECB 0x00000121
++#define CKM_DES_CBC 0x00000122
++#define CKM_DES_MAC 0x00000123
++
++/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
++#define CKM_DES_MAC_GENERAL 0x00000124
++#define CKM_DES_CBC_PAD 0x00000125
++
++#define CKM_DES2_KEY_GEN 0x00000130
++#define CKM_DES3_KEY_GEN 0x00000131
++#define CKM_DES3_ECB 0x00000132
++#define CKM_DES3_CBC 0x00000133
++#define CKM_DES3_MAC 0x00000134
++
++/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
++ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
++ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
++#define CKM_DES3_MAC_GENERAL 0x00000135
++#define CKM_DES3_CBC_PAD 0x00000136
++#define CKM_CDMF_KEY_GEN 0x00000140
++#define CKM_CDMF_ECB 0x00000141
++#define CKM_CDMF_CBC 0x00000142
++#define CKM_CDMF_MAC 0x00000143
++#define CKM_CDMF_MAC_GENERAL 0x00000144
++#define CKM_CDMF_CBC_PAD 0x00000145
++
++/* the following four DES mechanisms are new for v2.20 */
++#define CKM_DES_OFB64 0x00000150
++#define CKM_DES_OFB8 0x00000151
++#define CKM_DES_CFB64 0x00000152
++#define CKM_DES_CFB8 0x00000153
++
++#define CKM_MD2 0x00000200
++
++/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD2_HMAC 0x00000201
++#define CKM_MD2_HMAC_GENERAL 0x00000202
++
++#define CKM_MD5 0x00000210
++
++/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD5_HMAC 0x00000211
++#define CKM_MD5_HMAC_GENERAL 0x00000212
++
++#define CKM_SHA_1 0x00000220
++
++/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
++#define CKM_SHA_1_HMAC 0x00000221
++#define CKM_SHA_1_HMAC_GENERAL 0x00000222
++
++/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
++ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
++ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
++#define CKM_RIPEMD128 0x00000230
++#define CKM_RIPEMD128_HMAC 0x00000231
++#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
++#define CKM_RIPEMD160 0x00000240
++#define CKM_RIPEMD160_HMAC 0x00000241
++#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256 0x00000250
++#define CKM_SHA256_HMAC 0x00000251
++#define CKM_SHA256_HMAC_GENERAL 0x00000252
++
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224 0x00000255
++#define CKM_SHA224_HMAC 0x00000256
++#define CKM_SHA224_HMAC_GENERAL 0x00000257
++
++#define CKM_SHA384 0x00000260
++#define CKM_SHA384_HMAC 0x00000261
++#define CKM_SHA384_HMAC_GENERAL 0x00000262
++#define CKM_SHA512 0x00000270
++#define CKM_SHA512_HMAC 0x00000271
++#define CKM_SHA512_HMAC_GENERAL 0x00000272
++
++/* SecurID is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_SECURID_KEY_GEN 0x00000280
++#define CKM_SECURID 0x00000282
++
++/* HOTP is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_HOTP_KEY_GEN 0x00000290
++#define CKM_HOTP 0x00000291
++
++/* ACTI is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_ACTI 0x000002A0
++#define CKM_ACTI_KEY_GEN 0x000002A1
++
++/* All of the following mechanisms are new for v2.0 */
++/* Note that CAST128 and CAST5 are the same algorithm */
++#define CKM_CAST_KEY_GEN 0x00000300
++#define CKM_CAST_ECB 0x00000301
++#define CKM_CAST_CBC 0x00000302
++#define CKM_CAST_MAC 0x00000303
++#define CKM_CAST_MAC_GENERAL 0x00000304
++#define CKM_CAST_CBC_PAD 0x00000305
++#define CKM_CAST3_KEY_GEN 0x00000310
++#define CKM_CAST3_ECB 0x00000311
++#define CKM_CAST3_CBC 0x00000312
++#define CKM_CAST3_MAC 0x00000313
++#define CKM_CAST3_MAC_GENERAL 0x00000314
++#define CKM_CAST3_CBC_PAD 0x00000315
++#define CKM_CAST5_KEY_GEN 0x00000320
++#define CKM_CAST128_KEY_GEN 0x00000320
++#define CKM_CAST5_ECB 0x00000321
++#define CKM_CAST128_ECB 0x00000321
++#define CKM_CAST5_CBC 0x00000322
++#define CKM_CAST128_CBC 0x00000322
++#define CKM_CAST5_MAC 0x00000323
++#define CKM_CAST128_MAC 0x00000323
++#define CKM_CAST5_MAC_GENERAL 0x00000324
++#define CKM_CAST128_MAC_GENERAL 0x00000324
++#define CKM_CAST5_CBC_PAD 0x00000325
++#define CKM_CAST128_CBC_PAD 0x00000325
++#define CKM_RC5_KEY_GEN 0x00000330
++#define CKM_RC5_ECB 0x00000331
++#define CKM_RC5_CBC 0x00000332
++#define CKM_RC5_MAC 0x00000333
++#define CKM_RC5_MAC_GENERAL 0x00000334
++#define CKM_RC5_CBC_PAD 0x00000335
++#define CKM_IDEA_KEY_GEN 0x00000340
++#define CKM_IDEA_ECB 0x00000341
++#define CKM_IDEA_CBC 0x00000342
++#define CKM_IDEA_MAC 0x00000343
++#define CKM_IDEA_MAC_GENERAL 0x00000344
++#define CKM_IDEA_CBC_PAD 0x00000345
++#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
++#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
++#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
++#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
++#define CKM_XOR_BASE_AND_DATA 0x00000364
++#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
++#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
++#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
++#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
++
++/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
++ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
++ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
++#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
++#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
++#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
++#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
++#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
++
++/* CKM_TLS_PRF is new for v2.20 */
++#define CKM_TLS_PRF 0x00000378
++
++#define CKM_SSL3_MD5_MAC 0x00000380
++#define CKM_SSL3_SHA1_MAC 0x00000381
++#define CKM_MD5_KEY_DERIVATION 0x00000390
++#define CKM_MD2_KEY_DERIVATION 0x00000391
++#define CKM_SHA1_KEY_DERIVATION 0x00000392
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_KEY_DERIVATION 0x00000393
++#define CKM_SHA384_KEY_DERIVATION 0x00000394
++#define CKM_SHA512_KEY_DERIVATION 0x00000395
++
++/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_KEY_DERIVATION 0x00000396
++
++#define CKM_PBE_MD2_DES_CBC 0x000003A0
++#define CKM_PBE_MD5_DES_CBC 0x000003A1
++#define CKM_PBE_MD5_CAST_CBC 0x000003A2
++#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
++#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
++#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
++#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
++#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
++#define CKM_PBE_SHA1_RC4_128 0x000003A6
++#define CKM_PBE_SHA1_RC4_40 0x000003A7
++#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
++#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
++#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
++#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
++
++/* CKM_PKCS5_PBKD2 is new for v2.10 */
++#define CKM_PKCS5_PBKD2 0x000003B0
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
++
++/* WTLS mechanisms are new for v2.20 */
++#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
++#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
++#define CKM_WTLS_PRF 0x000003D3
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
++
++#define CKM_KEY_WRAP_LYNKS 0x00000400
++#define CKM_KEY_WRAP_SET_OAEP 0x00000401
++
++/* CKM_CMS_SIG is new for v2.20 */
++#define CKM_CMS_SIG 0x00000500
++
++/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */
++#define CKM_KIP_DERIVE 0x00000510
++#define CKM_KIP_WRAP 0x00000511
++#define CKM_KIP_MAC 0x00000512
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_CAMELLIA_KEY_GEN 0x00000550
++#define CKM_CAMELLIA_ECB 0x00000551
++#define CKM_CAMELLIA_CBC 0x00000552
++#define CKM_CAMELLIA_MAC 0x00000553
++#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
++#define CKM_CAMELLIA_CBC_PAD 0x00000555
++#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
++#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
++#define CKM_CAMELLIA_CTR 0x00000558
++
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_ARIA_KEY_GEN 0x00000560
++#define CKM_ARIA_ECB 0x00000561
++#define CKM_ARIA_CBC 0x00000562
++#define CKM_ARIA_MAC 0x00000563
++#define CKM_ARIA_MAC_GENERAL 0x00000564
++#define CKM_ARIA_CBC_PAD 0x00000565
++#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
++#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
++
++/* Fortezza mechanisms */
++#define CKM_SKIPJACK_KEY_GEN 0x00001000
++#define CKM_SKIPJACK_ECB64 0x00001001
++#define CKM_SKIPJACK_CBC64 0x00001002
++#define CKM_SKIPJACK_OFB64 0x00001003
++#define CKM_SKIPJACK_CFB64 0x00001004
++#define CKM_SKIPJACK_CFB32 0x00001005
++#define CKM_SKIPJACK_CFB16 0x00001006
++#define CKM_SKIPJACK_CFB8 0x00001007
++#define CKM_SKIPJACK_WRAP 0x00001008
++#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
++#define CKM_SKIPJACK_RELAYX 0x0000100a
++#define CKM_KEA_KEY_PAIR_GEN 0x00001010
++#define CKM_KEA_KEY_DERIVE 0x00001011
++#define CKM_FORTEZZA_TIMESTAMP 0x00001020
++#define CKM_BATON_KEY_GEN 0x00001030
++#define CKM_BATON_ECB128 0x00001031
++#define CKM_BATON_ECB96 0x00001032
++#define CKM_BATON_CBC128 0x00001033
++#define CKM_BATON_COUNTER 0x00001034
++#define CKM_BATON_SHUFFLE 0x00001035
++#define CKM_BATON_WRAP 0x00001036
++
++/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
++ * CKM_EC_KEY_PAIR_GEN is preferred */
++#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
++#define CKM_EC_KEY_PAIR_GEN 0x00001040
++
++#define CKM_ECDSA 0x00001041
++#define CKM_ECDSA_SHA1 0x00001042
++
++/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
++ * are new for v2.11 */
++#define CKM_ECDH1_DERIVE 0x00001050
++#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
++#define CKM_ECMQV_DERIVE 0x00001052
++
++#define CKM_JUNIPER_KEY_GEN 0x00001060
++#define CKM_JUNIPER_ECB128 0x00001061
++#define CKM_JUNIPER_CBC128 0x00001062
++#define CKM_JUNIPER_COUNTER 0x00001063
++#define CKM_JUNIPER_SHUFFLE 0x00001064
++#define CKM_JUNIPER_WRAP 0x00001065
++#define CKM_FASTHASH 0x00001070
++
++/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
++ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
++ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
++ * new for v2.11 */
++#define CKM_AES_KEY_GEN 0x00001080
++#define CKM_AES_ECB 0x00001081
++#define CKM_AES_CBC 0x00001082
++#define CKM_AES_MAC 0x00001083
++#define CKM_AES_MAC_GENERAL 0x00001084
++#define CKM_AES_CBC_PAD 0x00001085
++
++/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_AES_CTR 0x00001086
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKM_BLOWFISH_KEY_GEN 0x00001090
++#define CKM_BLOWFISH_CBC 0x00001091
++#define CKM_TWOFISH_KEY_GEN 0x00001092
++#define CKM_TWOFISH_CBC 0x00001093
++
++
++/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
++#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
++#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
++#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
++#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
++#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
++#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
++
++#define CKM_DSA_PARAMETER_GEN 0x00002000
++#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
++#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
++
++#define CKM_VENDOR_DEFINED 0x80000000
++
++typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
++
++
++/* CK_MECHANISM is a structure that specifies a particular
++ * mechanism */
++typedef struct CK_MECHANISM {
++ CK_MECHANISM_TYPE mechanism;
++ CK_VOID_PTR pParameter;
++
++ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulParameterLen; /* in bytes */
++} CK_MECHANISM;
++
++typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
++
++
++/* CK_MECHANISM_INFO provides information about a particular
++ * mechanism */
++typedef struct CK_MECHANISM_INFO {
++ CK_ULONG ulMinKeySize;
++ CK_ULONG ulMaxKeySize;
++ CK_FLAGS flags;
++} CK_MECHANISM_INFO;
++
++/* The flags are defined as follows:
++ * Bit Flag Mask Meaning */
++#define CKF_HW 0x00000001 /* performed by HW */
++
++/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
++ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
++ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
++ * and CKF_DERIVE are new for v2.0. They specify whether or not
++ * a mechanism can be used for a particular task */
++#define CKF_ENCRYPT 0x00000100
++#define CKF_DECRYPT 0x00000200
++#define CKF_DIGEST 0x00000400
++#define CKF_SIGN 0x00000800
++#define CKF_SIGN_RECOVER 0x00001000
++#define CKF_VERIFY 0x00002000
++#define CKF_VERIFY_RECOVER 0x00004000
++#define CKF_GENERATE 0x00008000
++#define CKF_GENERATE_KEY_PAIR 0x00010000
++#define CKF_WRAP 0x00020000
++#define CKF_UNWRAP 0x00040000
++#define CKF_DERIVE 0x00080000
++
++/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
++ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
++ * describe a token's EC capabilities not available in mechanism
++ * information. */
++#define CKF_EC_F_P 0x00100000
++#define CKF_EC_F_2M 0x00200000
++#define CKF_EC_ECPARAMETERS 0x00400000
++#define CKF_EC_NAMEDCURVE 0x00800000
++#define CKF_EC_UNCOMPRESS 0x01000000
++#define CKF_EC_COMPRESS 0x02000000
++
++#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
++
++typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
++
++
++/* CK_RV is a value that identifies the return value of a
++ * Cryptoki function */
++/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_RV;
++
++#define CKR_OK 0x00000000
++#define CKR_CANCEL 0x00000001
++#define CKR_HOST_MEMORY 0x00000002
++#define CKR_SLOT_ID_INVALID 0x00000003
++
++/* CKR_FLAGS_INVALID was removed for v2.0 */
++
++/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
++#define CKR_GENERAL_ERROR 0x00000005
++#define CKR_FUNCTION_FAILED 0x00000006
++
++/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
++ * and CKR_CANT_LOCK are new for v2.01 */
++#define CKR_ARGUMENTS_BAD 0x00000007
++#define CKR_NO_EVENT 0x00000008
++#define CKR_NEED_TO_CREATE_THREADS 0x00000009
++#define CKR_CANT_LOCK 0x0000000A
++
++#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
++#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
++#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
++#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
++#define CKR_DATA_INVALID 0x00000020
++#define CKR_DATA_LEN_RANGE 0x00000021
++#define CKR_DEVICE_ERROR 0x00000030
++#define CKR_DEVICE_MEMORY 0x00000031
++#define CKR_DEVICE_REMOVED 0x00000032
++#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
++#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
++#define CKR_FUNCTION_CANCELED 0x00000050
++#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
++
++/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
++#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
++
++#define CKR_KEY_HANDLE_INVALID 0x00000060
++
++/* CKR_KEY_SENSITIVE was removed for v2.0 */
++
++#define CKR_KEY_SIZE_RANGE 0x00000062
++#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
++
++/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
++ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
++ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
++ * v2.0 */
++#define CKR_KEY_NOT_NEEDED 0x00000064
++#define CKR_KEY_CHANGED 0x00000065
++#define CKR_KEY_NEEDED 0x00000066
++#define CKR_KEY_INDIGESTIBLE 0x00000067
++#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
++#define CKR_KEY_NOT_WRAPPABLE 0x00000069
++#define CKR_KEY_UNEXTRACTABLE 0x0000006A
++
++#define CKR_MECHANISM_INVALID 0x00000070
++#define CKR_MECHANISM_PARAM_INVALID 0x00000071
++
++/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
++ * were removed for v2.0 */
++#define CKR_OBJECT_HANDLE_INVALID 0x00000082
++#define CKR_OPERATION_ACTIVE 0x00000090
++#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
++#define CKR_PIN_INCORRECT 0x000000A0
++#define CKR_PIN_INVALID 0x000000A1
++#define CKR_PIN_LEN_RANGE 0x000000A2
++
++/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
++#define CKR_PIN_EXPIRED 0x000000A3
++#define CKR_PIN_LOCKED 0x000000A4
++
++#define CKR_SESSION_CLOSED 0x000000B0
++#define CKR_SESSION_COUNT 0x000000B1
++#define CKR_SESSION_HANDLE_INVALID 0x000000B3
++#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
++#define CKR_SESSION_READ_ONLY 0x000000B5
++#define CKR_SESSION_EXISTS 0x000000B6
++
++/* CKR_SESSION_READ_ONLY_EXISTS and
++ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
++#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
++#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
++
++#define CKR_SIGNATURE_INVALID 0x000000C0
++#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
++#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
++#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
++#define CKR_TOKEN_NOT_PRESENT 0x000000E0
++#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
++#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
++#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
++#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
++#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
++#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
++#define CKR_USER_NOT_LOGGED_IN 0x00000101
++#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
++#define CKR_USER_TYPE_INVALID 0x00000103
++
++/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
++ * are new to v2.01 */
++#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
++#define CKR_USER_TOO_MANY_TYPES 0x00000105
++
++#define CKR_WRAPPED_KEY_INVALID 0x00000110
++#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
++#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
++#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
++#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
++#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
++
++/* These are new to v2.0 */
++#define CKR_RANDOM_NO_RNG 0x00000121
++
++/* These are new to v2.11 */
++#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
++
++/* These are new to v2.0 */
++#define CKR_BUFFER_TOO_SMALL 0x00000150
++#define CKR_SAVED_STATE_INVALID 0x00000160
++#define CKR_INFORMATION_SENSITIVE 0x00000170
++#define CKR_STATE_UNSAVEABLE 0x00000180
++
++/* These are new to v2.01 */
++#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
++#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
++#define CKR_MUTEX_BAD 0x000001A0
++#define CKR_MUTEX_NOT_LOCKED 0x000001A1
++
++/* The following return values are new for PKCS #11 v2.20 amendment 3 */
++#define CKR_NEW_PIN_MODE 0x000001B0
++#define CKR_NEXT_OTP 0x000001B1
++
++/* This is new to v2.20 */
++#define CKR_FUNCTION_REJECTED 0x00000200
++
++#define CKR_VENDOR_DEFINED 0x80000000
++
++
++/* CK_NOTIFY is an application callback that processes events */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication /* passed to C_OpenSession */
++);
++
++
++/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
++ * version and pointers of appropriate types to all the
++ * Cryptoki functions */
++/* CK_FUNCTION_LIST is new for v2.0 */
++typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
++
++typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
++
++typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
++
++
++/* CK_CREATEMUTEX is an application callback for creating a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
++ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
++);
++
++
++/* CK_DESTROYMUTEX is an application callback for destroying a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_LOCKMUTEX is an application callback for locking a mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_UNLOCKMUTEX is an application callback for unlocking a
++ * mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_C_INITIALIZE_ARGS provides the optional arguments to
++ * C_Initialize */
++typedef struct CK_C_INITIALIZE_ARGS {
++ CK_CREATEMUTEX CreateMutex;
++ CK_DESTROYMUTEX DestroyMutex;
++ CK_LOCKMUTEX LockMutex;
++ CK_UNLOCKMUTEX UnlockMutex;
++ CK_FLAGS flags;
++ CK_VOID_PTR pReserved;
++} CK_C_INITIALIZE_ARGS;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
++#define CKF_OS_LOCKING_OK 0x00000002
++
++typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
++
++
++/* additional flags for parameters to functions */
++
++/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
++#define CKF_DONT_BLOCK 1
++
++/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
++ * Generation Function (MGF) applied to a message block when
++ * formatting a message block for the PKCS #1 OAEP encryption
++ * scheme. */
++typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
++
++typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
++
++/* The following MGFs are defined */
++/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
++ * are new for v2.20 */
++#define CKG_MGF1_SHA1 0x00000001
++#define CKG_MGF1_SHA256 0x00000002
++#define CKG_MGF1_SHA384 0x00000003
++#define CKG_MGF1_SHA512 0x00000004
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKG_MGF1_SHA224 0x00000005
++
++/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
++ * of the encoding parameter when formatting a message block
++ * for the PKCS #1 OAEP encryption scheme. */
++typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
++
++typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
++
++/* The following encoding parameter sources are defined */
++#define CKZ_DATA_SPECIFIED 0x00000001
++
++/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
++ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_OAEP mechanism. */
++typedef struct CK_RSA_PKCS_OAEP_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
++ CK_VOID_PTR pSourceData;
++ CK_ULONG ulSourceDataLen;
++} CK_RSA_PKCS_OAEP_PARAMS;
++
++typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
++
++/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
++ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_PSS mechanism(s). */
++typedef struct CK_RSA_PKCS_PSS_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_ULONG sLen;
++} CK_RSA_PKCS_PSS_PARAMS;
++
++typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
++
++/* CK_EC_KDF_TYPE is new for v2.11. */
++typedef CK_ULONG CK_EC_KDF_TYPE;
++
++/* The following EC Key Derivation Functions are defined */
++#define CKD_NULL 0x00000001
++#define CKD_SHA1_KDF 0x00000002
++
++/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
++ * where each party contributes one key pair.
++ */
++typedef struct CK_ECDH1_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_ECDH1_DERIVE_PARAMS;
++
++typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
++
++
++/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
++typedef struct CK_ECDH2_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_ECDH2_DERIVE_PARAMS;
++
++typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_ECMQV_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_ECMQV_DERIVE_PARAMS;
++
++typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
++
++/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
++ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
++typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
++typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
++
++/* The following X9.42 DH key derivation functions are defined
++ (besides CKD_NULL already defined : */
++#define CKD_SHA1_KDF_ASN1 0x00000003
++#define CKD_SHA1_KDF_CONCATENATE 0x00000004
++
++/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
++ * contributes one key pair */
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_X9_42_DH1_DERIVE_PARAMS;
++
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
++
++/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
++ * mechanisms, where each party contributes two key pairs */
++typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_X9_42_DH2_DERIVE_PARAMS;
++
++typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_X9_42_MQV_DERIVE_PARAMS;
++
++typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
++
++/* CK_KEA_DERIVE_PARAMS provides the parameters to the
++ * CKM_KEA_DERIVE mechanism */
++/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
++typedef struct CK_KEA_DERIVE_PARAMS {
++ CK_BBOOL isSender;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pRandomB;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_KEA_DERIVE_PARAMS;
++
++typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
++
++
++/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
++ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
++ * holds the effective keysize */
++typedef CK_ULONG CK_RC2_PARAMS;
++
++typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
++
++
++/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
++ * mechanism */
++typedef struct CK_RC2_CBC_PARAMS {
++ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++
++ CK_BYTE iv[8]; /* IV for CBC mode */
++} CK_RC2_CBC_PARAMS;
++
++typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
++
++
++/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC2_MAC_GENERAL mechanism */
++/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC2_MAC_GENERAL_PARAMS {
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC2_MAC_GENERAL_PARAMS;
++
++typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC2_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
++ * CKM_RC5_MAC mechanisms */
++/* CK_RC5_PARAMS is new for v2.0 */
++typedef struct CK_RC5_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++} CK_RC5_PARAMS;
++
++typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
++
++
++/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
++ * mechanism */
++/* CK_RC5_CBC_PARAMS is new for v2.0 */
++typedef struct CK_RC5_CBC_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_BYTE_PTR pIv; /* pointer to IV */
++ CK_ULONG ulIvLen; /* length of IV in bytes */
++} CK_RC5_CBC_PARAMS;
++
++typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
++
++
++/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC5_MAC_GENERAL mechanism */
++/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC5_MAC_GENERAL_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC5_MAC_GENERAL_PARAMS;
++
++typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC5_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
++ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
++ * the MAC */
++/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
++
++typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
++
++/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
++typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[8];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pPassword;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPAndGLen;
++ CK_ULONG ulQLen;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pPrimeP;
++ CK_BYTE_PTR pBaseG;
++ CK_BYTE_PTR pSubprimeQ;
++} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
++
++typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
++ CK_SKIPJACK_PRIVATE_WRAP_PTR;
++
++
++/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_RELAYX mechanism */
++/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_RELAYX_PARAMS {
++ CK_ULONG ulOldWrappedXLen;
++ CK_BYTE_PTR pOldWrappedX;
++ CK_ULONG ulOldPasswordLen;
++ CK_BYTE_PTR pOldPassword;
++ CK_ULONG ulOldPublicDataLen;
++ CK_BYTE_PTR pOldPublicData;
++ CK_ULONG ulOldRandomLen;
++ CK_BYTE_PTR pOldRandomA;
++ CK_ULONG ulNewPasswordLen;
++ CK_BYTE_PTR pNewPassword;
++ CK_ULONG ulNewPublicDataLen;
++ CK_BYTE_PTR pNewPublicData;
++ CK_ULONG ulNewRandomLen;
++ CK_BYTE_PTR pNewRandomA;
++} CK_SKIPJACK_RELAYX_PARAMS;
++
++typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
++ CK_SKIPJACK_RELAYX_PARAMS_PTR;
++
++
++typedef struct CK_PBE_PARAMS {
++ CK_BYTE_PTR pInitVector;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pSalt;
++ CK_ULONG ulSaltLen;
++ CK_ULONG ulIteration;
++} CK_PBE_PARAMS;
++
++typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
++
++
++/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
++ * CKM_KEY_WRAP_SET_OAEP mechanism */
++/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
++typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
++ CK_BYTE bBC; /* block contents byte */
++ CK_BYTE_PTR pX; /* extra data */
++ CK_ULONG ulXLen; /* length of extra data in bytes */
++} CK_KEY_WRAP_SET_OAEP_PARAMS;
++
++typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
++ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_SSL3_RANDOM_DATA;
++
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_VERSION_PTR pVersion;
++} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hClientMacSecret;
++ CK_OBJECT_HANDLE hServerMacSecret;
++ CK_OBJECT_HANDLE hClientKey;
++ CK_OBJECT_HANDLE hServerKey;
++ CK_BYTE_PTR pIVClient;
++ CK_BYTE_PTR pIVServer;
++} CK_SSL3_KEY_MAT_OUT;
++
++typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_PARAMS {
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_BBOOL bIsExport;
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_SSL3_KEY_MAT_PARAMS;
++
++typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
++
++/* CK_TLS_PRF_PARAMS is new for version 2.20 */
++typedef struct CK_TLS_PRF_PARAMS {
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_TLS_PRF_PARAMS;
++
++typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
++
++/* WTLS is new for version 2.20 */
++typedef struct CK_WTLS_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_WTLS_RANDOM_DATA;
++
++typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
++
++typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_BYTE_PTR pVersion;
++} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
++
++typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++typedef struct CK_WTLS_PRF_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_WTLS_PRF_PARAMS;
++
++typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hMacSecret;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pIV;
++} CK_WTLS_KEY_MAT_OUT;
++
++typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_ULONG ulSequenceNumber;
++ CK_BBOOL bIsExport;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_WTLS_KEY_MAT_PARAMS;
++
++typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
++
++/* CMS is new for version 2.20 */
++typedef struct CK_CMS_SIG_PARAMS {
++ CK_OBJECT_HANDLE certificateHandle;
++ CK_MECHANISM_PTR pSigningMechanism;
++ CK_MECHANISM_PTR pDigestMechanism;
++ CK_UTF8CHAR_PTR pContentType;
++ CK_BYTE_PTR pRequestedAttributes;
++ CK_ULONG ulRequestedAttributesLen;
++ CK_BYTE_PTR pRequiredAttributes;
++ CK_ULONG ulRequiredAttributesLen;
++} CK_CMS_SIG_PARAMS;
++
++typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
++
++typedef struct CK_KEY_DERIVATION_STRING_DATA {
++ CK_BYTE_PTR pData;
++ CK_ULONG ulLen;
++} CK_KEY_DERIVATION_STRING_DATA;
++
++typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
++ CK_KEY_DERIVATION_STRING_DATA_PTR;
++
++
++/* The CK_EXTRACT_PARAMS is used for the
++ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
++ * of the base key should be used as the first bit of the
++ * derived key */
++/* CK_EXTRACT_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_EXTRACT_PARAMS;
++
++typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
++
++/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
++ * indicate the Pseudo-Random Function (PRF) used to generate
++ * key bits using PKCS #5 PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
++
++typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
++
++/* The following PRFs are defined in PKCS #5 v2.0. */
++#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
++
++
++/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
++ * source of the salt value when deriving a key using PKCS #5
++ * PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
++
++typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
++
++/* The following salt value sources are defined in PKCS #5 v2.0. */
++#define CKZ_SALT_SPECIFIED 0x00000001
++
++/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
++ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
++ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
++typedef struct CK_PKCS5_PBKD2_PARAMS {
++ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ CK_VOID_PTR pSaltSourceData;
++ CK_ULONG ulSaltSourceDataLen;
++ CK_ULONG iterations;
++ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ CK_VOID_PTR pPrfData;
++ CK_ULONG ulPrfDataLen;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG_PTR ulPasswordLen;
++} CK_PKCS5_PBKD2_PARAMS;
++
++typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
++
++/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */
++
++typedef CK_ULONG CK_OTP_PARAM_TYPE;
++typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */
++
++typedef struct CK_OTP_PARAM {
++ CK_OTP_PARAM_TYPE type;
++ CK_VOID_PTR pValue;
++ CK_ULONG ulValueLen;
++} CK_OTP_PARAM;
++
++typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
++
++typedef struct CK_OTP_PARAMS {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_PARAMS;
++
++typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
++
++typedef struct CK_OTP_SIGNATURE_INFO {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_SIGNATURE_INFO;
++
++typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CK_OTP_VALUE 0
++#define CK_OTP_PIN 1
++#define CK_OTP_CHALLENGE 2
++#define CK_OTP_TIME 3
++#define CK_OTP_COUNTER 4
++#define CK_OTP_FLAGS 5
++#define CK_OTP_OUTPUT_LENGTH 6
++#define CK_OTP_OUTPUT_FORMAT 7
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CKF_NEXT_OTP 0x00000001
++#define CKF_EXCLUDE_TIME 0x00000002
++#define CKF_EXCLUDE_COUNTER 0x00000004
++#define CKF_EXCLUDE_CHALLENGE 0x00000008
++#define CKF_EXCLUDE_PIN 0x00000010
++#define CKF_USER_FRIENDLY_OTP 0x00000020
++
++/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */
++typedef struct CK_KIP_PARAMS {
++ CK_MECHANISM_PTR pMechanism;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++} CK_KIP_PARAMS;
++
++typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
++
++/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_AES_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_AES_CTR_PARAMS;
++
++typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_CAMELLIA_CTR_PARAMS;
++
++typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++#endif
+Index: openssl/util/libeay.num
+diff -u openssl/util/libeay.num:1.8.2.1.6.1.4.1.4.1.2.1 openssl/util/libeay.num:1.9.2.4
+--- openssl/util/libeay.num:1.8.2.1.6.1.4.1.4.1.2.1 Wed Dec 23 17:27:04 2015
++++ openssl/util/libeay.num Wed Dec 23 17:45:51 2015
+@@ -4198,3 +4198,5 @@
+ OPENSSL_strncasecmp 4566 EXIST::FUNCTION:
+ OPENSSL_gmtime 4567 EXIST::FUNCTION:
+ OPENSSL_gmtime_adj 4568 EXIST::FUNCTION:
++ENGINE_load_pk11ca 4569 EXIST::FUNCTION:HW_PKCS11CA,ENGINE
++ENGINE_load_pk11so 4569 EXIST::FUNCTION:HW_PKCS11SO,ENGINE
+Index: openssl/util/mk1mf.pl
+diff -u openssl/util/mk1mf.pl:1.9.2.1.14.1 openssl/util/mk1mf.pl:1.9.4.1
+--- openssl/util/mk1mf.pl:1.9.2.1.14.1 Wed Mar 4 14:03:25 2015
++++ openssl/util/mk1mf.pl Wed Mar 4 14:04:40 2015
+@@ -109,6 +109,8 @@
+ no-ecdh - No ECDH
+ no-engine - No engine
+ no-hw - No hw
++ no-hw-pkcs11ca - No hw PKCS#11 CA flavor
++ no-hw-pkcs11so - No hw PKCS#11 SO flavor
+ nasm - Use NASM for x86 asm
+ nw-nasm - Use NASM x86 asm for NetWare
+ nw-mwasm - Use Metrowerks x86 asm for NetWare
+@@ -270,6 +272,8 @@
+ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost;
+ $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine;
+ $cflags.=" -DOPENSSL_NO_HW" if $no_hw;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so;
+ $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake;
+ $cflags.= " -DZLIB" if $zlib_opt;
+ $cflags.= " -DZLIB_SHARED" if $zlib_opt == 2;
+@@ -335,6 +339,9 @@
+ $dir=$val;
+ }
+
++ if ($key eq "PK11_LIB_LOCATION")
++ { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";}
++
+ if ($key eq "KRB5_INCLUDES")
+ { $cflags .= " $val";}
+
+@@ -1061,6 +1068,8 @@
+ "no-gost" => \$no_gost,
+ "no-engine" => \$no_engine,
+ "no-hw" => \$no_hw,
++ "no-hw-pkcs11ca" => \$no_hw_pkcs11ca,
++ "no-hw-pkcs11so" => \$no_hw_pkcs11so,
+ "just-ssl" =>
+ [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast,
+ \$no_md2, \$no_sha, \$no_mdc2, \$no_dsa, \$no_dh,
+Index: openssl/util/mkdef.pl
+diff -u openssl/util/mkdef.pl:1.7.2.1 openssl/util/mkdef.pl:1.8
+--- openssl/util/mkdef.pl:1.7.2.1 Sun Jan 15 16:09:52 2012
++++ openssl/util/mkdef.pl Sun Jan 15 16:30:10 2012
+@@ -94,7 +94,7 @@
+ # External "algorithms"
+ "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM",
+ # Engines
+- "STATIC_ENGINE", "ENGINE", "HW", "GMP",
++ "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO",
+ # RFC3779
+ "RFC3779",
+ # TLS
+@@ -125,6 +125,7 @@
+ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
+ my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
+ my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw;
++my $no_pkcs11ca; my $no_pkcs11so;
+ my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
+ my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
+ my $no_jpake; my $no_ssl2;
+@@ -218,6 +219,8 @@
+ elsif (/^no-ssl2$/) { $no_ssl2=1; }
+ elsif (/^no-capieng$/) { $no_capieng=1; }
+ elsif (/^no-jpake$/) { $no_jpake=1; }
++ elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; }
++ elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; }
+ }
+
+
+@@ -1165,6 +1168,8 @@
+ if ($keyword eq "KRB5" && $no_krb5) { return 0; }
+ if ($keyword eq "ENGINE" && $no_engine) { return 0; }
+ if ($keyword eq "HW" && $no_hw) { return 0; }
++ if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; }
++ if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; }
+ if ($keyword eq "FP_API" && $no_fp_api) { return 0; }
+ if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; }
+ if ($keyword eq "GMP" && $no_gmp) { return 0; }
+Index: openssl/util/pl/VC-32.pl
+diff -u openssl/util/pl/VC-32.pl:1.7.2.1.16.1 openssl/util/pl/VC-32.pl:1.7.4.1
+--- openssl/util/pl/VC-32.pl:1.7.2.1.16.1 Wed Dec 23 17:27:05 2015
++++ openssl/util/pl/VC-32.pl Wed Dec 23 17:45:51 2015
+@@ -36,7 +36,7 @@
+ my $f = $shlib?' /MD':' /MT';
+ $lib_cflag='/Zl' if (!$shlib); # remove /DEFAULTLIBs from static lib
+ $opt_cflags=$f.' /Ox';
+- $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG';
++ $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG';
+ $lflags="/nologo /subsystem:console /opt:ref";
+
+ *::perlasm_compile_target = sub {
diff --git a/bin/pkcs11/openssl-1.0.1t-patch b/bin/pkcs11/openssl-1.0.1t-patch
new file mode 100644
index 0000000..dfc2628
--- /dev/null
+++ b/bin/pkcs11/openssl-1.0.1t-patch
@@ -0,0 +1,15791 @@
+Index: openssl/Configure
+diff -u openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.4.1.2.1 openssl/Configure:1.19
+--- openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.4.1.2.1 Mon Jun 13 15:10:46 2016
++++ openssl/Configure Mon Jun 13 15:20:23 2016
+@@ -10,7 +10,7 @@
+
+ # see INSTALL for instructions.
+
+-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
++my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+
+ # Options:
+ #
+@@ -23,6 +23,12 @@
+ # default). This needn't be set in advance, you can
+ # just as well use "make INSTALL_PREFIX=/whatever install".
+ #
++# --pk11-libname PKCS#11 library name.
++# (No default)
++#
++# --pk11-flavor either crypto-accelerator or sign-only
++# (No default)
++#
+ # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected
+ # to live in the subdirectory lib/ and the header files in
+ # include/. A value is required.
+@@ -355,24 +361,23 @@
+ ####
+ # *-generic* is endian-neutral target, but ./config is free to
+ # throw in -D[BL]_ENDIAN, whichever appropriate...
+-"linux-generic32","gcc:-O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ppc", "gcc:-DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc32_asm}:linux32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-generic32","gcc:-DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-ppc", "gcc:-DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc32_asm}:linux32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ # It's believed that majority of ARM toolchains predefine appropriate -march.
+ # If you compiler does not, do complement config command line with one!
+-"linux-armv4", "gcc:-O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-armv4", "gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ #### IA-32 targets...
+-"linux-ia32-icc", "icc:-DL_ENDIAN -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-elf", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-aout", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out",
++"linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out",
+ ####
+-"linux-generic64","gcc:-O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ppc64", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-ia64", "gcc:-DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ia64-ecc","ecc:-DL_ENDIAN -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ia64-icc","icc:-DL_ENDIAN -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-x86_64", "gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-x86_64-clang","clang: -m64 -DL_ENDIAN -O3 -Wall -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux64-s390x", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-ppc64", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux64-s390x", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ #### So called "highgprs" target for z/Architecture CPUs
+ # "Highgprs" is kernel feature first implemented in Linux 2.6.32, see
+ # /proc/cpuinfo. The idea is to preserve most significant bits of
+@@ -668,6 +673,10 @@
+ my $idx_arflags = $idx++;
+ my $idx_multilib = $idx++;
+
++# PKCS#11 engine patch
++my $pk11_libname="";
++my $pk11_flavor="";
++
+ my $prefix="";
+ my $libdir="";
+ my $openssldir="";
+@@ -895,6 +904,14 @@
+ $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
+ $flags.=$_." ";
+ }
++ elsif (/^--pk11-libname=(.*)$/)
++ {
++ $pk11_libname=$1;
++ }
++ elsif (/^--pk11-flavor=(.*)$/)
++ {
++ $pk11_flavor=$1;
++ }
+ elsif (/^--prefix=(.*)$/)
+ {
+ $prefix=$1;
+@@ -1062,6 +1079,22 @@
+ exit 0;
+ }
+
++if (! $pk11_libname)
++ {
++ print STDERR "You must set --pk11-libname for PKCS#11 library.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
++if (! $pk11_flavor
++ || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only"))
++ {
++ print STDERR "You must set --pk11-flavor.\n";
++ print STDERR "Choices are crypto-accelerator and sign-only.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
+ if ($target =~ m/^CygWin32(-.*)$/) {
+ $target = "Cygwin".$1;
+ }
+@@ -1139,6 +1172,25 @@
+ $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO";
+ }
+
++if ($pk11_flavor eq "crypto-accelerator")
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $options .= " no-hw-pkcs11so";
++ print " no-hw-pkcs11so [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11SO\n";
++ }
++else
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $options .= " no-hw-pkcs11ca";
++ print " no-hw-pkcs11ca [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11CA\n";
++}
++
+ my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds;
+
+ $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target =~ /^mingw/);
+@@ -1228,6 +1280,8 @@
+ if ($flags ne "") { $cflags="$flags$cflags"; }
+ else { $no_user_cflags=1; }
+
++$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags";
++
+ # Kerberos settings. The flavor must be provided from outside, either through
+ # the script "config" or manually.
+ if (!$no_krb5)
+@@ -1626,6 +1680,7 @@
+ s/^VERSION=.*/VERSION=$version/;
+ s/^MAJOR=.*/MAJOR=$major/;
+ s/^MINOR=.*/MINOR=$minor/;
++ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/;
+ s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/;
+ s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/;
+ s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/;
+Index: openssl/Makefile.org
+diff -u openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.10.1.2.1 openssl/Makefile.org:1.12
+--- openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.10.1.2.1 Mon Jun 13 15:10:47 2016
++++ openssl/Makefile.org Mon Jun 13 15:20:23 2016
+@@ -26,6 +26,9 @@
+ INSTALL_PREFIX=
+ INSTALLTOP=/usr/local/ssl
+
++# You must set this through --pk11-libname configure option.
++PK11_LIB_LOCATION=
++
+ # Do not edit this manually. Use Configure --openssldir=DIR do change this!
+ OPENSSLDIR=/usr/local/ssl
+
+Index: openssl/README.pkcs11
+diff -u /dev/null openssl/README.pkcs11:1.8
+--- /dev/null Mon Jun 13 15:26:28 2016
++++ openssl/README.pkcs11 Fri Oct 4 14:16:43 2013
+@@ -0,0 +1,266 @@
++ISC modified
++============
++
++The previous key naming scheme was kept for backward compatibility.
++
++The PKCS#11 engine exists in two flavors, crypto-accelerator and
++sign-only. The first one is from the Solaris patch and uses the
++PKCS#11 device for all crypto operations it supports. The second
++is a stripped down version which provides only the useful
++function (i.e., signature with a RSA private key in the device
++protected key store and key loading).
++
++As a hint PKCS#11 boards should use the crypto-accelerator flavor,
++external PKCS#11 devices the sign-only. SCA 6000 is an example
++of the first, AEP Keyper of the second.
++
++Note it is mandatory to set a pk11-flavor (and only one) in
++config/Configure.
++
++It is highly recommended to compile in (vs. as a DSO) the engine.
++The way to configure this is system dependent, on Unixes it is no-shared
++(and is in general the default), on WIN32 it is enable-static-engine
++(and still enable to build the OpenSSL libraries as DLLs).
++
++PKCS#11 engine support for OpenSSL 0.9.8l
++=========================================
++
++[Nov 19, 2009]
++
++Contents:
++
++Overview
++Revisions of the patch for 0.9.8 branch
++FAQs
++Feedback
++
++Overview
++========
++
++This patch containing code available in OpenSolaris adds support for PKCS#11
++engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against
++OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system
++must provide PKCS#11 backend otherwise the patch is useless. You provide the
++PKCS#11 library name during the build configuration phase, see below.
++
++Patch can be applied like this:
++
++ # NOTE: use gtar if on Solaris
++ tar xfzv openssl-0.9.8l.tar.gz
++ # now download the patch to the current directory
++ # ...
++ cd openssl-0.9.8l
++ # NOTE: must use gpatch if on Solaris (is part of the system)
++ patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19
++
++It is designed to support pure acceleration for RSA, DSA, DH and all the
++symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share
++except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA.
++
++According to the PKCS#11 providers installed on your machine, it can support
++following mechanisms:
++
++ RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4,
++ AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB,
++ AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224,
++ SHA256, SHA384, SHA512
++
++Note that for AES counter mode the application must provide their own EVP
++functions since OpenSSL doesn't support counter mode through EVP yet. You may
++see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an
++example of code that uses the PKCS#11 engine and deals with the fork-safety
++problem (see engine.c and packet.c files if interested).
++
++You must provide the location of PKCS#11 library in your system to the
++configure script. You will be instructed to do that when you try to run the
++config script:
++
++ $ ./config
++ Operating system: i86pc-whatever-solaris2
++ Configuring for solaris-x86-cc
++ You must set --pk11-libname for PKCS#11 library.
++ See README.pkcs11 for more information.
++
++Taking openCryptoki project on Linux AMD64 box as an example, you would run
++configure script like this:
++
++ ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so
++
++To check whether newly built openssl really supports PKCS#11 it's enough to run
++"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the
++output. If you see no PKCS#11 engine support check that the built openssl binary
++and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits.
++
++The patch, during various phases of development, was tested on Solaris against
++PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and
++OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project
++(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more
++information). Some Linux distributions even ship those libraries with the
++system. The patch should work on any system that is supported by OpenSSL itself
++and has functional PKCS#11 library.
++
++The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are
++copyrighted by RSA Security Inc., see pkcs11.h for more information.
++
++Other added/modified code in this patch is copyrighted by Sun Microsystems,
++Inc. and is released under the OpenSSL license (see LICENSE file for more
++information).
++
++Revisions of the patch for 0.9.8 branch
++=======================================
++
++2009-11-19
++- adjusted for OpenSSL version 0.9.8l
++
++- bugs and RFEs:
++
++ 6479874 OpenSSL should support RSA key by reference/hardware keystores
++ 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split
++ 6732677 make check to trigger Solaris specific code automatic in the
++ PKCS#11 engine
++
++2009-03-11
++- adjusted for OpenSSL version 0.9.8j
++
++- README.pkcs11 moved out of the patch, and is shipped together with it in a
++ tarball instead so that it can be read before the patch is applied.
++
++- fixed bugs:
++
++ 6804216 pkcs#11 engine should support a key length range for RC4
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-12-02
++- fixed bugs and RFEs (most of the work done by Vladimir Kotal)
++
++ 6723504 more granular locking in PKCS#11 engine
++ 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true
++ 6710420 PKCS#11 engine source should be lint clean
++ 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take
++ it seriously
++ 6746712 PKCS#11 engine source code should be cstyle clean
++ 6731380 return codes of several functions are not checked in the PKCS#11
++ engine code
++ 6746735 PKCS#11 engine should use extended FILE space API
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-08-01
++- fixed bug
++
++ 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers
++ and digests
++
++- Solaris specific code for slot selection made automatic
++
++2008-07-29
++- update the patch to OpenSSL 0.9.8h version
++- pkcs11t.h updated to the latest version:
++
++ 6545665 make CKM_AES_CTR available to non-kernel users
++
++- fixed bugs in the engine code:
++
++ 6602801 PK11_SESSION cache has to employ reference counting scheme for
++ asymmetric key operations
++ 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called
++ atomically
++ 6607307 pkcs#11 engine can't read RSA private keys
++ 6652362 pk11_RSA_finish() is cutting corners
++ 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in
++ suboptimal way
++ 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more
++ resilient to destroy failures
++ 6667273 OpenSSL engine should not use free() but OPENSSL_free()
++ 6670363 PKCS#11 engine fails to reuse existing symmetric keys
++ 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine
++ 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size
++ of big numbers leading to failures
++ 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of
++ -1
++ 6706622 pk11_load_{pub,priv}key create corrupted RSA key references
++ 6707129 return values from BN_new() in pk11_DH_generate_key() are not
++ checked
++ 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to
++ structure reuse
++ 6707782 OpenSSL PKCS#11 engine pretends to be aware of
++ OPENSSL_NO_{RSA,DSA,DH}
++ defines but fails miserably
++ 6709966 make check_new_*() to return values to indicate cache hit/miss
++ 6705200 pk11_dh struct initialization in PKCS#11 engine is missing
++ generate_params parameter
++ 6709513 PKCS#11 engine sets IV length even for ECB modes
++ 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the
++ PKCS#11 engine
++ 6728871 PKCS#11 engine must reset global_session in pk11_finish()
++
++- new features and enhancements:
++
++ 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512
++ 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes
++ 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric
++ ciphers and digests
++
++2007-10-15
++- update for 0.9.8f version
++- update for "6607670 teach pkcs#11 engine how to use keys be reference"
++
++2007-10-02
++- draft for "6607670 teach pkcs#11 engine how to use keys be reference"
++- draft for "6607307 pkcs#11 engine can't read RSA private keys"
++
++2007-09-26
++- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes
++ significant performance drop
++- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine
++
++2007-05-25
++- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers
++
++2007-05-19
++- initial patch for 0.9.8e using latest OpenSolaris code
++
++FAQs
++====
++
++(1) my build failed on Linux distro with this error:
++
++../libcrypto.a(hw_pk11.o): In function `pk11_library_init':
++hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork'
++
++Answer:
++
++ - don't use "no-threads" when configuring
++ - if you didn't then OpenSSL failed to create a threaded library by
++ default. You may manually edit Configure and try again. Look for the
++ architecture that Configure printed, for example:
++
++Configured for linux-elf.
++
++ - then edit Configure, find string "linux-elf" (inluding the quotes),
++ and add flags to support threads to the 4th column of the 2nd string.
++ If you build with GCC then adding "-pthread" should be enough. With
++ "linux-elf" as an example, you would add " -pthread" right after
++ "-D_REENTRANT", like this:
++
++....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:.....
++
++(2) I'm using MinGW/MSYS environment and get undeclared reference error for
++pthread_atfork() function when trying to build OpenSSL with the patch.
++
++Answer:
++
++ Sorry, pthread_atfork() is not implemented in the current pthread-win32
++ (as of Nov 2009). You can not use the patch there.
++
++
++Feedback
++========
++
++Please send feedback to security-discuss@opensolaris.org. The patch was
++created by Jan.Pechanec@Sun.COM from code available in OpenSolaris.
++
++Latest version should be always available on http://blogs.sun.com/janp.
++
+Index: openssl/crypto/opensslconf.h
+diff -u openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.6.1.2.1 openssl/crypto/opensslconf.h:1.10
+--- openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.6.1.2.1 Mon Jun 13 15:10:49 2016
++++ openssl/crypto/opensslconf.h Mon Jun 13 15:20:26 2016
+@@ -47,6 +47,9 @@
+
+ #endif /* OPENSSL_DOING_MAKEDEPEND */
+
++#ifndef OPENSSL_THREADS
++# define OPENSSL_THREADS
++#endif
+ #ifndef OPENSSL_NO_DYNAMIC_ENGINE
+ # define OPENSSL_NO_DYNAMIC_ENGINE
+ #endif
+@@ -94,6 +97,8 @@
+ # endif
+ #endif
+
++#define OPENSSL_CPUID_OBJ
++
+ /* crypto/opensslconf.h.in */
+
+ /* Generate 80386 code? */
+@@ -140,7 +145,7 @@
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+-#undef RC4_CHUNK
++#define RC4_CHUNK unsigned long
+ #endif
+ #endif
+
+@@ -148,7 +153,7 @@
+ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+ #ifndef DES_LONG
+-#define DES_LONG unsigned long
++#define DES_LONG unsigned int
+ #endif
+ #endif
+
+@@ -159,9 +164,9 @@
+ /* Should we define BN_DIV2W here? */
+
+ /* Only one for the following should be defined */
+-#undef SIXTY_FOUR_BIT_LONG
++#define SIXTY_FOUR_BIT_LONG
+ #undef SIXTY_FOUR_BIT
+-#define THIRTY_TWO_BIT
++#undef THIRTY_TWO_BIT
+ #endif
+
+ #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+@@ -173,7 +178,7 @@
+
+ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+ #define CONFIG_HEADER_BF_LOCL_H
+-#undef BF_PTR
++#define BF_PTR2
+ #endif /* HEADER_BF_LOCL_H */
+
+ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+@@ -203,7 +208,7 @@
+ /* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+ #ifndef DES_UNROLL
+-#undef DES_UNROLL
++#define DES_UNROLL
+ #endif
+
+ /* These default values were supplied by
+Index: openssl/crypto/engine/Makefile
+diff -u openssl/crypto/engine/Makefile:1.8.2.1.4.1.16.1 openssl/crypto/engine/Makefile:1.10
+--- openssl/crypto/engine/Makefile:1.8.2.1.4.1.16.1 Wed Dec 23 18:09:29 2015
++++ openssl/crypto/engine/Makefile Wed Dec 23 18:27:10 2015
+@@ -22,13 +22,15 @@
+ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \
+ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \
+ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \
+- eng_rsax.c eng_rdrand.c
++ eng_rsax.c eng_rdrand.c \
++ hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c
+ LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
+ eng_table.o eng_pkey.o eng_fat.o eng_all.o \
+ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \
+ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \
+ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \
+- eng_rsax.o eng_rdrand.o
++ eng_rsax.o eng_rdrand.o \
++ hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o
+
+ SRC= $(LIBSRC)
+
+@@ -296,6 +298,83 @@
+ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+ eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+ eng_table.o: eng_table.c
++hw_pk11.o: ../../e_os.h ../../include/openssl/aes.h
++hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
++hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h
++hw_pk11.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h
++hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
++hw_pk11.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
++hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/err.h
++hw_pk11.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
++hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/obj_mac.h
++hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
++hw_pk11.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
++hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
++hw_pk11.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
++hw_pk11.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
++hw_pk11.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
++hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
++hw_pk11.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h hw_pk11.c
++hw_pk11.o: hw_pk11_err.c hw_pk11_err.h hw_pk11ca.h pkcs11.h pkcs11f.h pkcs11t.h
++hw_pk11_pub.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
++hw_pk11_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
++hw_pk11_pub.o: ../../include/openssl/objects.h
++hw_pk11_pub.o: ../../include/openssl/opensslconf.h
++hw_pk11_pub.o: ../../include/openssl/opensslv.h
++hw_pk11_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
++hw_pk11_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
++hw_pk11_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
++hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
++hw_pk11_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
++hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
++hw_pk11_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11_pub.c hw_pk11ca.h
++hw_pk11_pub.o: pkcs11.h pkcs11f.h pkcs11t.h
++hw_pk11so.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11so.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11so.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11so.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11so.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11so.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11so.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/md5.h
++hw_pk11so.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
++hw_pk11so.o: ../../include/openssl/opensslconf.h
++hw_pk11so.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
++hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
++hw_pk11so.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
++hw_pk11so.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
++hw_pk11so.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
++hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
++hw_pk11so.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h
++hw_pk11so.o: hw_pk11_err.c hw_pk11_err.h hw_pk11so.c hw_pk11so.h pkcs11.h
++hw_pk11so.o: pkcs11f.h pkcs11t.h
++hw_pk11so_pub.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11so_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11so_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11so_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11so_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11so_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11so_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
++hw_pk11so_pub.o: ../../include/openssl/objects.h
++hw_pk11so_pub.o: ../../include/openssl/opensslconf.h
++hw_pk11so_pub.o: ../../include/openssl/opensslv.h
++hw_pk11so_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
++hw_pk11so_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
++hw_pk11so_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
++hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
++hw_pk11so_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
++hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
++hw_pk11so_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11so.h
++hw_pk11so_pub.o: hw_pk11so_pub.c pkcs11.h pkcs11f.h pkcs11t.h
+ tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h
+ tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+ tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+Index: openssl/crypto/engine/cryptoki.h
+diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4
+--- /dev/null Mon Jun 13 15:26:29 2016
++++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008
+@@ -0,0 +1,103 @@
++/*
++ * CDDL HEADER START
++ *
++ * The contents of this file are subject to the terms of the
++ * Common Development and Distribution License, Version 1.0 only
++ * (the "License"). You may not use this file except in compliance
++ * with the License.
++ *
++ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
++ * or http://www.opensolaris.org/os/licensing.
++ * See the License for the specific language governing permissions
++ * and limitations under the License.
++ *
++ * When distributing Covered Code, include this CDDL HEADER in each
++ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
++ * If applicable, add the following below this CDDL HEADER, with the
++ * fields enclosed by brackets "[]" replaced with your own identifying
++ * information: Portions Copyright [yyyy] [name of copyright owner]
++ *
++ * CDDL HEADER END
++ */
++/*
++ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _CRYPTOKI_H
++#define _CRYPTOKI_H
++
++/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef CK_PTR
++#define CK_PTR *
++#endif
++
++#ifndef CK_DEFINE_FUNCTION
++#define CK_DEFINE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION
++#define CK_DECLARE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION_POINTER
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
++#endif
++
++#ifndef CK_CALLBACK_FUNCTION
++#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
++#endif
++
++#ifndef NULL_PTR
++#include <unistd.h> /* For NULL */
++#define NULL_PTR NULL
++#endif
++
++/*
++ * pkcs11t.h defines TRUE and FALSE in a way that upsets lint
++ */
++#ifndef CK_DISABLE_TRUE_FALSE
++#define CK_DISABLE_TRUE_FALSE
++#ifndef TRUE
++#define TRUE 1
++#endif /* TRUE */
++#ifndef FALSE
++#define FALSE 0
++#endif /* FALSE */
++#endif /* CK_DISABLE_TRUE_FALSE */
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++#include "pkcs11.h"
++
++/* Solaris specific functions */
++
++#include <stdlib.h>
++
++/*
++ * SUNW_C_GetMechSession will initialize the framework and do all
++ * the necessary PKCS#11 calls to create a session capable of
++ * providing operations on the requested mechanism
++ */
++CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech,
++ CK_SESSION_HANDLE_PTR hSession);
++
++/*
++ * SUNW_C_KeyToObject will create a secret key object for the given
++ * mechanism from the rawkey data.
++ */
++CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len,
++ CK_OBJECT_HANDLE_PTR obj);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _CRYPTOKI_H */
+Index: openssl/crypto/engine/eng_all.c
+diff -u openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.16.1.2.1 openssl/crypto/engine/eng_all.c:1.8
+--- openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.16.1.2.1 Mon Jun 13 15:10:52 2016
++++ openssl/crypto/engine/eng_all.c Mon Jun 13 15:20:31 2016
+@@ -122,6 +122,14 @@
+ # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
+ ENGINE_load_capi();
+ # endif
++# ifndef OPENSSL_NO_HW_PKCS11
++# ifndef OPENSSL_NO_HW_PKCS11CA
++ ENGINE_load_pk11ca();
++# endif
++# ifndef OPENSSL_NO_HW_PKCS11SO
++ ENGINE_load_pk11so();
++# endif
++# endif
+ #endif
+ ENGINE_register_all_complete();
+ }
+Index: openssl/crypto/engine/engine.h
+diff -u openssl/crypto/engine/engine.h:1.5.2.1.4.1.16.1 openssl/crypto/engine/engine.h:1.7
+--- openssl/crypto/engine/engine.h:1.5.2.1.4.1.16.1 Wed Dec 23 18:09:30 2015
++++ openssl/crypto/engine/engine.h Wed Dec 23 18:27:11 2015
+@@ -416,6 +416,12 @@
+ void ENGINE_load_rsax(void);
+ void ENGINE_load_rdrand(void);
+ void ENGINE_load_builtin_engines(void);
++# ifndef OPENSSL_NO_HW_PKCS11CA
++void ENGINE_load_pk11ca(void);
++# endif
++# ifndef OPENSSL_NO_HW_PKCS11SO
++void ENGINE_load_pk11so(void);
++# endif
+
+ /*
+ * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+Index: openssl/crypto/engine/hw_pk11.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.33
+--- /dev/null Mon Jun 13 15:26:29 2016
++++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:07:41 2013
+@@ -0,0 +1,4010 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++#include <openssl/aes.h>
++#include <openssl/des.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/* #undef DEBUG_SLOT_SELECTION */
++/*
++ * Solaris specific code. See comment at check_hw_mechanisms() for more
++ * information.
++ */
++#if defined(__SVR4) && defined(__sun)
++#undef SOLARIS_HW_SLOT_SELECTION
++#endif
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.c"
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel
++ * library. See comment at check_hw_mechanisms() for more information.
++ */
++static int *hw_cnids;
++static int *hw_dnids;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++#ifndef OPENSSL_NO_RSA
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DSA
++int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DH
++int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock);
++#endif
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++/* Symmetric cipher and digest support functions */
++static int cipher_nid_to_pk11(int nid);
++static int pk11_usable_ciphers(const int **nids);
++static int pk11_usable_digests(const int **nids);
++static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc);
++static int pk11_cipher_final(PK11_SESSION *sp);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl);
++#else
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl);
++#endif
++static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx);
++static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid);
++static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid);
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp);
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len);
++static int md_nid_to_pk11(int nid);
++static int pk11_digest_init(EVP_MD_CTX *ctx);
++static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data,
++ size_t count);
++static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md);
++static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
++static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
++
++static int pk11_choose_slots(int *any_slot_found);
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher,
++ int *local_cipher_nids);
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest,
++ int *local_digest_nids);
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids,
++ int id);
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++static int check_hw_mechanisms(void);
++static int nid_in_table(int nid, int *nid_table);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* Index for the supported ciphers */
++enum pk11_cipher_id {
++ PK11_DES_CBC,
++ PK11_DES3_CBC,
++ PK11_DES_ECB,
++ PK11_DES3_ECB,
++ PK11_RC4,
++ PK11_AES_128_CBC,
++ PK11_AES_192_CBC,
++ PK11_AES_256_CBC,
++ PK11_AES_128_ECB,
++ PK11_AES_192_ECB,
++ PK11_AES_256_ECB,
++ PK11_AES_128_CTR,
++ PK11_AES_192_CTR,
++ PK11_AES_256_CTR,
++ PK11_BLOWFISH_CBC,
++ PK11_CIPHER_MAX
++};
++
++/* Index for the supported digests */
++enum pk11_digest_id {
++ PK11_MD5,
++ PK11_SHA1,
++ PK11_SHA224,
++ PK11_SHA256,
++ PK11_SHA384,
++ PK11_SHA512,
++ PK11_DIGEST_MAX
++};
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static int cipher_nids[PK11_CIPHER_MAX];
++static int digest_nids[PK11_DIGEST_MAX];
++static int cipher_count = 0;
++static int digest_count = 0;
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_recover = CK_FALSE;
++static CK_BBOOL pk11_have_dsa = CK_FALSE;
++static CK_BBOOL pk11_have_dh = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++typedef struct PK11_CIPHER_st
++ {
++ enum pk11_cipher_id id;
++ int nid;
++ int iv_len;
++ int min_key_len;
++ int max_key_len;
++ CK_KEY_TYPE key_type;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_CIPHER;
++
++static PK11_CIPHER ciphers[] =
++ {
++ { PK11_DES_CBC, NID_des_cbc, 8, 8, 8,
++ CKK_DES, CKM_DES_CBC, },
++ { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24,
++ CKK_DES3, CKM_DES3_CBC, },
++ { PK11_DES_ECB, NID_des_ecb, 0, 8, 8,
++ CKK_DES, CKM_DES_ECB, },
++ { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24,
++ CKK_DES3, CKM_DES3_ECB, },
++ { PK11_RC4, NID_rc4, 0, 16, 256,
++ CKK_RC4, CKM_RC4, },
++ { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_128_CTR, NID_aes_128_ctr, 16, 16, 16,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_192_CTR, NID_aes_192_ctr, 16, 24, 24,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_256_CTR, NID_aes_256_ctr, 16, 32, 32,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16,
++ CKK_BLOWFISH, CKM_BLOWFISH_CBC, },
++ };
++
++typedef struct PK11_DIGEST_st
++ {
++ enum pk11_digest_id id;
++ int nid;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_DIGEST;
++
++static PK11_DIGEST digests[] =
++ {
++ {PK11_MD5, NID_md5, CKM_MD5, },
++ {PK11_SHA1, NID_sha1, CKM_SHA_1, },
++ {PK11_SHA224, NID_sha224, CKM_SHA224, },
++ {PK11_SHA256, NID_sha256, CKM_SHA256, },
++ {PK11_SHA384, NID_sha384, CKM_SHA384, },
++ {PK11_SHA512, NID_sha512, CKM_SHA512, },
++ {0, NID_undef, 0xFFFF, },
++ };
++
++/*
++ * Structure to be used for the cipher_data/md_data in
++ * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11
++ * session in multiple cipher_update calls
++ */
++typedef struct PK11_CIPHER_STATE_st
++ {
++ PK11_SESSION *sp;
++ } PK11_CIPHER_STATE;
++
++
++/*
++ * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets
++ * called when libcrypto requests a cipher NID.
++ *
++ * Note how the PK11_CIPHER_STATE is used here.
++ */
++
++/* DES CBC EVP */
++static const EVP_CIPHER pk11_des_cbc =
++ {
++ NID_des_cbc,
++ 8, 8, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/* 3DES CBC EVP */
++static const EVP_CIPHER pk11_3des_cbc =
++ {
++ NID_des_ede3_cbc,
++ 8, 24, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and
++ * get_asn1_parameters fields are set to NULL.
++ */
++static const EVP_CIPHER pk11_des_ecb =
++ {
++ NID_des_ecb,
++ 8, 8, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_3des_ecb =
++ {
++ NID_des_ede3_ecb,
++ 8, 24, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++
++static const EVP_CIPHER pk11_aes_128_cbc =
++ {
++ NID_aes_128_cbc,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_cbc =
++ {
++ NID_aes_192_cbc,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_cbc =
++ {
++ NID_aes_256_cbc,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use IV so that's why set_asn1_parameters and
++ * get_asn1_parameters are set to NULL.
++ */
++static const EVP_CIPHER pk11_aes_128_ecb =
++ {
++ NID_aes_128_ecb,
++ 16, 16, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_ecb =
++ {
++ NID_aes_192_ecb,
++ 16, 24, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_ecb =
++ {
++ NID_aes_256_ecb,
++ 16, 32, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_128_ctr =
++ {
++ NID_aes_128_ctr,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_ctr =
++ {
++ NID_aes_192_ctr,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_ctr =
++ {
++ NID_aes_256_ctr,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_bf_cbc =
++ {
++ NID_bf_cbc,
++ 8, 16, 8,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_rc4 =
++ {
++ NID_rc4,
++ 1, 16, 0,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_MD pk11_md5 =
++ {
++ NID_md5,
++ NID_md5WithRSAEncryption,
++ MD5_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ MD5_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha1 =
++ {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha224 =
++ {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-224 uses the same cblock size as SHA-256 */
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha256 =
++ {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha384 =
++ {
++ NID_sha384,
++ NID_sha384WithRSAEncryption,
++ SHA384_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-384 uses the same cblock size as SHA-512 */
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha512 =
++ {
++ NID_sha512,
++ NID_sha512WithRSAEncryption,
++ SHA512_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11SO
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name =
++ "PKCS #11 engine support (crypto accelerator)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++#ifndef OPENSSL_NO_RSA
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DSA], &attr);
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DH] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DH], &attr);
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++#ifndef OPENSSL_NO_RSA
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (find_lock[OP_DSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DSA]);
++ OPENSSL_free(find_lock[OP_DSA]);
++ find_lock[OP_DSA] = NULL;
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (find_lock[OP_DH] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DH]);
++ OPENSSL_free(find_lock[OP_DH]);
++ find_lock[OP_DH] = NULL;
++ }
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++#ifndef OPENSSL_NO_RSA
++ const RSA_METHOD *rsa = NULL;
++ RSA_METHOD *pk11_rsa = PK11_RSA();
++#endif /* OPENSSL_NO_RSA */
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name) ||
++ !ENGINE_set_ciphers(e, pk11_engine_ciphers) ||
++ !ENGINE_set_digests(e, pk11_engine_digests))
++ return (0);
++#ifndef OPENSSL_NO_RSA
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (pk11_have_dsa == CK_TRUE)
++ {
++ if (!ENGINE_set_DSA(e, PK11_DSA()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (pk11_have_dh == CK_TRUE)
++ {
++ if (!ENGINE_set_DH(e, PK11_DH()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DH\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DH */
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++/*
++ * Apache calls OpenSSL function RSA_blinding_on() once during startup
++ * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp
++ * here, we wire it back to the OpenSSL software implementation.
++ * Since it is used only once, performance is not a concern.
++ */
++#ifndef OPENSSL_NO_RSA
++ rsa = RSA_PKCS1_SSLeay();
++ pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp;
++ pk11_rsa->bn_mod_exp = rsa->bn_mod_exp;
++ if (pk11_have_recover != CK_TRUE)
++ pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec;
++#endif /* OPENSSL_NO_RSA */
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ LOCK_OBJSTORE(OP_DSA);
++ LOCK_OBJSTORE(OP_DH);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ CK_ULONG ul_state_len;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ /*
++ * Disable digest if C_GetOperationState is not supported since
++ * this function is required by OpenSSL digest copy function
++ */
++ /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */
++ if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len)
++ != CKR_OK) {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: C_GetOperationState() not supported, "
++ "setting digest_count to 0\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ digest_count = 0;
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ break;
++#endif
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++#ifndef OPENSSL_NO_RSA
++ (void) pk11_destroy_rsa_key_objects(NULL);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ (void) pk11_destroy_dsa_key_objects(NULL);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ (void) pk11_destroy_dh_key_objects(NULL);
++#endif /* OPENSSL_NO_DH */
++ (void) pk11_destroy_cipher_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ case OP_DIGEST:
++ case OP_CIPHER:
++ myslot = SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ break;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ sp->opdata_dsa_pub_num = NULL;
++ sp->opdata_dsa_priv = NULL;
++ sp->opdata_dsa_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ sp->opdata_dh_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DH */
++ case OP_CIPHER:
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ sp->opdata_encrypt = -1;
++ break;
++ default:
++ break;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++/* Destroy DSA public key from single session. */
++int
++pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key,
++ ret, uselock, OP_DSA, CK_FALSE);
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy DSA private key from single session. */
++int
++pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key,
++ ret, uselock, OP_DSA, CK_TRUE);
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv = NULL;
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_dsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_dsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++/* Destroy DH key from single session. */
++int
++pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dh_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dh_key,
++ ret, uselock, OP_DH, CK_TRUE);
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DH key object wrapper.
++ *
++ * arg0: pointer to PKCS#11 engine session structure
++ * if session is NULL, try to destroy all objects in the free list
++ */
++int
++pk11_destroy_dh_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DH].head;
++ uselock = FALSE;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dh_object(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DH */
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/* Symmetric ciphers and digests support functions */
++
++static int
++cipher_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; i++)
++ if (ciphers[i].nid == nid)
++ return (ciphers[i].id);
++ return (-1);
++ }
++
++static int
++pk11_usable_ciphers(const int **nids)
++ {
++ if (cipher_count > 0)
++ *nids = cipher_nids;
++ else
++ *nids = NULL;
++ return (cipher_count);
++ }
++
++static int
++pk11_usable_digests(const int **nids)
++ {
++ if (digest_count > 0)
++ *nids = digest_nids;
++ else
++ *nids = NULL;
++ return (digest_count);
++ }
++
++/*
++ * Init context for encryption or decryption using a symmetric key.
++ */
++static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher,
++ PK11_SESSION *sp, CK_MECHANISM_PTR pmech)
++ {
++ CK_RV rv;
++ CK_AES_CTR_PARAMS ctr_params;
++
++ /*
++ * We expect pmech->mechanism to be already set and
++ * pParameter/ulParameterLen initialized to NULL/0 before
++ * pk11_init_symetric() is called.
++ */
++ OPENSSL_assert(pmech->mechanism != 0);
++ OPENSSL_assert(pmech->pParameter == NULL);
++ OPENSSL_assert(pmech->ulParameterLen == 0);
++
++ if (ctx->cipher->nid == NID_aes_128_ctr ||
++ ctx->cipher->nid == NID_aes_192_ctr ||
++ ctx->cipher->nid == NID_aes_256_ctr)
++ {
++ pmech->pParameter = (void *)(&ctr_params);
++ pmech->ulParameterLen = sizeof (ctr_params);
++ /*
++ * For now, we are limited to the fixed length of the counter,
++ * it covers the whole counter block. That's what RFC 4344
++ * needs. For more information on internal structure of the
++ * counter block, see RFC 3686. If needed in the future, we can
++ * add code so that the counter length can be set via
++ * ENGINE_ctrl() function.
++ */
++ ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8;
++ OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE);
++ (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE);
++ }
++ else
++ {
++ if (pcipher->iv_len > 0)
++ {
++ pmech->pParameter = (void *)ctx->iv;
++ pmech->ulParameterLen = pcipher->iv_len;
++ }
++ }
++
++ /* if we get here, the encryption needs to be reinitialized */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++ else
++ rv = pFuncList->C_DecryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ?
++ PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/* ARGSUSED */
++static int
++pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc)
++ {
++ CK_MECHANISM mech;
++ int index;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ PK11_CIPHER *p_ciph_table_row;
++
++ state->sp = NULL;
++
++ index = cipher_nid_to_pk11(ctx->cipher->nid);
++ if (index < 0 || index >= PK11_CIPHER_MAX)
++ return (0);
++
++ p_ciph_table_row = &ciphers[index];
++ /*
++ * iv_len in the ctx->cipher structure is the maximum IV length for the
++ * current cipher and it must be less or equal to the IV length in our
++ * ciphers table. The key length must be in the allowed interval. From
++ * all cipher modes that the PKCS#11 engine supports only RC4 allows a
++ * key length to be in some range, all other NIDs have a precise key
++ * length. Every application can define its own EVP functions so this
++ * code serves as a sanity check.
++ *
++ * Note that the reason why the IV length in ctx->cipher might be
++ * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs
++ * macro to define functions that return EVP structures for all DES
++ * modes. So, even ECB modes get 8 byte IV.
++ */
++ if (ctx->cipher->iv_len < p_ciph_table_row->iv_len ||
++ ctx->key_len < p_ciph_table_row->min_key_len ||
++ ctx->key_len > p_ciph_table_row->max_key_len) {
++ PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM);
++ return (0);
++ }
++
++ if ((sp = pk11_get_session(OP_CIPHER)) == NULL)
++ return (0);
++
++ /* if applicable, the mechanism parameter is used for IV */
++ mech.mechanism = p_ciph_table_row->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ /* The key object is destroyed here if it is not the current key. */
++ (void) check_new_cipher_key(sp, key, ctx->key_len);
++
++ /*
++ * If the key is the same and the encryption is also the same, then
++ * just reuse it. However, we must not forget to reinitialize the
++ * context that was finalized in pk11_cipher_cleanup().
++ */
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE &&
++ sp->opdata_encrypt == ctx->encrypt)
++ {
++ state->sp = sp;
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ return (1);
++ }
++
++ /*
++ * Check if the key has been invalidated. If so, a new key object
++ * needs to be created.
++ */
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ sp->opdata_cipher_key = pk11_get_cipher_key(
++ ctx, key, p_ciph_table_row->key_type, sp);
++ }
++
++ if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1)
++ {
++ /*
++ * The previous encryption/decryption is different. Need to
++ * terminate the previous * active encryption/decryption here.
++ */
++ if (!pk11_cipher_final(sp))
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++ }
++
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ /* now initialize the context with a new key */
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ sp->opdata_encrypt = ctx->encrypt;
++ state->sp = sp;
++
++ return (1);
++ }
++
++/*
++ * When reusing the same key in an encryption/decryption session for a
++ * decryption/encryption session, we need to close the active session
++ * and recreate a new one. Note that the key is in the global session so
++ * that it needs not be recreated.
++ *
++ * It is more appropriate to use C_En/DecryptFinish here. At the time of this
++ * development, these two functions in the PKCS#11 libraries used return
++ * unexpected errors when passing in 0 length output. It may be a good
++ * idea to try them again if performance is a problem here and fix
++ * C_En/DecryptFinial if there are bugs there causing the problem.
++ */
++static int
++pk11_cipher_final(PK11_SESSION *sp)
++ {
++ CK_RV rv;
++
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * An engine interface function. The calling function allocates sufficient
++ * memory for the output buffer "out" to hold the results.
++ */
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl)
++#else
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl)
++#endif
++ {
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ CK_RV rv;
++ unsigned long outl = inl;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ sp = (PK11_SESSION *) state->sp;
++
++ if (!inl)
++ return (1);
++
++ /* RC4 is the only stream cipher we support */
++ if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0)
++ return (0);
++
++ if (ctx->encrypt)
++ {
++ rv = pFuncList->C_EncryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_ENCRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++ else
++ {
++ rv = pFuncList->C_DecryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_DECRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++
++ /*
++ * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always
++ * the same size of input.
++ * The application has guaranteed to call the block ciphers with
++ * correctly aligned buffers.
++ */
++ if (inl != outl)
++ return (0);
++
++ return (1);
++ }
++
++/*
++ * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal()
++ * here is the right thing because in EVP_DecryptFinal_ex(), engine's
++ * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but
++ * the engine can't find out that it's the finalizing call. We wouldn't
++ * necessarily have to finalize the context here since reinitializing it with
++ * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness,
++ * let's do it. Some implementations might leak memory if the previously used
++ * context is initialized without finalizing it first.
++ */
++static int
++pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_ULONG len = EVP_MAX_BLOCK_LENGTH;
++ CK_BYTE buf[EVP_MAX_BLOCK_LENGTH];
++ PK11_CIPHER_STATE *state = ctx->cipher_data;
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * We are not interested in the data here, we just need to get
++ * rid of the context.
++ */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptFinal(
++ state->sp->session, buf, &len);
++ else
++ rv = pFuncList->C_DecryptFinal(
++ state->sp->session, buf, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ?
++ PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv);
++ pk11_return_session(state->sp, OP_CIPHER);
++ return (0);
++ }
++
++ pk11_return_session(state->sp, OP_CIPHER);
++ state->sp = NULL;
++ }
++
++ return (1);
++ }
++
++/*
++ * Registered by the ENGINE when used to find out how to deal with
++ * a particular NID in the ENGINE. This says what we'll do at the
++ * top level - note, that list is restricted by what we answer with
++ */
++/* ARGSUSED */
++static int
++pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid)
++ {
++ if (!cipher)
++ return (pk11_usable_ciphers(nids));
++
++ switch (nid)
++ {
++ case NID_des_ede3_cbc:
++ *cipher = &pk11_3des_cbc;
++ break;
++ case NID_des_cbc:
++ *cipher = &pk11_des_cbc;
++ break;
++ case NID_des_ede3_ecb:
++ *cipher = &pk11_3des_ecb;
++ break;
++ case NID_des_ecb:
++ *cipher = &pk11_des_ecb;
++ break;
++ case NID_aes_128_cbc:
++ *cipher = &pk11_aes_128_cbc;
++ break;
++ case NID_aes_192_cbc:
++ *cipher = &pk11_aes_192_cbc;
++ break;
++ case NID_aes_256_cbc:
++ *cipher = &pk11_aes_256_cbc;
++ break;
++ case NID_aes_128_ecb:
++ *cipher = &pk11_aes_128_ecb;
++ break;
++ case NID_aes_192_ecb:
++ *cipher = &pk11_aes_192_ecb;
++ break;
++ case NID_aes_256_ecb:
++ *cipher = &pk11_aes_256_ecb;
++ break;
++ case NID_bf_cbc:
++ *cipher = &pk11_bf_cbc;
++ break;
++ case NID_rc4:
++ *cipher = &pk11_rc4;
++ break;
++ case NID_aes_128_ctr:
++ *cipher = &pk11_aes_128_ctr;
++ break;
++ case NID_aes_192_ctr:
++ *cipher = &pk11_aes_192_ctr;
++ break;
++ case NID_aes_256_ctr:
++ *cipher = &pk11_aes_256_ctr;
++ break;
++ default:
++ *cipher = NULL;
++ break;
++ }
++ return (*cipher != NULL);
++ }
++
++/* ARGSUSED */
++static int
++pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid)
++ {
++ if (!digest)
++ return (pk11_usable_digests(nids));
++
++ switch (nid)
++ {
++ case NID_md5:
++ *digest = &pk11_md5;
++ break;
++ case NID_sha1:
++ *digest = &pk11_sha1;
++ break;
++ case NID_sha224:
++ *digest = &pk11_sha224;
++ break;
++ case NID_sha256:
++ *digest = &pk11_sha256;
++ break;
++ case NID_sha384:
++ *digest = &pk11_sha384;
++ break;
++ case NID_sha512:
++ *digest = &pk11_sha512;
++ break;
++ default:
++ *digest = NULL;
++ break;
++ }
++ return (*digest != NULL);
++ }
++
++
++/* Create a secret key object in a PKCS#11 session */
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY;
++ CK_ULONG ul_key_attr_count = 6;
++ unsigned char key_buf[PK11_KEY_LEN_MAX];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VALUE, (void*) NULL, 0},
++ };
++
++ /*
++ * Create secret key object in global_session. All other sessions
++ * can use the key handles. Here is why:
++ * OpenSSL will call EncryptInit and EncryptUpdate using a secret key.
++ * It may then call DecryptInit and DecryptUpdate using the same key.
++ * To use the same key object, we need to call EncryptFinal with
++ * a 0 length message. Currently, this does not work for 3DES
++ * mechanism. To get around this problem, we close the session and
++ * then create a new session to use the same key object. When a session
++ * is closed, all the object handles will be invalid. Thus, create key
++ * objects in a global session, an individual session may be closed to
++ * terminate the active operation.
++ */
++ CK_SESSION_HANDLE session = global_session;
++ a_key_template[0].pValue = &obj_key;
++ a_key_template[1].pValue = &key_type;
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ a_key_template[5].pValue = (void *) key;
++ }
++ else
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ memcpy(key_buf, key, ctx->key_len);
++ if ((key_type == CKK_DES) ||
++ (key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[0]);
++ if ((key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[8]);
++ if (key_type == CKK_DES3)
++ DES_fixup_key_parity((DES_cblock *) &key_buf[16]);
++ a_key_template[5].pValue = (void *) key_buf;
++ }
++ a_key_template[5].ulValueLen = (unsigned long) ctx->key_len;
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++
++ /*
++ * Save the key information used in this session.
++ * The max can be saved is PK11_KEY_LEN_MAX.
++ */
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ sp->opdata_key_len = PK11_KEY_LEN_MAX;
++ (void) memcpy(sp->opdata_key, key, sp->opdata_key_len);
++ }
++ else
++ {
++ sp->opdata_key_len = ctx->key_len;
++ (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len);
++ }
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++err:
++
++ return (h_key);
++ }
++
++static int
++md_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; i++)
++ if (digests[i].nid == nid)
++ return (digests[i].id);
++ return (-1);
++ }
++
++static int
++pk11_digest_init(EVP_MD_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_MECHANISM mech;
++ int index;
++ PK11_SESSION *sp;
++ PK11_DIGEST *pdp;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ state->sp = NULL;
++
++ index = md_nid_to_pk11(ctx->digest->type);
++ if (index < 0 || index >= PK11_DIGEST_MAX)
++ return (0);
++
++ pdp = &digests[index];
++ if ((sp = pk11_get_session(OP_DIGEST)) == NULL)
++ return (0);
++
++ /* at present, no parameter is needed for supported digests */
++ mech.mechanism = pdp->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ rv = pFuncList->C_DigestInit(sp->session, &mech);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv);
++ pk11_return_session(sp, OP_DIGEST);
++ return (0);
++ }
++
++ state->sp = sp;
++
++ return (1);
++ }
++
++static int
++pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
++ {
++ CK_RV rv;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ /* 0 length message will cause a failure in C_DigestFinal */
++ if (count == 0)
++ return (1);
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data,
++ count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ return (1);
++ }
++
++static int
++pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
++ {
++ CK_RV rv;
++ unsigned long len;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++ len = ctx->digest->md_size;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestFinal(state->sp->session, md, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ if (ctx->digest->md_size != len)
++ return (0);
++
++ /*
++ * Final is called and digest is returned, so return the session
++ * to the pool
++ */
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++
++ return (1);
++ }
++
++static int
++pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
++ {
++ CK_RV rv;
++ int ret = 0;
++ PK11_CIPHER_STATE *state, *state_to;
++ CK_BYTE_PTR pstate = NULL;
++ CK_ULONG ul_state_len;
++
++ /* The copy-from state */
++ state = (PK11_CIPHER_STATE *) from->md_data;
++ if (state == NULL || state->sp == NULL)
++ goto err;
++
++ /* Initialize the copy-to state */
++ if (!pk11_digest_init(to))
++ goto err;
++ state_to = (PK11_CIPHER_STATE *) to->md_data;
++
++ /* Get the size of the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, NULL,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++ if (ul_state_len == 0)
++ {
++ goto err;
++ }
++
++ pstate = OPENSSL_malloc(ul_state_len);
++ if (pstate == NULL)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, pstate,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++
++ /* Set the operation state of the copy-to session */
++ rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate,
++ ul_state_len, 0, 0);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY,
++ PK11_R_SET_OPERATION_STATE, rv);
++ goto err;
++ }
++
++ ret = 1;
++err:
++ if (pstate != NULL)
++ OPENSSL_free(pstate);
++
++ return (ret);
++ }
++
++/* Return any pending session state to the pool */
++static int
++pk11_digest_cleanup(EVP_MD_CTX *ctx)
++ {
++ PK11_CIPHER_STATE *state = ctx->md_data;
++ unsigned char buf[EVP_MAX_MD_SIZE];
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * If state->sp is not NULL then pk11_digest_final() has not
++ * been called yet. We must call it now to free any memory
++ * that might have been allocated in the token when
++ * pk11_digest_init() was called. pk11_digest_final()
++ * will return the session to the cache.
++ */
++ if (!pk11_digest_final(ctx, buf))
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * Check if the new key is the same as the key object in the session. If the key
++ * is the same, no need to create a new key object. Otherwise, the old key
++ * object needs to be destroyed and a new one will be created. Return 1 for
++ * cache hit, 0 for cache miss. Note that we must check the key length first
++ * otherwise we could end up reusing a different, longer key with the same
++ * prefix.
++ */
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len)
++ {
++ if (sp->opdata_key_len != key_len ||
++ memcmp(sp->opdata_key, key, key_len) != 0)
++ {
++ (void) pk11_destroy_cipher_key_objects(sp);
++ return (0);
++ }
++ return (1);
++ }
++
++/* Destroy one or more secret key objects. */
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_CIPHER].head;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE)
++ {
++ /*
++ * The secret key object is created in the
++ * global_session. See pk11_get_cipher_key().
++ */
++ if (pk11_destroy_object(global_session,
++ sp->opdata_cipher_key, CK_FALSE) == 0)
++ goto err;
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ }
++ }
++ ret = 1;
++err:
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_X_509
++ * CKM_RSA_PKCS
++ * CKM_DSA
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * Symmetric ciphers optionally supported
++ *
++ * CKM_DES3_CBC
++ * CKM_DES_CBC
++ * CKM_AES_CBC
++ * CKM_DES3_ECB
++ * CKM_DES_ECB
++ * CKM_AES_ECB
++ * CKM_AES_CTR
++ * CKM_RC4
++ * CKM_BLOWFISH_CBC
++ *
++ * Digests optionally supported
++ *
++ * CKM_MD5
++ * CKM_SHA_1
++ * CKM_SHA224
++ * CKM_SHA256
++ * CKM_SHA384
++ * CKM_SHA512
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ int slot_n_cipher = 0;
++ int slot_n_digest = 0;
++ CK_SLOT_ID current_slot = 0;
++ int current_slot_n_cipher = 0;
++ int current_slot_n_digest = 0;
++
++ int local_cipher_nids[PK11_CIPHER_MAX];
++ int local_digest_nids[PK11_DIGEST_MAX];
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ CK_BBOOL slot_has_recover = CK_FALSE;
++ CK_BBOOL slot_has_dsa = CK_FALSE;
++ CK_BBOOL slot_has_dh = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_RSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ /*
++ * Check if this slot is capable of encryption,
++ * decryption, sign, and verify with CKM_RSA_X_509.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_RSA_X_509, &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY) &&
++ (mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT)))
++ {
++ slot_has_rsa = CK_TRUE;
++ if (mech_info.flags & CKF_VERIFY_RECOVER)
++ {
++ slot_has_recover = CK_TRUE;
++ }
++ }
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_DSA.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
++ &mech_info);
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ slot_has_dsa = CK_TRUE;
++ }
++
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ /*
++ * Check if this slot is capable of DH key generataion and
++ * derivation.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
++
++ if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
++ {
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_DERIVE, &mech_info);
++ if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
++ {
++ slot_has_dh = CK_TRUE;
++ }
++ }
++#endif /* OPENSSL_NO_DH */
++
++ if (!found_candidate_slot &&
++ (slot_has_rsa || slot_has_dsa || slot_has_dh))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ pk11_have_recover = slot_has_recover;
++ pk11_have_dsa = slot_has_dsa;
++ pk11_have_dh = slot_has_dh;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa/dsa/dh\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ found_candidate_slot = CK_FALSE;
++ best_slot_sofar = 0;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ current_slot = pSlotList[i];
++ current_slot_n_cipher = 0;
++ current_slot_n_digest = 0;
++ (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
++ (void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
++
++ pk11_find_symmetric_ciphers(pFuncList, current_slot,
++ &current_slot_n_cipher, local_cipher_nids);
++
++ pk11_find_digests(pFuncList, current_slot,
++ &current_slot_n_digest, local_digest_nids);
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG,
++ current_slot_n_cipher);
++ fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG,
++ current_slot_n_digest);
++ fprintf(stderr, "%s: best so far cipher/digest slot: %d\n",
++ PK11_DBG, best_slot_sofar);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * If the current slot supports more ciphers/digests than
++ * the previous best one we change the current best to this one,
++ * otherwise leave it where it is.
++ */
++ if ((current_slot_n_cipher + current_slot_n_digest) >
++ (slot_n_cipher + slot_n_digest))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: changing best so far slot to %d\n",
++ PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = SLOTID = current_slot;
++ cipher_count = slot_n_cipher = current_slot_n_cipher;
++ digest_count = slot_n_digest = current_slot_n_digest;
++ (void) memcpy(cipher_nids, local_cipher_nids,
++ sizeof (local_cipher_nids));
++ (void) memcpy(digest_nids, local_digest_nids,
++ sizeof (local_digest_nids));
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover);
++ fprintf(stderr,
++ "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa);
++ fprintf(stderr,
++ "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++ fprintf(stderr,
++ "%s: cipher_count %d\n", PK11_DBG, cipher_count);
++ fprintf(stderr,
++ "%s: digest_count %d\n", PK11_DBG, digest_count);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ OPENSSL_free(hw_cnids);
++ OPENSSL_free(hw_dnids);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist,
++ int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher,
++ int *local_cipher_nids, int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if ((mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT))
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(ciphers[id].nid, hw_cnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_cipher_nids[(*current_slot_n_cipher)++] =
++ ciphers[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if (mech_info.flags & CKF_DIGEST)
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(digests[id].nid, hw_dnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_digest_nids[(*current_slot_n_digest)++] =
++ digests[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++/* Find what symmetric ciphers this slot supports. */
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; ++i)
++ {
++ pk11_get_symmetric_cipher(pflist, current_slot,
++ ciphers[i].mech_type, current_slot_n_cipher,
++ local_cipher_nids, ciphers[i].id);
++ }
++ }
++
++/* Find what digest algorithms this slot supports. */
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; ++i)
++ {
++ pk11_get_digest(pflist, current_slot, digests[i].mech_type,
++ current_slot_n_digest, local_digest_nids, digests[i].id);
++ }
++ }
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * It would be great if we could use pkcs11_kernel directly since this library
++ * offers hardware slots only. That's the easiest way to achieve the situation
++ * where we use the hardware accelerators when present and OpenSSL native code
++ * otherwise. That presumes the fact that OpenSSL native code is faster than the
++ * code in the soft token. It's a logical assumption - Crypto Framework has some
++ * inherent overhead so going there for the software implementation of a
++ * mechanism should be logically slower in contrast to the OpenSSL native code,
++ * presuming that both implementations are of similar speed. For example, the
++ * soft token for AES is roughly three times slower than OpenSSL for 64 byte
++ * blocks and still 20% slower for 8KB blocks. So, if we want to ship products
++ * that use the PKCS#11 engine by default, we must somehow avoid that regression
++ * on machines without hardware acceleration. That's why switching to the
++ * pkcs11_kernel library seems like a very good idea.
++ *
++ * The problem is that OpenSSL built with SunStudio is roughly 2x slower for
++ * asymmetric operations (RSA/DSA/DH) than the soft token built with the same
++ * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11
++ * library, we would have had a performance regression on machines without
++ * hardware acceleration for asymmetric operations for all applications that use
++ * the PKCS#11 engine. There is one such application - Apache web server since
++ * it's shipped configured to use the PKCS#11 engine by default. Having said
++ * that, we can't switch to the pkcs11_kernel library now and have to come with
++ * a solution that, on non-accelerated machines, uses the OpenSSL native code
++ * for all symmetric ciphers and digests while it uses the soft token for
++ * asymmetric operations.
++ *
++ * This is the idea: dlopen() pkcs11_kernel directly and find out what
++ * mechanisms are there. We don't care about duplications (more slots can
++ * support the same mechanism), we just want to know what mechanisms can be
++ * possibly supported in hardware on that particular machine. As said before,
++ * pkcs11_kernel will show you hardware providers only.
++ *
++ * Then, we rely on the fact that since we use libpkcs11 library we will find
++ * the metaslot. When we go through the metaslot's mechanisms for symmetric
++ * ciphers and digests, we check that any found mechanism is in the table
++ * created using the pkcs11_kernel library. So, as a result we have two arrays
++ * of mechanisms that were advertised as supported in hardware which was the
++ * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token
++ * code for symmetric ciphers and digests. See pk11_choose_slots() for more
++ * information.
++ *
++ * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined
++ * the code won't be used.
++ */
++#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64)
++static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1";
++#else
++static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1";
++#endif
++
++/*
++ * Check hardware capabilities of the machines. The output are two lists,
++ * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware
++ * providers together. They are not sorted and may contain duplicate mechanisms.
++ */
++static int check_hw_mechanisms(void)
++ {
++ int i;
++ CK_RV rv;
++ void *handle;
++ CK_C_GetFunctionList p;
++ CK_TOKEN_INFO token_info;
++ CK_ULONG ulSlotCount = 0;
++ int n_cipher = 0, n_digest = 0;
++ CK_FUNCTION_LIST_PTR pflist = NULL;
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL;
++ int hw_ctable_size, hw_dtable_size;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n",
++ PK11_DBG);
++#endif
++ if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ if ((p = (CK_C_GetFunctionList)dlsym(handle,
++ PK11_GET_FUNCTION_LIST)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ if (p(&pflist) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /* no slots, set the hw mechanism tables as empty */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG);
++#endif
++ hw_cnids = OPENSSL_malloc(sizeof (int));
++ hw_dnids = OPENSSL_malloc(sizeof (int));
++ if (hw_cnids == NULL || hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ /* this means empty tables */
++ hw_cnids[0] = NID_undef;
++ hw_dnids[0] = NID_undef;
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the slot list for processing */
++ if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /*
++ * We don't care about duplicit mechanisms in multiple slots and also
++ * reserve one slot for the terminal NID_undef which we use to stop the
++ * search.
++ */
++ hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1;
++ hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1;
++ tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int));
++ tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int));
++ if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * Do not use memset since we should not rely on the fact that NID_undef
++ * is zero now.
++ */
++ for (i = 0; i < hw_ctable_size; ++i)
++ tmp_hw_cnids[i] = NID_undef;
++ for (i = 0; i < hw_dtable_size; ++i)
++ tmp_hw_dnids[i] = NID_undef;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel);
++ fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount);
++ fprintf(stderr, "%s: now looking for mechs supported in hw\n",
++ PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * We are filling the hw mech tables here. Global tables are
++ * still NULL so all mechanisms are put into tmp tables.
++ */
++ pk11_find_symmetric_ciphers(pflist, pSlotList[i],
++ &n_cipher, tmp_hw_cnids);
++ pk11_find_digests(pflist, pSlotList[i],
++ &n_digest, tmp_hw_dnids);
++ }
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects. Also, C_Finalize() is triggered by
++ * dlclose(3C).
++ */
++#if 0
++ pflist->C_Finalize(NULL);
++#endif
++ OPENSSL_free(pSlotList);
++ (void) dlclose(handle);
++ hw_cnids = tmp_hw_cnids;
++ hw_dnids = tmp_hw_dnids;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++
++err:
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++ if (tmp_hw_cnids != NULL)
++ OPENSSL_free(tmp_hw_cnids);
++ if (tmp_hw_dnids != NULL)
++ OPENSSL_free(tmp_hw_dnids);
++
++ return (0);
++ }
++
++/*
++ * Check presence of a NID in the table of NIDs. The table may be NULL (i.e.,
++ * non-existent).
++ */
++static int nid_in_table(int nid, int *nid_table)
++ {
++ int i = 0;
++
++ /*
++ * a special case. NULL means that we are initializing a new
++ * table.
++ */
++ if (nid_table == NULL)
++ return (1);
++
++ /*
++ * the table is never full, there is always at least one
++ * NID_undef.
++ */
++ while (nid_table[i] != NID_undef)
++ {
++ if (nid_table[i++] == nid)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++ }
++
++ return (0);
++ }
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11_err.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.5
+--- /dev/null Mon Jun 13 15:26:29 2016
++++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 00:43:26 2011
+@@ -0,0 +1,288 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_err.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <openssl/err.h>
++#include "hw_pk11_err.h"
++
++/* BEGIN ERROR CODES */
++#ifndef OPENSSL_NO_ERR
++static ERR_STRING_DATA pk11_str_functs[]=
++{
++{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"},
++{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"},
++{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"},
++{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"},
++{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"},
++{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"},
++{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"},
++{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"},
++{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"},
++{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"},
++{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"},
++{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"},
++{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"},
++{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"},
++{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"},
++{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"},
++{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"},
++{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"},
++{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"},
++{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"},
++{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"},
++{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"},
++{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"},
++{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"},
++{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"},
++{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"},
++{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"},
++{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"},
++{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"},
++{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"},
++{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"},
++{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"},
++{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"},
++{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"},
++{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"},
++{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"},
++{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"},
++{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"},
++{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"},
++{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"},
++{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"},
++{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"},
++{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"},
++{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"},
++{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"},
++{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"},
++{ 0, NULL}
++};
++
++static ERR_STRING_DATA pk11_str_reasons[]=
++{
++{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"},
++{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"},
++{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"},
++{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"},
++{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"},
++{ PK11_R_INITIALIZE, "C_Initialize failed"},
++{ PK11_R_FINALIZE, "C_Finalize failed"},
++{ PK11_R_GETINFO, "C_GetInfo faile"},
++{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"},
++{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"},
++{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"},
++{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"},
++{ PK11_R_NO_MODULUS, "no modulus"},
++{ PK11_R_NO_EXPONENT, "no exponent"},
++{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"},
++{ PK11_R_FINDOBJECTS, "C_FindObjects failed"},
++{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"},
++{ PK11_R_CREATEOBJECT, "C_CreateObject failed"},
++{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"},
++{ PK11_R_OPENSESSION, "C_OpenSession failed"},
++{ PK11_R_CLOSESESSION, "C_CloseSession failed"},
++{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"},
++{ PK11_R_ENCRYPT, "C_Encrypt failed"},
++{ PK11_R_SIGNINIT, "C_SignInit failed"},
++{ PK11_R_SIGN, "C_Sign failed"},
++{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"},
++{ PK11_R_DECRYPT, "C_Decrypt failed"},
++{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"},
++{ PK11_R_VERIFY, "C_Verify failed"},
++{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"},
++{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"},
++{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"},
++{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"},
++{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"},
++{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"},
++{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"},
++{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"},
++{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"},
++{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"},
++{ PK11_R_DIGEST_TOO_BIG, "digest too big"},
++{ PK11_R_MALLOC_FAILURE, "malloc failure"},
++{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"},
++{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"},
++{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"},
++{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"},
++{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"},
++{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"},
++{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"},
++{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"},
++{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"},
++{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"},
++{ PK11_R_DIGESTINIT, "C_DigestInit failed"},
++{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"},
++{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"},
++{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"},
++{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"},
++{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"},
++{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"},
++{ PK11_R_DERIVEKEY, "C_DeriveKey failed"},
++{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"},
++{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"},
++{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"},
++{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"},
++{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"},
++{ PK11_R_ADD_NID_FAILED, "failed to add NID" },
++{ PK11_R_ATFORK_FAILED, "atfork() failed" },
++{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" },
++{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" },
++{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" },
++{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" },
++{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" },
++{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" },
++{ PK11_R_PIPE_FAILED, "pipe() failed" },
++{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" },
++{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" },
++{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" },
++{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" },
++{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" },
++{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" },
++{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" },
++{ PK11_R_NO_OBJECT_FOUND, "specified object not found" },
++{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" },
++{ PK11_R_SYSCONF_FAILED, "sysconf() failed" },
++{ PK11_R_MMAP_FAILED, "mmap() failed" },
++{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" },
++{ PK11_R_MLOCK_FAILED, "mlock() failed" },
++{ PK11_R_FORK_FAILED, "fork() failed" },
++{ 0, NULL}
++};
++#endif /* OPENSSL_NO_ERR */
++
++static int pk11_lib_error_code = 0;
++static int pk11_error_init = 1;
++
++static void
++ERR_load_pk11_strings(void)
++ {
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++
++ if (pk11_error_init)
++ {
++ pk11_error_init = 0;
++#ifndef OPENSSL_NO_ERR
++ ERR_load_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_load_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ }
++}
++
++static void
++ERR_unload_pk11_strings(void)
++ {
++ if (pk11_error_init == 0)
++ {
++#ifndef OPENSSL_NO_ERR
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ pk11_error_init = 1;
++ }
++}
++
++void
++ERR_pk11_error(int function, int reason, char *file, int line)
++{
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++ ERR_PUT_error(pk11_lib_error_code, function, reason, file, line);
++}
++
++void
++PK11err_add_data(int function, int reason, CK_RV rv)
++{
++ char tmp_buf[20];
++
++ PK11err(function, reason);
++ (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++}
+Index: openssl/crypto/engine/hw_pk11_err.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.13
+--- /dev/null Mon Jun 13 15:26:29 2016
++++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:04:20 2013
+@@ -0,0 +1,440 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#ifndef HW_PK11_ERR_H
++#define HW_PK11_ERR_H
++
++void ERR_pk11_error(int function, int reason, char *file, int line);
++void PK11err_add_data(int function, int reason, CK_RV rv);
++#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__)
++
++/* Error codes for the PK11 functions. */
++
++/* Function codes. */
++
++#define PK11_F_INIT 100
++#define PK11_F_FINISH 101
++#define PK11_F_DESTROY 102
++#define PK11_F_CTRL 103
++#define PK11_F_RSA_INIT 104
++#define PK11_F_RSA_FINISH 105
++#define PK11_F_GET_PUB_RSA_KEY 106
++#define PK11_F_GET_PRIV_RSA_KEY 107
++#define PK11_F_RSA_GEN_KEY 108
++#define PK11_F_RSA_PUB_ENC 109
++#define PK11_F_RSA_PRIV_ENC 110
++#define PK11_F_RSA_PUB_DEC 111
++#define PK11_F_RSA_PRIV_DEC 112
++#define PK11_F_RSA_SIGN 113
++#define PK11_F_RSA_VERIFY 114
++#define PK11_F_RAND_ADD 115
++#define PK11_F_RAND_BYTES 116
++#define PK11_F_GET_SESSION 117
++#define PK11_F_FREE_SESSION 118
++#define PK11_F_LOAD_PUBKEY 119
++#define PK11_F_LOAD_PRIVKEY 120
++#define PK11_F_RSA_PUB_ENC_LOW 121
++#define PK11_F_RSA_PRIV_ENC_LOW 122
++#define PK11_F_RSA_PUB_DEC_LOW 123
++#define PK11_F_RSA_PRIV_DEC_LOW 124
++#define PK11_F_DSA_SIGN 125
++#define PK11_F_DSA_VERIFY 126
++#define PK11_F_DSA_INIT 127
++#define PK11_F_DSA_FINISH 128
++#define PK11_F_GET_PUB_DSA_KEY 129
++#define PK11_F_GET_PRIV_DSA_KEY 130
++#define PK11_F_DH_INIT 131
++#define PK11_F_DH_FINISH 132
++#define PK11_F_MOD_EXP_DH 133
++#define PK11_F_GET_DH_KEY 134
++#define PK11_F_FREE_ALL_SESSIONS 135
++#define PK11_F_SETUP_SESSION 136
++#define PK11_F_DESTROY_OBJECT 137
++#define PK11_F_CIPHER_INIT 138
++#define PK11_F_CIPHER_DO_CIPHER 139
++#define PK11_F_GET_CIPHER_KEY 140
++#define PK11_F_DIGEST_INIT 141
++#define PK11_F_DIGEST_UPDATE 142
++#define PK11_F_DIGEST_FINAL 143
++#define PK11_F_CHOOSE_SLOT 144
++#define PK11_F_CIPHER_FINAL 145
++#define PK11_F_LIBRARY_INIT 146
++#define PK11_F_LOAD 147
++#define PK11_F_DH_GEN_KEY 148
++#define PK11_F_DH_COMP_KEY 149
++#define PK11_F_DIGEST_COPY 150
++#define PK11_F_CIPHER_CLEANUP 151
++#define PK11_F_ACTIVE_ADD 152
++#define PK11_F_ACTIVE_DELETE 153
++#define PK11_F_CHECK_HW_MECHANISMS 154
++#define PK11_F_INIT_SYMMETRIC 155
++#define PK11_F_ADD_AES_CTR_NIDS 156
++#define PK11_F_INIT_ALL_LOCKS 157
++#define PK11_F_RETURN_SESSION 158
++#define PK11_F_GET_PIN 159
++#define PK11_F_FIND_ONE_OBJECT 160
++#define PK11_F_CHECK_TOKEN_ATTRS 161
++#define PK11_F_CACHE_PIN 162
++#define PK11_F_MLOCK_PIN_IN_MEMORY 163
++#define PK11_F_TOKEN_LOGIN 164
++#define PK11_F_TOKEN_RELOGIN 165
++#define PK11_F_RUN_ASKPASS 166
++
++/* Reason codes. */
++#define PK11_R_ALREADY_LOADED 100
++#define PK11_R_DSO_FAILURE 101
++#define PK11_R_NOT_LOADED 102
++#define PK11_R_PASSED_NULL_PARAMETER 103
++#define PK11_R_COMMAND_NOT_IMPLEMENTED 104
++#define PK11_R_INITIALIZE 105
++#define PK11_R_FINALIZE 106
++#define PK11_R_GETINFO 107
++#define PK11_R_GETSLOTLIST 108
++#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109
++#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110
++#define PK11_R_GETATTRIBUTVALUE 111
++#define PK11_R_NO_MODULUS 112
++#define PK11_R_NO_EXPONENT 113
++#define PK11_R_FINDOBJECTSINIT 114
++#define PK11_R_FINDOBJECTS 115
++#define PK11_R_FINDOBJECTSFINAL 116
++#define PK11_R_CREATEOBJECT 118
++#define PK11_R_DESTROYOBJECT 119
++#define PK11_R_OPENSESSION 120
++#define PK11_R_CLOSESESSION 121
++#define PK11_R_ENCRYPTINIT 122
++#define PK11_R_ENCRYPT 123
++#define PK11_R_SIGNINIT 124
++#define PK11_R_SIGN 125
++#define PK11_R_DECRYPTINIT 126
++#define PK11_R_DECRYPT 127
++#define PK11_R_VERIFYINIT 128
++#define PK11_R_VERIFY 129
++#define PK11_R_VERIFYRECOVERINIT 130
++#define PK11_R_VERIFYRECOVER 131
++#define PK11_R_GEN_KEY 132
++#define PK11_R_SEEDRANDOM 133
++#define PK11_R_GENERATERANDOM 134
++#define PK11_R_INVALID_MESSAGE_LENGTH 135
++#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136
++#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137
++#define PK11_R_UNKNOWN_PADDING_TYPE 138
++#define PK11_R_PADDING_CHECK_FAILED 139
++#define PK11_R_DIGEST_TOO_BIG 140
++#define PK11_R_MALLOC_FAILURE 141
++#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142
++#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143
++#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144
++#define PK11_R_MISSING_KEY_COMPONENT 145
++#define PK11_R_INVALID_SIGNATURE_LENGTH 146
++#define PK11_R_INVALID_DSA_SIGNATURE_R 147
++#define PK11_R_INVALID_DSA_SIGNATURE_S 148
++#define PK11_R_INCONSISTENT_KEY 149
++#define PK11_R_ENCRYPTUPDATE 150
++#define PK11_R_DECRYPTUPDATE 151
++#define PK11_R_DIGESTINIT 152
++#define PK11_R_DIGESTUPDATE 153
++#define PK11_R_DIGESTFINAL 154
++#define PK11_R_ENCRYPTFINAL 155
++#define PK11_R_DECRYPTFINAL 156
++#define PK11_R_NO_PRNG_SUPPORT 157
++#define PK11_R_GETTOKENINFO 158
++#define PK11_R_DERIVEKEY 159
++#define PK11_R_GET_OPERATION_STATE 160
++#define PK11_R_SET_OPERATION_STATE 161
++#define PK11_R_INVALID_HANDLE 162
++#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163
++#define PK11_R_INVALID_OPERATION_TYPE 164
++#define PK11_R_ADD_NID_FAILED 165
++#define PK11_R_ATFORK_FAILED 166
++
++#define PK11_R_TOKEN_LOGIN_FAILED 167
++#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168
++#define PK11_R_INVALID_PKCS11_URI 169
++#define PK11_R_COULD_NOT_READ_PIN 170
++#define PK11_R_COULD_NOT_OPEN_COMMAND 171
++#define PK11_R_PIPE_FAILED 172
++#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173
++#define PK11_R_BAD_PASSPHRASE_SPEC 174
++#define PK11_R_TOKEN_NOT_INITIALIZED 175
++#define PK11_R_TOKEN_PIN_NOT_SET 176
++#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177
++#define PK11_R_MISSING_OBJECT_LABEL 178
++#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179
++#define PK11_R_PRIV_KEY_NOT_FOUND 180
++#define PK11_R_NO_OBJECT_FOUND 181
++#define PK11_R_PIN_CACHING_POLICY_INVALID 182
++#define PK11_R_SYSCONF_FAILED 183
++#define PK11_R_MMAP_FAILED 183
++#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184
++#define PK11_R_MLOCK_FAILED 185
++#define PK11_R_FORK_FAILED 186
++
++/* max byte length of a symetric key we support */
++#define PK11_KEY_LEN_MAX 32
++
++#ifdef NOPTHREADS
++/*
++ * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the
++ * free_session list and active_list but generally serves as a global
++ * per-process lock for the whole engine.
++ *
++ * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as
++ * the global engine lock. This is not optimal w.r.t. performance but
++ * it's safe.
++ */
++#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC
++#endif
++
++/*
++ * This structure encapsulates all reusable information for a PKCS#11
++ * session. A list of these objects is created on behalf of the
++ * calling application using an on-demand method. Each operation
++ * type (see PK11_OPTYPE below) has its own per-process list.
++ * Each of the lists is basically a cache for faster PKCS#11 object
++ * access to avoid expensive C_Find{,Init,Final}Object() calls.
++ *
++ * When a new request comes in, an object will be taken from the list
++ * (if there is one) or a new one is created to handle the request
++ * (if the list is empty). See pk11_get_session() on how it is done.
++ */
++typedef struct PK11_st_SESSION
++ {
++ struct PK11_st_SESSION *next;
++ CK_SESSION_HANDLE session; /* PK11 session handle */
++ pid_t pid; /* Current process ID */
++ CK_BBOOL pub_persistent; /* is pub key in keystore? */
++ CK_BBOOL priv_persistent;/* is priv key in keystore? */
++ union
++ {
++#ifndef OPENSSL_NO_RSA
++ struct
++ {
++ CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */
++ RSA *rsa_pub; /* pub key addr */
++ BIGNUM *rsa_n_num; /* pub modulus */
++ BIGNUM *rsa_e_num; /* pub exponent */
++ RSA *rsa_priv; /* priv key addr */
++ BIGNUM *rsa_pn_num; /* pub modulus */
++ BIGNUM *rsa_pe_num; /* pub exponent */
++ BIGNUM *rsa_d_num; /* priv exponent */
++ } u_RSA;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ struct
++ {
++ CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */
++ DSA *dsa_pub; /* pub key addr */
++ BIGNUM *dsa_pub_num; /* pub key */
++ DSA *dsa_priv; /* priv key addr */
++ BIGNUM *dsa_priv_num; /* priv key */
++ } u_DSA;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ struct
++ {
++ CK_OBJECT_HANDLE dh_key; /* key handle */
++ DH *dh; /* dh key addr */
++ BIGNUM *dh_priv_num; /* priv dh key */
++ } u_DH;
++#endif /* OPENSSL_NO_DH */
++ struct
++ {
++ CK_OBJECT_HANDLE cipher_key; /* key handle */
++ unsigned char key[PK11_KEY_LEN_MAX];
++ int key_len; /* priv key len */
++ int encrypt; /* 1/0 enc/decr */
++ } u_cipher;
++ } opdata_u;
++ } PK11_SESSION;
++
++#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key
++#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key
++#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub
++#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv
++#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num
++#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num
++#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num
++#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num
++#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num
++#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key
++#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key
++#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub
++#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num
++#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv
++#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num
++#define opdata_dh_key opdata_u.u_DH.dh_key
++#define opdata_dh opdata_u.u_DH.dh
++#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num
++#define opdata_cipher_key opdata_u.u_cipher.cipher_key
++#define opdata_key opdata_u.u_cipher.key
++#define opdata_key_len opdata_u.u_cipher.key_len
++#define opdata_encrypt opdata_u.u_cipher.encrypt
++
++/*
++ * We have 3 different groups of operation types:
++ * 1) asymmetric operations
++ * 2) random operations
++ * 3) symmetric and digest operations
++ *
++ * This division into groups stems from the fact that it's common that hardware
++ * providers may support operations from one group only. For example, hardware
++ * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support
++ * only a single group of operations.
++ *
++ * For every group a different slot can be chosen. That means that we must have
++ * at least 3 different lists of cached PKCS#11 sessions since sessions from
++ * different groups may be initialized in different slots.
++ *
++ * To provide locking granularity in multithreaded environment, the groups are
++ * further splitted into types with each type having a separate session cache.
++ */
++typedef enum PK11_OPTYPE_ENUM
++ {
++ OP_RAND,
++ OP_RSA,
++ OP_DSA,
++ OP_DH,
++ OP_CIPHER,
++ OP_DIGEST,
++ OP_MAX
++ } PK11_OPTYPE;
++
++/*
++ * This structure contains the heads of the lists forming the object caches
++ * and locks associated with the lists.
++ */
++typedef struct PK11_st_CACHE
++ {
++ PK11_SESSION *head;
++#ifndef NOPTHREADS
++ pthread_mutex_t *lock;
++#endif
++ } PK11_CACHE;
++
++/* structure for tracking handles of asymmetric key objects */
++typedef struct PK11_active_st
++ {
++ CK_OBJECT_HANDLE h;
++ unsigned int refcnt;
++ struct PK11_active_st *prev;
++ struct PK11_active_st *next;
++ } PK11_active;
++
++#ifndef NOPTHREADS
++extern pthread_mutex_t *find_lock[];
++#endif
++extern PK11_active *active_list[];
++/*
++ * These variables are specific for the RSA keys by reference code. See
++ * hw_pk11_pub.c for explanation.
++ */
++extern CK_FLAGS pubkey_token_flags;
++
++#ifndef NOPTHREADS
++#define LOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0)
++#define UNLOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0)
++#else
++#define LOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE)
++#define UNLOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE)
++#endif
++
++extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++extern int pk11_token_relogin(CK_SESSION_HANDLE session);
++
++#ifndef OPENSSL_NO_RSA
++extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern RSA_METHOD *PK11_RSA(void);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DSA_METHOD *PK11_DSA(void);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++extern int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DH_METHOD *PK11_DH(void);
++#endif /* OPENSSL_NO_DH */
++
++extern CK_FUNCTION_LIST_PTR pFuncList;
++
++#endif /* HW_PK11_ERR_H */
+Index: openssl/crypto/engine/hw_pk11_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.42
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:27:06 2013
+@@ -0,0 +1,3556 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif /* OPENSSL_NO_DH */
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++#ifndef OPENSSL_NO_RSA
++/* RSA stuff */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_init(RSA *rsa);
++static int pk11_RSA_finish(RSA *rsa);
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#else
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#endif
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++#endif
++
++/* DSA stuff */
++#ifndef OPENSSL_NO_DSA
++static int pk11_DSA_init(DSA *dsa);
++static int pk11_DSA_finish(DSA *dsa);
++static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen,
++ DSA *dsa);
++static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len,
++ DSA_SIG *sig, DSA *dsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session);
++
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa);
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa);
++#endif
++
++/* DH stuff */
++#ifndef OPENSSL_NO_DH
++static int pk11_DH_init(DH *dh);
++static int pk11_DH_finish(DH *dh);
++static int pk11_DH_generate_key(DH *dh);
++static int pk11_DH_compute_key(unsigned char *key,
++ const BIGNUM *pub_key, DH *dh);
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr,
++ BIGNUM **priv_key, CK_SESSION_HANDLE session);
++
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh);
++#endif
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa =
++ {
++ "PKCS#11 RSA method",
++ pk11_RSA_public_encrypt, /* rsa_pub_encrypt */
++ pk11_RSA_public_decrypt, /* rsa_pub_decrypt */
++ pk11_RSA_private_encrypt, /* rsa_priv_encrypt */
++ pk11_RSA_private_decrypt, /* rsa_priv_decrypt */
++ NULL, /* rsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_RSA_init, /* init */
++ pk11_RSA_finish, /* finish */
++ RSA_FLAG_SIGN_VER, /* flags */
++ NULL, /* app_data */
++ pk11_RSA_sign, /* rsa_sign */
++ pk11_RSA_verify /* rsa_verify */
++ };
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ return (&pk11_rsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* Our internal DSA_METHOD that we provide pointers to */
++static DSA_METHOD pk11_dsa =
++ {
++ "PKCS#11 DSA method",
++ pk11_dsa_do_sign, /* dsa_do_sign */
++ NULL, /* dsa_sign_setup */
++ pk11_dsa_do_verify, /* dsa_do_verify */
++ NULL, /* dsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_DSA_init, /* init */
++ pk11_DSA_finish, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++ };
++
++DSA_METHOD *
++PK11_DSA(void)
++ {
++ return (&pk11_dsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DH
++/*
++ * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for
++ * output buffer may somewhat exceed the precise number of bytes needed, but
++ * should not exceed it by a large amount. That may be caused, for example, by
++ * rounding it up to multiple of X in the underlying bignum library. 8 should be
++ * enough.
++ */
++#define DH_BUF_RESERVE 8
++
++/* Our internal DH_METHOD that we provide pointers to */
++static DH_METHOD pk11_dh =
++ {
++ "PKCS#11 DH method",
++ pk11_DH_generate_key, /* generate_key */
++ pk11_DH_compute_key, /* compute_key */
++ NULL, /* bn_mod_exp */
++ pk11_DH_init, /* init */
++ pk11_DH_finish, /* finish */
++ 0, /* flags */
++ NULL, /* app_data */
++ NULL /* generate_params */
++ };
++
++DH_METHOD *
++PK11_DH(void)
++ {
++ return (&pk11_dh);
++ }
++#endif
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++/* Lengths of DSA data and signature */
++#define DSA_DATA_LEN 20
++#define DSA_SIGNATURE_LEN 40
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++#ifndef OPENSSL_NO_RSA
++/*
++ * Similiar to OpenSSL to take advantage of the paddings. The goal is to
++ * support all paddings in this engine although PK11 library does not
++ * support all the paddings used in OpenSSL.
++ * The input errors should have been checked in the padding functions.
++ */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ i = RSA_padding_add_SSLv23(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++
++/*
++ * Similar to Openssl to take advantage of the paddings. The input errors
++ * should be catched in the padding functions
++ */
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ case RSA_SSLV23_PADDING:
++ default:
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int j, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++
++ num = BN_num_bytes(rsa->n);
++
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ /* make data into a big number */
++ if (BN_bin2bn(from, (int)flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's paddings here.
++ */
++ for (j = 0; j < r; j++)
++ if (buf[j] != 0)
++ break;
++
++ p = buf + j;
++ j = r - j; /* j is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ r = RSA_padding_check_SSLv23(to, num, p, j, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, j, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int i, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++ num = BN_num_bytes(rsa->n);
++ buf = (unsigned char *)OPENSSL_malloc(num);
++ if (buf == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ if (BN_bin2bn(from, flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's here
++ */
++ for (i = 0; i < r; i++)
++ if (buf[i] != 0)
++ break;
++
++ p = buf + i;
++ i = r - i; /* i is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, i, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/*
++ * This function implements RSA public encryption using C_EncryptInit and
++ * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_encrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_EncryptInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Encrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_encrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_encrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private encryption using C_SignInit and
++ * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG ul_sig_len = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ {
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW,
++ PK11_R_SIGNINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char *)from, flen, to, &ul_sig_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN,
++ rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ retval = ul_sig_len;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private decryption using C_DecryptInit and
++ * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DecryptInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Decrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA public decryption using C_VerifyRecoverInit
++ * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyRecoverInit(sp->session,
++ p_mech, h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVERINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_VerifyRecover(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVER, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++static int pk11_RSA_init(RSA *rsa)
++ {
++ /*
++ * This flag in the RSA_METHOD enables the new rsa_sign,
++ * rsa_verify functions. See rsa.h for details.
++ */
++ rsa->flags |= RSA_FLAG_SIGN_VER;
++
++ return (1);
++ }
++
++static int pk11_RSA_finish(RSA *rsa)
++ {
++ /*
++ * Since we are overloading OpenSSL's native RSA_eay_finish() we need
++ * to do the same as in the original function, i.e. to free bignum
++ * structures.
++ */
++ if (rsa->_method_mod_n != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_n);
++ if (rsa->_method_mod_p != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_p);
++ if (rsa->_method_mod_q != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_q);
++
++ return (1);
++ }
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#else
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#endif
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto err;
++ }
++ rv = pFuncList->C_Verify(sp->session, s, i,
++ (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* The DSA function implementation */
++/* ARGSUSED */
++static int pk11_DSA_init(DSA *dsa)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DSA_finish(DSA *dsa)
++ {
++ return (1);
++ }
++
++
++static DSA_SIG *
++pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
++ {
++ BIGNUM *r = NULL, *s = NULL;
++ int i;
++ DSA_SIG *dsa_sig = NULL;
++
++ CK_RV rv;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_priv_key;
++
++ /*
++ * The signature is the concatenation of r and s,
++ * each is 20 bytes long
++ */
++ unsigned char sigret[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned int siglen2 = DSA_SIGNATURE_LEN / 2;
++
++ PK11_SESSION *sp = NULL;
++
++ if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_priv(sp, dsa);
++
++ h_priv_key = sp->opdata_dsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_dsa_priv_key =
++ pk11_get_private_dsa_key((DSA *)dsa,
++ &sp->opdata_dsa_priv,
++ &sp->opdata_dsa_priv_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto ret;
++ }
++
++ (void) memset(sigret, 0, siglen);
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char*) dgst, dlen, sigret,
++ (CK_ULONG_PTR) &siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv);
++ goto ret;
++ }
++ }
++
++
++ if ((s = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((r = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((dsa_sig = DSA_SIG_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if (BN_bin2bn(sigret, siglen2, r) == NULL ||
++ BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ dsa_sig->r = r;
++ dsa_sig->s = s;
++
++ret:
++ if (dsa_sig == NULL)
++ {
++ if (r != NULL)
++ BN_free(r);
++ if (s != NULL)
++ BN_free(s);
++ }
++
++ pk11_return_session(sp, OP_DSA);
++ return (dsa_sig);
++ }
++
++static int
++pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig,
++ DSA *dsa)
++ {
++ int i;
++ CK_RV rv;
++ int retval = 0;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_pub_key;
++
++ unsigned char sigbuf[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned long siglen2 = DSA_SIGNATURE_LEN/2;
++
++ PK11_SESSION *sp = NULL;
++
++ if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_R);
++ goto ret;
++ }
++
++ if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_S);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_pub(sp, dsa);
++
++ h_pub_key = sp->opdata_dsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_dsa_pub_key =
++ pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub,
++ &sp->opdata_dsa_pub_num, sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto ret;
++ }
++
++ /*
++ * The representation of each of the two big numbers could
++ * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need
++ * to act accordingly and shift if necessary.
++ */
++ (void) memset(sigbuf, 0, siglen);
++ BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r));
++ BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 -
++ BN_num_bytes(sig->s));
++
++ rv = pFuncList->C_Verify(sp->session,
++ (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv);
++ goto ret;
++ }
++ }
++
++ retval = 1;
++ret:
++
++ pk11_return_session(sp, OP_DSA);
++ return (retval);
++ }
++
++
++/*
++ * Create a public key object in a session from a given dsa structure.
++ * The *dsa_pub_num pointer is non-NULL for DSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ if (init_template_value(dsa->p, &a_key_template[4].pValue,
++ &a_key_template[4].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->pub_key, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_pub_num != NULL)
++ if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ for (i = 4; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given dsa structure
++ * The *dsa_priv_num pointer is non-NULL for DSA private keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ int i;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 9;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(dsa->p, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(dsa->priv_key, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_priv_num != NULL)
++ if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ /*
++ * 5 to 8 entries in the key template are key components.
++ * They need to be freed apon exit or error.
++ */
++ for (i = 5; i <= 8; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only public key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_pub != dsa) ||
++ (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only private key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_priv != dsa) ||
++ (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++
++#ifndef OPENSSL_NO_DH
++/* The DH function implementation */
++/* ARGSUSED */
++static int pk11_DH_init(DH *dh)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DH_finish(DH *dh)
++ {
++ return (1);
++ }
++
++/*
++ * Generate DH key-pair.
++ *
++ * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key
++ * and override it even if it is set. OpenSSL does not touch dh->priv_key
++ * if set and just computes dh->pub_key. It looks like PKCS#11 standard
++ * is not capable of providing this functionality. This could be a problem
++ * for applications relying on OpenSSL's semantics.
++ */
++static int pk11_DH_generate_key(DH *dh)
++ {
++ CK_ULONG i;
++ CK_RV rv, rv1;
++ int reuse_mem_len = 0, ret = 0;
++ PK11_SESSION *sp = NULL;
++ CK_BYTE_PTR reuse_mem;
++
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++
++ CK_ULONG ul_pub_key_attr_count = 3;
++ CK_ATTRIBUTE pub_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *)NULL, 0},
++ {CKA_BASE, (void *)NULL, 0}
++ };
++
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)}
++ };
++
++ CK_ULONG pub_key_attr_result_count = 1;
++ CK_ATTRIBUTE pub_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ pub_key_template[1].ulValueLen = BN_num_bytes(dh->p);
++ if (pub_key_template[1].ulValueLen > 0)
++ {
++ /*
++ * We must not increase ulValueLen by DH_BUF_RESERVE since that
++ * could cause the same rounding problem. See definition of
++ * DH_BUF_RESERVE above.
++ */
++ pub_key_template[1].pValue =
++ OPENSSL_malloc(pub_key_template[1].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[1].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->p, pub_key_template[1].pValue);
++ }
++ else
++ goto err;
++
++ pub_key_template[2].ulValueLen = BN_num_bytes(dh->g);
++ if (pub_key_template[2].ulValueLen > 0)
++ {
++ pub_key_template[2].pValue =
++ OPENSSL_malloc(pub_key_template[2].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[2].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->g, pub_key_template[2].pValue);
++ }
++ else
++ goto err;
++
++ /*
++ * Note: we are only using PK11_SESSION structure for getting
++ * a session handle. The objects created in this function are
++ * destroyed before return and thus not cached.
++ */
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ rv = pFuncList->C_GenerateKeyPair(sp->session,
++ &mechanism,
++ pub_key_template,
++ ul_pub_key_attr_count,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_pub_key,
++ &h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv);
++ goto err;
++ }
++
++ /*
++ * Reuse the larger memory allocated. We know the larger memory
++ * should be sufficient for reuse.
++ */
++ if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen)
++ {
++ reuse_mem = pub_key_template[1].pValue;
++ reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE;
++ }
++ else
++ {
++ reuse_mem = pub_key_template[2].pValue;
++ reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++ rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK || rv1 != CKR_OK)
++ {
++ rv = (rv != CKR_OK) ? rv : rv1;
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 ||
++ ((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++
++ /* Reuse the memory allocated */
++ pub_key_result[0].pValue = reuse_mem;
++ pub_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (pub_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->pub_key == NULL)
++ if ((dh->pub_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->pub_key = BN_bin2bn(pub_key_result[0].pValue,
++ pub_key_result[0].ulValueLen, dh->pub_key);
++ if (dh->pub_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ /* Reuse the memory allocated */
++ priv_key_result[0].pValue = reuse_mem;
++ priv_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->priv_key == NULL)
++ if ((dh->priv_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->priv_key = BN_bin2bn(priv_key_result[0].pValue,
++ priv_key_result[0].ulValueLen, dh->priv_key);
++ if (dh->priv_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ ret = 1;
++
++err:
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_pub_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ for (i = 1; i <= 2; i++)
++ {
++ if (pub_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(pub_key_template[i].pValue);
++ pub_key_template[i].pValue = NULL;
++ }
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key,
++ DH *dh)
++ {
++ unsigned int i;
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0};
++ CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
++ CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
++ CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++
++ CK_ULONG seclen;
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (key_class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_VALUE_LEN, &seclen, sizeof (seclen)},
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_RV rv;
++ int ret = -1;
++ PK11_SESSION *sp = NULL;
++
++ if (dh->priv_key == NULL)
++ goto err;
++
++ priv_key_template[0].pValue = &key_class;
++ priv_key_template[1].pValue = &key_type;
++ seclen = BN_num_bytes(dh->p);
++
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ mechanism.ulParameterLen = BN_num_bytes(pub_key);
++ mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen);
++ if (mechanism.pParameter == NULL)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ BN_bn2bin(pub_key, mechanism.pParameter);
++
++ (void) check_new_dh_key(sp, dh);
++
++ h_key = sp->opdata_dh_key;
++ if (h_key == CK_INVALID_HANDLE)
++ h_key = sp->opdata_dh_key =
++ pk11_get_dh_key((DH*) dh, &sp->opdata_dh,
++ &sp->opdata_dh_priv_num, sp->session);
++
++ if (h_key == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT);
++ goto err;
++ }
++
++ rv = pFuncList->C_DeriveKey(sp->session,
++ &mechanism,
++ h_key,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++ priv_key_result[0].pValue =
++ OPENSSL_malloc(priv_key_result[0].ulValueLen);
++ if (!priv_key_result[0].pValue)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ /*
++ * OpenSSL allocates the output buffer 'key' which is the same
++ * length of the public key. It is long enough for the derived key
++ */
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ /*
++ * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip
++ * leading zeros from a computed shared secret. However,
++ * OpenSSL always did it so we must do the same here. The
++ * vagueness of the spec regarding leading zero bytes was
++ * finally cleared with TLS 1.1 (RFC 4346) saying that leading
++ * zeros are stripped before the computed data is used as the
++ * pre-master secret.
++ */
++ for (i = 0; i < priv_key_result[0].ulValueLen; ++i)
++ {
++ if (((char *)priv_key_result[0].pValue)[i] != 0)
++ break;
++ }
++
++ (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i,
++ priv_key_result[0].ulValueLen - i);
++ ret = priv_key_result[0].ulValueLen - i;
++ }
++
++err:
++
++ if (h_derived_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++ if (priv_key_result[0].pValue)
++ {
++ OPENSSL_free(priv_key_result[0].pValue);
++ priv_key_result[0].pValue = NULL;
++ }
++
++ if (mechanism.pParameter)
++ {
++ OPENSSL_free(mechanism.pParameter);
++ mechanism.pParameter = NULL;
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh,
++ DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE key_type = CKK_DH;
++ CK_ULONG found;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ULONG ul_key_attr_count = 7;
++ CK_ATTRIBUTE key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)},
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *) NULL, 0},
++ {CKA_BASE, (void *) NULL, 0},
++ {CKA_VALUE, (void *) NULL, 0},
++ };
++
++ key_template[0].pValue = &class;
++ key_template[1].pValue = &key_type;
++
++ key_template[4].ulValueLen = BN_num_bytes(dh->p);
++ key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[4].ulValueLen);
++ if (key_template[4].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->p, key_template[4].pValue);
++
++ key_template[5].ulValueLen = BN_num_bytes(dh->g);
++ key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[5].ulValueLen);
++ if (key_template[5].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->g, key_template[5].pValue);
++
++ key_template[6].ulValueLen = BN_num_bytes(dh->priv_key);
++ key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[6].ulValueLen);
++ if (key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->priv_key, key_template[6].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DH);
++ rv = pFuncList->C_FindObjectsInit(session, key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL,
++ rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++ }
++
++ if (dh_priv_num != NULL)
++ if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dh;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DH);
++
++malloc_err:
++ for (i = 4; i <= 6; i++)
++ {
++ if (key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(key_template[i].pValue);
++ key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ *
++ * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh
++ * to CK_INVALID_HANDLE even when it fails to destroy the object.
++ */
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh)
++ {
++ /*
++ * Provide protection against DH structure reuse by making the
++ * check for cache hit stronger. Private key component of DH key
++ * is unique so it is sufficient to compare it with value cached
++ * in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dh != dh) ||
++ (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dh_object(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11ca.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.4
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:20 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */
++
++#define token_lock pk11ca_token_lock
++#define find_lock pk11ca_find_lock
++#define active_list pk11ca_active_list
++#define pubkey_token_flags pk11ca_pubkey_token_flags
++#define pubkey_SLOTID pk11ca_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11ca_error
++#define PK11err_add_data PK11CAerr_add_data
++#define pk11_get_session pk11ca_get_session
++#define pk11_return_session pk11ca_return_session
++#define pk11_active_add pk11ca_active_add
++#define pk11_active_delete pk11ca_active_delete
++#define pk11_active_remove pk11ca_active_remove
++#define pk11_free_active_list pk11ca_free_active_list
++#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv
++#define pk11_load_privkey pk11ca_load_privkey
++#define pk11_load_pubkey pk11ca_load_pubkey
++#define PK11_RSA PK11CA_RSA
++#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv
++#define PK11_DSA PK11CA_DSA
++#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11ca_destroy_dh_object
++#define PK11_DH PK11CA_DH
++#define pk11_token_relogin pk11ca_token_relogin
++#define pFuncList pk11ca_pFuncList
++#define pk11_pin pk11ca_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11ca
+Index: openssl/crypto/engine/hw_pk11so.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.8
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:05:16 2013
+@@ -0,0 +1,1775 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/*#undef DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_DSA
++#define OPENSSL_NO_DSA
++#endif
++#ifndef OPENSSL_NO_DH
++#define OPENSSL_NO_DH
++#endif
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.c"
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++static int pk11_choose_slots(int *any_slot_found);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11CA
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name = "PKCS #11 engine support (sign only)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name))
++ return (0);
++
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++ (void) pk11_destroy_rsa_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ if (optype == OP_RSA)
++ {
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_PKCS
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ CK_SLOT_ID current_slot = 0;
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * Check if this slot is capable of signing with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN)))
++ {
++ slot_has_rsa = CK_TRUE;
++ }
++
++ if (!found_candidate_slot && slot_has_rsa)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ /*SLOTID = pSlotList[0];*/
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11so.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.4
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:20 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */
++
++#define token_lock pk11so_token_lock
++#define find_lock pk11so_find_lock
++#define active_list pk11so_active_list
++#define pubkey_token_flags pk11so_pubkey_token_flags
++#define pubkey_SLOTID pk11so_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11so_error
++#define PK11err_add_data PK11SOerr_add_data
++#define pk11_get_session pk11so_get_session
++#define pk11_return_session pk11so_return_session
++#define pk11_active_add pk11so_active_add
++#define pk11_active_delete pk11so_active_delete
++#define pk11_active_remove pk11so_active_remove
++#define pk11_free_active_list pk11so_free_active_list
++#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv
++#define pk11_load_privkey pk11so_load_privkey
++#define pk11_load_pubkey pk11so_load_pubkey
++#define PK11_RSA PK11SO_RSA
++#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv
++#define PK11_DSA PK11SO_DSA
++#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11so_destroy_dh_object
++#define PK11_DH PK11SO_DH
++#define pk11_token_relogin pk11so_token_relogin
++#define pFuncList pk11so_pFuncList
++#define pk11_pin pk11so_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11so
+Index: openssl/crypto/engine/hw_pk11so_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.10
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:05:38 2013
+@@ -0,0 +1,1642 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++/* RSA stuff */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa;
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ const RSA_METHOD *rsa;
++
++ if (pk11_rsa.name == NULL)
++ {
++ rsa = RSA_PKCS1_SSLeay();
++ memcpy(&pk11_rsa, rsa, sizeof(*rsa));
++ pk11_rsa.name = "PKCS#11 RSA method";
++ pk11_rsa.rsa_sign = pk11_RSA_sign;
++ }
++ return (&pk11_rsa);
++ }
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/pkcs11.h
+diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,299 @@
++/* pkcs11.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++#ifndef _PKCS11_H_
++#define _PKCS11_H_ 1
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Before including this file (pkcs11.h) (or pkcs11t.h by
++ * itself), 6 platform-specific macros must be defined. These
++ * macros are described below, and typical definitions for them
++ * are also given. Be advised that these definitions can depend
++ * on both the platform and the compiler used (and possibly also
++ * on whether a Cryptoki library is linked statically or
++ * dynamically).
++ *
++ * In addition to defining these 6 macros, the packing convention
++ * for Cryptoki structures should be set. The Cryptoki
++ * convention on packing is that structures should be 1-byte
++ * aligned.
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, this might be done by using the following
++ * preprocessor directive before including pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(push, cryptoki, 1)
++ *
++ * and using the following preprocessor directive after including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(pop, cryptoki)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, this might be done by using
++ * the following preprocessor directive before including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(1)
++ *
++ * In a UNIX environment, you're on your own for this. You might
++ * not need to do (or be able to do!) anything.
++ *
++ *
++ * Now for the macros:
++ *
++ *
++ * 1. CK_PTR: The indirection string for making a pointer to an
++ * object. It can be used like this:
++ *
++ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, it might be defined by:
++ *
++ * #define CK_PTR far *
++ *
++ * In a typical UNIX environment, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ *
++ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
++ * an exportable Cryptoki library function definition out of a
++ * return type and a function name. It should be used in the
++ * following fashion to define the exposed Cryptoki functions in
++ * a Cryptoki library:
++ *
++ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * )
++ * {
++ * ...
++ * }
++ *
++ * If you're using Microsoft Developer Studio 5.0 to define a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllexport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to define a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
++ * an importable Cryptoki library function declaration out of a
++ * return type and a function name. It should be used in the
++ * following fashion:
++ *
++ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * );
++ *
++ * If you're using Microsoft Developer Studio 5.0 to declare a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllimport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to declare a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
++ * which makes a Cryptoki API function pointer declaration or
++ * function pointer type declaration out of a return type and a
++ * function name. It should be used in the following fashion:
++ *
++ * // Define funcPtr to be a pointer to a Cryptoki API function
++ * // taking arguments args and returning CK_RV.
++ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
++ *
++ * or
++ *
++ * // Define funcPtrType to be the type of a pointer to a
++ * // Cryptoki API function taking arguments args and returning
++ * // CK_RV, and then define funcPtr to be a variable of type
++ * // funcPtrType.
++ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
++ * funcPtrType funcPtr;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to access
++ * functions in a Win32 Cryptoki .dll, in might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __declspec(dllimport) (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to access functions in a Win16 Cryptoki .dll, it might
++ * be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __export _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
++ * a function pointer type for an application callback out of
++ * a return type for the callback and a name for the callback.
++ * It should be used in the following fashion:
++ *
++ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
++ *
++ * to declare a function pointer, myCallback, to a callback
++ * which takes arguments args and returns a CK_RV. It can also
++ * be used like this:
++ *
++ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
++ * myCallbackType myCallback;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to do Win32
++ * Cryptoki development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to do Win16 development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 6. NULL_PTR: This macro is the value of a NULL pointer.
++ *
++ * In any ANSI/ISO C environment (and in many others as well),
++ * this should best be defined by
++ *
++ * #ifndef NULL_PTR
++ * #define NULL_PTR 0
++ * #endif
++ */
++
++
++/* All the various Cryptoki types and #define'd values are in the
++ * file pkcs11t.h. */
++#include "pkcs11t.h"
++
++#define __PASTE(x,y) x##y
++
++
++/* ==============================================================
++ * Define the "extern" form of all the entry points.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ extern CK_DECLARE_FUNCTION(CK_RV, name)
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define the typedef form of all the entry points. That is, for
++ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
++ * a pointer to that kind of function.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define structed vector of entry points. A CK_FUNCTION_LIST
++ * contains a CK_VERSION indicating a library's Cryptoki version
++ * and then a whole slew of function pointers to the routines in
++ * the library. This type was declared, but not defined, in
++ * pkcs11t.h.
++ * ==============================================================
++ */
++
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ __PASTE(CK_,name) name;
++
++struct CK_FUNCTION_LIST {
++
++ CK_VERSION version; /* Cryptoki version */
++
++/* Pile all the function pointers into the CK_FUNCTION_LIST. */
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++};
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++#undef __PASTE
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+Index: openssl/crypto/engine/pkcs11f.h
+diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,912 @@
++/* pkcs11f.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This header file contains pretty much everything about all the */
++/* Cryptoki function prototypes. Because this information is */
++/* used for more than just declaring function prototypes, the */
++/* order of the functions appearing herein is important, and */
++/* should not be altered. */
++
++/* General-purpose */
++
++/* C_Initialize initializes the Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Initialize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
++ * cast to CK_C_INITIALIZE_ARGS_PTR
++ * and dereferenced */
++);
++#endif
++
++
++/* C_Finalize indicates that an application is done with the
++ * Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Finalize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
++);
++#endif
++
++
++/* C_GetInfo returns general information about Cryptoki. */
++CK_PKCS11_FUNCTION_INFO(C_GetInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_INFO_PTR pInfo /* location that receives information */
++);
++#endif
++
++
++/* C_GetFunctionList returns the function list. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
++ * function list */
++);
++#endif
++
++
++
++/* Slot and token management */
++
++/* C_GetSlotList obtains a list of slots in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_BBOOL tokenPresent, /* only slots with tokens? */
++ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
++ CK_ULONG_PTR pulCount /* receives number of slots */
++);
++#endif
++
++
++/* C_GetSlotInfo obtains information about a particular slot in
++ * the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the ID of the slot */
++ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
++);
++#endif
++
++
++/* C_GetTokenInfo obtains information about a particular token
++ * in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
++);
++#endif
++
++
++/* C_GetMechanismList obtains a list of mechanism types
++ * supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of token's slot */
++ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
++ CK_ULONG_PTR pulCount /* gets # of mechs. */
++);
++#endif
++
++
++/* C_GetMechanismInfo obtains information about a particular
++ * mechanism possibly supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_MECHANISM_TYPE type, /* type of mechanism */
++ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
++);
++#endif
++
++
++/* C_InitToken initializes a token. */
++CK_PKCS11_FUNCTION_INFO(C_InitToken)
++#ifdef CK_NEED_ARG_LIST
++/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
++ CK_ULONG ulPinLen, /* length in bytes of the PIN */
++ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
++);
++#endif
++
++
++/* C_InitPIN initializes the normal user's PIN. */
++CK_PKCS11_FUNCTION_INFO(C_InitPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
++ CK_ULONG ulPinLen /* length in bytes of the PIN */
++);
++#endif
++
++
++/* C_SetPIN modifies the PIN of the user who is logged in. */
++CK_PKCS11_FUNCTION_INFO(C_SetPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
++ CK_ULONG ulOldLen, /* length of the old PIN */
++ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
++ CK_ULONG ulNewLen /* length of the new PIN */
++);
++#endif
++
++
++
++/* Session management */
++
++/* C_OpenSession opens a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_OpenSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the slot's ID */
++ CK_FLAGS flags, /* from CK_SESSION_INFO */
++ CK_VOID_PTR pApplication, /* passed to callback */
++ CK_NOTIFY Notify, /* callback function */
++ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
++);
++#endif
++
++
++/* C_CloseSession closes a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CloseAllSessions closes all sessions with a token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID /* the token's slot */
++);
++#endif
++
++
++/* C_GetSessionInfo obtains information about the session. */
++CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_SESSION_INFO_PTR pInfo /* receives session info */
++);
++#endif
++
++
++/* C_GetOperationState obtains the state of the cryptographic operation
++ * in a session. */
++CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* gets state */
++ CK_ULONG_PTR pulOperationStateLen /* gets state length */
++);
++#endif
++
++
++/* C_SetOperationState restores the state of the cryptographic
++ * operation in a session. */
++CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* holds state */
++ CK_ULONG ulOperationStateLen, /* holds state length */
++ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
++ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
++);
++#endif
++
++
++/* C_Login logs a user into a token. */
++CK_PKCS11_FUNCTION_INFO(C_Login)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_USER_TYPE userType, /* the user type */
++ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
++ CK_ULONG ulPinLen /* the length of the PIN */
++);
++#endif
++
++
++/* C_Logout logs a user out from a token. */
++CK_PKCS11_FUNCTION_INFO(C_Logout)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Object management */
++
++/* C_CreateObject creates a new object. */
++CK_PKCS11_FUNCTION_INFO(C_CreateObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
++);
++#endif
++
++
++/* C_CopyObject copies an object, creating a new object for the
++ * copy. */
++CK_PKCS11_FUNCTION_INFO(C_CopyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
++);
++#endif
++
++
++/* C_DestroyObject destroys an object. */
++CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject /* the object's handle */
++);
++#endif
++
++
++/* C_GetObjectSize gets the size of an object in bytes. */
++CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ULONG_PTR pulSize /* receives size of object */
++);
++#endif
++
++
++/* C_GetAttributeValue obtains the value of one or more object
++ * attributes. */
++CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_SetAttributeValue modifies the value of one or more object
++ * attributes */
++CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_FindObjectsInit initializes a search for token and session
++ * objects that match a template. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
++ CK_ULONG ulCount /* attrs in search template */
++);
++#endif
++
++
++/* C_FindObjects continues a search for token and session
++ * objects that match a template, obtaining additional object
++ * handles. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjects)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
++ CK_ULONG ulMaxObjectCount, /* max handles to get */
++ CK_ULONG_PTR pulObjectCount /* actual # returned */
++);
++#endif
++
++
++/* C_FindObjectsFinal finishes a search for token and session
++ * objects. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Encryption and decryption */
++
++/* C_EncryptInit initializes an encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of encryption key */
++);
++#endif
++
++
++/* C_Encrypt encrypts single-part data. */
++CK_PKCS11_FUNCTION_INFO(C_Encrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pData, /* the plaintext data */
++ CK_ULONG ulDataLen, /* bytes of plaintext */
++ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptUpdate continues a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext data len */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptFinal finishes a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session handle */
++ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
++ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
++);
++#endif
++
++
++/* C_DecryptInit initializes a decryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of decryption key */
++);
++#endif
++
++
++/* C_Decrypt decrypts encrypted data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Decrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedData, /* ciphertext */
++ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
++ CK_BYTE_PTR pData, /* gets plaintext */
++ CK_ULONG_PTR pulDataLen /* gets p-text size */
++);
++#endif
++
++
++/* C_DecryptUpdate continues a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
++ CK_ULONG ulEncryptedPartLen, /* input length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* p-text size */
++);
++#endif
++
++
++/* C_DecryptFinal finishes a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pLastPart, /* gets plaintext */
++ CK_ULONG_PTR pulLastPartLen /* p-text size */
++);
++#endif
++
++
++
++/* Message digesting */
++
++/* C_DigestInit initializes a message-digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
++);
++#endif
++
++
++/* C_Digest digests data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Digest)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* data to be digested */
++ CK_ULONG ulDataLen, /* bytes of data to digest */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets digest length */
++);
++#endif
++
++
++/* C_DigestUpdate continues a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* data to be digested */
++ CK_ULONG ulPartLen /* bytes of data to be digested */
++);
++#endif
++
++
++/* C_DigestKey continues a multi-part message-digesting
++ * operation, by digesting the value of a secret key as part of
++ * the data already digested. */
++CK_PKCS11_FUNCTION_INFO(C_DigestKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hKey /* secret key to digest */
++);
++#endif
++
++
++/* C_DigestFinal finishes a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
++);
++#endif
++
++
++
++/* Signing and MACing */
++
++/* C_SignInit initializes a signature (private key encryption)
++ * operation, where the signature is (will be) an appendix to
++ * the data, and plaintext cannot be recovered from the
++ *signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of signature key */
++);
++#endif
++
++
++/* C_Sign signs (encrypts with private key) data in a single
++ * part, where the signature is (will be) an appendix to the
++ * data, and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Sign)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignUpdate continues a multiple-part signature operation,
++ * where the signature is (will be) an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* the data to sign */
++ CK_ULONG ulPartLen /* count of bytes to sign */
++);
++#endif
++
++
++/* C_SignFinal finishes a multiple-part signature operation,
++ * returning the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignRecoverInit initializes a signature operation, where
++ * the data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of the signature key */
++);
++#endif
++
++
++/* C_SignRecover signs data in a single operation, where the
++ * data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++
++/* Verifying signatures and MACs */
++
++/* C_VerifyInit initializes a verification operation, where the
++ * signature is an appendix to the data, and plaintext cannot
++ * cannot be recovered from the signature (e.g. DSA). */
++CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_Verify verifies a signature in a single-part operation,
++ * where the signature is an appendix to the data, and plaintext
++ * cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Verify)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* signed data */
++ CK_ULONG ulDataLen, /* length of signed data */
++ CK_BYTE_PTR pSignature, /* signature */
++ CK_ULONG ulSignatureLen /* signature length*/
++);
++#endif
++
++
++/* C_VerifyUpdate continues a multiple-part verification
++ * operation, where the signature is an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* signed data */
++ CK_ULONG ulPartLen /* length of signed data */
++);
++#endif
++
++
++/* C_VerifyFinal finishes a multiple-part verification
++ * operation, checking the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen /* signature length */
++);
++#endif
++
++
++/* C_VerifyRecoverInit initializes a signature verification
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_VerifyRecover verifies a signature in a single-part
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen, /* signature length */
++ CK_BYTE_PTR pData, /* gets signed data */
++ CK_ULONG_PTR pulDataLen /* gets signed data len */
++);
++#endif
++
++
++
++/* Dual-function cryptographic operations */
++
++/* C_DigestEncryptUpdate continues a multiple-part digesting
++ * and encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptDigestUpdate continues a multiple-part decryption and
++ * digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets plaintext len */
++);
++#endif
++
++
++/* C_SignEncryptUpdate continues a multiple-part signing and
++ * encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptVerifyUpdate continues a multiple-part decryption and
++ * verify operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets p-text length */
++);
++#endif
++
++
++
++/* Key management */
++
++/* C_GenerateKey generates a secret key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
++ CK_ULONG ulCount, /* # of attrs in template */
++ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
++);
++#endif
++
++
++/* C_GenerateKeyPair generates a public-key/private-key pair,
++ * creating new key objects. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session
++ * handle */
++ CK_MECHANISM_PTR pMechanism, /* key-gen
++ * mech. */
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
++ * for pub.
++ * key */
++ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
++ * attrs. */
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
++ * for priv.
++ * key */
++ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
++ * attrs. */
++ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
++ * key
++ * handle */
++ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
++ * priv. key
++ * handle */
++);
++#endif
++
++
++/* C_WrapKey wraps (i.e., encrypts) a key. */
++CK_PKCS11_FUNCTION_INFO(C_WrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
++ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
++ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
++ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
++ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
++);
++#endif
++
++
++/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
++ * key object. */
++CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
++ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
++ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
++ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++/* C_DeriveKey derives a key from a base key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
++ CK_OBJECT_HANDLE hBaseKey, /* base key */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++
++/* Random number generation */
++
++/* C_SeedRandom mixes additional seed material into the token's
++ * random number generator. */
++CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSeed, /* the seed material */
++ CK_ULONG ulSeedLen /* length of seed material */
++);
++#endif
++
++
++/* C_GenerateRandom generates random data. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR RandomData, /* receives the random data */
++ CK_ULONG ulRandomLen /* # of bytes to generate */
++);
++#endif
++
++
++
++/* Parallel function management */
++
++/* C_GetFunctionStatus is a legacy function; it obtains an
++ * updated status of a function running in parallel with an
++ * application. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CancelFunction is a legacy function; it cancels a function
++ * running in parallel. */
++CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Functions added in for Cryptoki Version 2.01 or later */
++
++/* C_WaitForSlotEvent waits for a slot event (token insertion,
++ * removal, etc.) to occur. */
++CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FLAGS flags, /* blocking/nonblocking flag */
++ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
++ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
++);
++#endif
+Index: openssl/crypto/engine/pkcs11t.h
+diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2
+--- /dev/null Mon Jun 13 15:26:30 2016
++++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008
+@@ -0,0 +1,1885 @@
++/* pkcs11t.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* See top of pkcs11.h for information about the macros that
++ * must be defined and the structure-packing conventions that
++ * must be set before including this file. */
++
++#ifndef _PKCS11T_H_
++#define _PKCS11T_H_ 1
++
++#define CRYPTOKI_VERSION_MAJOR 2
++#define CRYPTOKI_VERSION_MINOR 20
++#define CRYPTOKI_VERSION_AMENDMENT 3
++
++#define CK_TRUE 1
++#define CK_FALSE 0
++
++#ifndef CK_DISABLE_TRUE_FALSE
++#ifndef FALSE
++#define FALSE CK_FALSE
++#endif
++
++#ifndef TRUE
++#define TRUE CK_TRUE
++#endif
++#endif
++
++/* an unsigned 8-bit value */
++typedef unsigned char CK_BYTE;
++
++/* an unsigned 8-bit character */
++typedef CK_BYTE CK_CHAR;
++
++/* an 8-bit UTF-8 character */
++typedef CK_BYTE CK_UTF8CHAR;
++
++/* a BYTE-sized Boolean flag */
++typedef CK_BYTE CK_BBOOL;
++
++/* an unsigned value, at least 32 bits long */
++typedef unsigned long int CK_ULONG;
++
++/* a signed value, the same size as a CK_ULONG */
++/* CK_LONG is new for v2.0 */
++typedef long int CK_LONG;
++
++/* at least 32 bits; each bit is a Boolean flag */
++typedef CK_ULONG CK_FLAGS;
++
++
++/* some special values for certain CK_ULONG variables */
++#define CK_UNAVAILABLE_INFORMATION (~0UL)
++#define CK_EFFECTIVELY_INFINITE 0
++
++
++typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++typedef CK_CHAR CK_PTR CK_CHAR_PTR;
++typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
++typedef CK_ULONG CK_PTR CK_ULONG_PTR;
++typedef void CK_PTR CK_VOID_PTR;
++
++/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
++typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
++
++
++/* The following value is always invalid if used as a session */
++/* handle or object handle */
++#define CK_INVALID_HANDLE 0
++
++
++typedef struct CK_VERSION {
++ CK_BYTE major; /* integer portion of version number */
++ CK_BYTE minor; /* 1/100ths portion of version number */
++} CK_VERSION;
++
++typedef CK_VERSION CK_PTR CK_VERSION_PTR;
++
++
++typedef struct CK_INFO {
++ /* manufacturerID and libraryDecription have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags; /* must be zero */
++
++ /* libraryDescription and libraryVersion are new for v2.0 */
++ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
++ CK_VERSION libraryVersion; /* version of library */
++} CK_INFO;
++
++typedef CK_INFO CK_PTR CK_INFO_PTR;
++
++
++/* CK_NOTIFICATION enumerates the types of notifications that
++ * Cryptoki provides to an application */
++/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_NOTIFICATION;
++#define CKN_SURRENDER 0
++
++/* The following notification is new for PKCS #11 v2.20 amendment 3 */
++#define CKN_OTP_CHANGED 1
++
++
++typedef CK_ULONG CK_SLOT_ID;
++
++typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
++
++
++/* CK_SLOT_INFO provides information about a slot */
++typedef struct CK_SLOT_INFO {
++ /* slotDescription and manufacturerID have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR slotDescription[64]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags;
++
++ /* hardwareVersion and firmwareVersion are new for v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++} CK_SLOT_INFO;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
++#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
++#define CKF_HW_SLOT 0x00000004 /* hardware slot */
++
++typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
++
++
++/* CK_TOKEN_INFO provides information about a token */
++typedef struct CK_TOKEN_INFO {
++ /* label, manufacturerID, and model have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR label[32]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_UTF8CHAR model[16]; /* blank padded */
++ CK_CHAR serialNumber[16]; /* blank padded */
++ CK_FLAGS flags; /* see below */
++
++ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
++ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
++ * changed from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulMaxSessionCount; /* max open sessions */
++ CK_ULONG ulSessionCount; /* sess. now open */
++ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
++ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
++ CK_ULONG ulMaxPinLen; /* in bytes */
++ CK_ULONG ulMinPinLen; /* in bytes */
++ CK_ULONG ulTotalPublicMemory; /* in bytes */
++ CK_ULONG ulFreePublicMemory; /* in bytes */
++ CK_ULONG ulTotalPrivateMemory; /* in bytes */
++ CK_ULONG ulFreePrivateMemory; /* in bytes */
++
++ /* hardwareVersion, firmwareVersion, and time are new for
++ * v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++ CK_CHAR utcTime[16]; /* time */
++} CK_TOKEN_INFO;
++
++/* The flags parameter is defined as follows:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RNG 0x00000001 /* has random #
++ * generator */
++#define CKF_WRITE_PROTECTED 0x00000002 /* token is
++ * write-
++ * protected */
++#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
++ * login */
++#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
++ * PIN is set */
++
++/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
++ * that means that *every* time the state of cryptographic
++ * operations of a session is successfully saved, all keys
++ * needed to continue those operations are stored in the state */
++#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
++
++/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
++ * that the token has some sort of clock. The time on that
++ * clock is returned in the token info structure */
++#define CKF_CLOCK_ON_TOKEN 0x00000040
++
++/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
++ * set, that means that there is some way for the user to login
++ * without sending a PIN through the Cryptoki library itself */
++#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
++
++/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
++ * that means that a single session with the token can perform
++ * dual simultaneous cryptographic operations (digest and
++ * encrypt; decrypt and digest; sign and encrypt; and decrypt
++ * and sign) */
++#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
++
++/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
++ * token has been initialized using C_InitializeToken or an
++ * equivalent mechanism outside the scope of PKCS #11.
++ * Calling C_InitializeToken when this flag is set will cause
++ * the token to be reinitialized. */
++#define CKF_TOKEN_INITIALIZED 0x00000400
++
++/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
++ * true, the token supports secondary authentication for
++ * private key objects. This flag is deprecated in v2.11 and
++ onwards. */
++#define CKF_SECONDARY_AUTHENTICATION 0x00000800
++
++/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect user login PIN has been entered at least once
++ * since the last successful authentication. */
++#define CKF_USER_PIN_COUNT_LOW 0x00010000
++
++/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect user PIN will it to become locked. */
++#define CKF_USER_PIN_FINAL_TRY 0x00020000
++
++/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
++ * user PIN has been locked. User login to the token is not
++ * possible. */
++#define CKF_USER_PIN_LOCKED 0x00040000
++
++/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the user PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
++
++/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect SO login PIN has been entered at least once since
++ * the last successful authentication. */
++#define CKF_SO_PIN_COUNT_LOW 0x00100000
++
++/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect SO PIN will it to become locked. */
++#define CKF_SO_PIN_FINAL_TRY 0x00200000
++
++/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
++ * PIN has been locked. SO login to the token is not possible.
++ */
++#define CKF_SO_PIN_LOCKED 0x00400000
++
++/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the SO PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
++
++typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
++
++
++/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
++ * identifies a session */
++typedef CK_ULONG CK_SESSION_HANDLE;
++
++typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
++
++
++/* CK_USER_TYPE enumerates the types of Cryptoki users */
++/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_USER_TYPE;
++/* Security Officer */
++#define CKU_SO 0
++/* Normal user */
++#define CKU_USER 1
++/* Context specific (added in v2.20) */
++#define CKU_CONTEXT_SPECIFIC 2
++
++/* CK_STATE enumerates the session states */
++/* CK_STATE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_STATE;
++#define CKS_RO_PUBLIC_SESSION 0
++#define CKS_RO_USER_FUNCTIONS 1
++#define CKS_RW_PUBLIC_SESSION 2
++#define CKS_RW_USER_FUNCTIONS 3
++#define CKS_RW_SO_FUNCTIONS 4
++
++
++/* CK_SESSION_INFO provides information about a session */
++typedef struct CK_SESSION_INFO {
++ CK_SLOT_ID slotID;
++ CK_STATE state;
++ CK_FLAGS flags; /* see below */
++
++ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulDeviceError; /* device-dependent error code */
++} CK_SESSION_INFO;
++
++/* The flags are defined in the following table:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RW_SESSION 0x00000002 /* session is r/w */
++#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
++
++typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
++
++
++/* CK_OBJECT_HANDLE is a token-specific identifier for an
++ * object */
++typedef CK_ULONG CK_OBJECT_HANDLE;
++
++typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
++
++
++/* CK_OBJECT_CLASS is a value that identifies the classes (or
++ * types) of objects that Cryptoki recognizes. It is defined
++ * as follows: */
++/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_OBJECT_CLASS;
++
++/* The following classes of objects are defined: */
++/* CKO_HW_FEATURE is new for v2.10 */
++/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
++/* CKO_MECHANISM is new for v2.20 */
++#define CKO_DATA 0x00000000
++#define CKO_CERTIFICATE 0x00000001
++#define CKO_PUBLIC_KEY 0x00000002
++#define CKO_PRIVATE_KEY 0x00000003
++#define CKO_SECRET_KEY 0x00000004
++#define CKO_HW_FEATURE 0x00000005
++#define CKO_DOMAIN_PARAMETERS 0x00000006
++#define CKO_MECHANISM 0x00000007
++
++/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */
++#define CKO_OTP_KEY 0x00000008
++
++#define CKO_VENDOR_DEFINED 0x80000000
++
++typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
++
++/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
++ * value that identifies the hardware feature type of an object
++ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
++typedef CK_ULONG CK_HW_FEATURE_TYPE;
++
++/* The following hardware feature types are defined */
++/* CKH_USER_INTERFACE is new for v2.20 */
++#define CKH_MONOTONIC_COUNTER 0x00000001
++#define CKH_CLOCK 0x00000002
++#define CKH_USER_INTERFACE 0x00000003
++#define CKH_VENDOR_DEFINED 0x80000000
++
++/* CK_KEY_TYPE is a value that identifies a key type */
++/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_KEY_TYPE;
++
++/* the following key types are defined: */
++#define CKK_RSA 0x00000000
++#define CKK_DSA 0x00000001
++#define CKK_DH 0x00000002
++
++/* CKK_ECDSA and CKK_KEA are new for v2.0 */
++/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
++#define CKK_ECDSA 0x00000003
++#define CKK_EC 0x00000003
++#define CKK_X9_42_DH 0x00000004
++#define CKK_KEA 0x00000005
++
++#define CKK_GENERIC_SECRET 0x00000010
++#define CKK_RC2 0x00000011
++#define CKK_RC4 0x00000012
++#define CKK_DES 0x00000013
++#define CKK_DES2 0x00000014
++#define CKK_DES3 0x00000015
++
++/* all these key types are new for v2.0 */
++#define CKK_CAST 0x00000016
++#define CKK_CAST3 0x00000017
++/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
++#define CKK_CAST5 0x00000018
++#define CKK_CAST128 0x00000018
++#define CKK_RC5 0x00000019
++#define CKK_IDEA 0x0000001A
++#define CKK_SKIPJACK 0x0000001B
++#define CKK_BATON 0x0000001C
++#define CKK_JUNIPER 0x0000001D
++#define CKK_CDMF 0x0000001E
++#define CKK_AES 0x0000001F
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKK_BLOWFISH 0x00000020
++#define CKK_TWOFISH 0x00000021
++
++/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */
++#define CKK_SECURID 0x00000022
++#define CKK_HOTP 0x00000023
++#define CKK_ACTI 0x00000024
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_CAMELLIA 0x00000025
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_ARIA 0x00000026
++
++
++#define CKK_VENDOR_DEFINED 0x80000000
++
++
++/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
++ * type */
++/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_CERTIFICATE_TYPE;
++
++/* The following certificate types are defined: */
++/* CKC_X_509_ATTR_CERT is new for v2.10 */
++/* CKC_WTLS is new for v2.20 */
++#define CKC_X_509 0x00000000
++#define CKC_X_509_ATTR_CERT 0x00000001
++#define CKC_WTLS 0x00000002
++#define CKC_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
++ * type */
++/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_ATTRIBUTE_TYPE;
++
++/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
++ consists of an array of values. */
++#define CKF_ARRAY_ATTRIBUTE 0x40000000
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_FORMAT attribute */
++#define CK_OTP_FORMAT_DECIMAL 0
++#define CK_OTP_FORMAT_HEXADECIMAL 1
++#define CK_OTP_FORMAT_ALPHANUMERIC 2
++#define CK_OTP_FORMAT_BINARY 3
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_..._REQUIREMENT attributes */
++#define CK_OTP_PARAM_IGNORED 0
++#define CK_OTP_PARAM_OPTIONAL 1
++#define CK_OTP_PARAM_MANDATORY 2
++
++/* The following attribute types are defined: */
++#define CKA_CLASS 0x00000000
++#define CKA_TOKEN 0x00000001
++#define CKA_PRIVATE 0x00000002
++#define CKA_LABEL 0x00000003
++#define CKA_APPLICATION 0x00000010
++#define CKA_VALUE 0x00000011
++
++/* CKA_OBJECT_ID is new for v2.10 */
++#define CKA_OBJECT_ID 0x00000012
++
++#define CKA_CERTIFICATE_TYPE 0x00000080
++#define CKA_ISSUER 0x00000081
++#define CKA_SERIAL_NUMBER 0x00000082
++
++/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
++ * for v2.10 */
++#define CKA_AC_ISSUER 0x00000083
++#define CKA_OWNER 0x00000084
++#define CKA_ATTR_TYPES 0x00000085
++
++/* CKA_TRUSTED is new for v2.11 */
++#define CKA_TRUSTED 0x00000086
++
++/* CKA_CERTIFICATE_CATEGORY ...
++ * CKA_CHECK_VALUE are new for v2.20 */
++#define CKA_CERTIFICATE_CATEGORY 0x00000087
++#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
++#define CKA_URL 0x00000089
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
++#define CKA_CHECK_VALUE 0x00000090
++
++#define CKA_KEY_TYPE 0x00000100
++#define CKA_SUBJECT 0x00000101
++#define CKA_ID 0x00000102
++#define CKA_SENSITIVE 0x00000103
++#define CKA_ENCRYPT 0x00000104
++#define CKA_DECRYPT 0x00000105
++#define CKA_WRAP 0x00000106
++#define CKA_UNWRAP 0x00000107
++#define CKA_SIGN 0x00000108
++#define CKA_SIGN_RECOVER 0x00000109
++#define CKA_VERIFY 0x0000010A
++#define CKA_VERIFY_RECOVER 0x0000010B
++#define CKA_DERIVE 0x0000010C
++#define CKA_START_DATE 0x00000110
++#define CKA_END_DATE 0x00000111
++#define CKA_MODULUS 0x00000120
++#define CKA_MODULUS_BITS 0x00000121
++#define CKA_PUBLIC_EXPONENT 0x00000122
++#define CKA_PRIVATE_EXPONENT 0x00000123
++#define CKA_PRIME_1 0x00000124
++#define CKA_PRIME_2 0x00000125
++#define CKA_EXPONENT_1 0x00000126
++#define CKA_EXPONENT_2 0x00000127
++#define CKA_COEFFICIENT 0x00000128
++#define CKA_PRIME 0x00000130
++#define CKA_SUBPRIME 0x00000131
++#define CKA_BASE 0x00000132
++
++/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
++#define CKA_PRIME_BITS 0x00000133
++#define CKA_SUBPRIME_BITS 0x00000134
++#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
++/* (To retain backwards-compatibility) */
++
++#define CKA_VALUE_BITS 0x00000160
++#define CKA_VALUE_LEN 0x00000161
++
++/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
++ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
++ * and CKA_EC_POINT are new for v2.0 */
++#define CKA_EXTRACTABLE 0x00000162
++#define CKA_LOCAL 0x00000163
++#define CKA_NEVER_EXTRACTABLE 0x00000164
++#define CKA_ALWAYS_SENSITIVE 0x00000165
++
++/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
++#define CKA_KEY_GEN_MECHANISM 0x00000166
++
++#define CKA_MODIFIABLE 0x00000170
++
++/* CKA_ECDSA_PARAMS is deprecated in v2.11,
++ * CKA_EC_PARAMS is preferred. */
++#define CKA_ECDSA_PARAMS 0x00000180
++#define CKA_EC_PARAMS 0x00000180
++
++#define CKA_EC_POINT 0x00000181
++
++/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
++ * are new for v2.10. Deprecated in v2.11 and onwards. */
++#define CKA_SECONDARY_AUTH 0x00000200
++#define CKA_AUTH_PIN_FLAGS 0x00000201
++
++/* CKA_ALWAYS_AUTHENTICATE ...
++ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
++#define CKA_ALWAYS_AUTHENTICATE 0x00000202
++
++#define CKA_WRAP_WITH_TRUSTED 0x00000210
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++
++/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */
++#define CKA_OTP_FORMAT 0x00000220
++#define CKA_OTP_LENGTH 0x00000221
++#define CKA_OTP_TIME_INTERVAL 0x00000222
++#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
++#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
++#define CKA_OTP_TIME_REQUIREMENT 0x00000225
++#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
++#define CKA_OTP_PIN_REQUIREMENT 0x00000227
++#define CKA_OTP_COUNTER 0x0000022E
++#define CKA_OTP_TIME 0x0000022F
++#define CKA_OTP_USER_IDENTIFIER 0x0000022A
++#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
++#define CKA_OTP_SERVICE_LOGO 0x0000022C
++#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
++
++
++/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
++ * are new for v2.10 */
++#define CKA_HW_FEATURE_TYPE 0x00000300
++#define CKA_RESET_ON_INIT 0x00000301
++#define CKA_HAS_RESET 0x00000302
++
++/* The following attributes are new for v2.20 */
++#define CKA_PIXEL_X 0x00000400
++#define CKA_PIXEL_Y 0x00000401
++#define CKA_RESOLUTION 0x00000402
++#define CKA_CHAR_ROWS 0x00000403
++#define CKA_CHAR_COLUMNS 0x00000404
++#define CKA_COLOR 0x00000405
++#define CKA_BITS_PER_PIXEL 0x00000406
++#define CKA_CHAR_SETS 0x00000480
++#define CKA_ENCODING_METHODS 0x00000481
++#define CKA_MIME_TYPES 0x00000482
++#define CKA_MECHANISM_TYPE 0x00000500
++#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
++#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
++#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
++#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
++
++#define CKA_VENDOR_DEFINED 0x80000000
++
++/* CK_ATTRIBUTE is a structure that includes the type, length
++ * and value of an attribute */
++typedef struct CK_ATTRIBUTE {
++ CK_ATTRIBUTE_TYPE type;
++ CK_VOID_PTR pValue;
++
++ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulValueLen; /* in bytes */
++} CK_ATTRIBUTE;
++
++typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
++
++
++/* CK_DATE is a structure that defines a date */
++typedef struct CK_DATE{
++ CK_CHAR year[4]; /* the year ("1900" - "9999") */
++ CK_CHAR month[2]; /* the month ("01" - "12") */
++ CK_CHAR day[2]; /* the day ("01" - "31") */
++} CK_DATE;
++
++
++/* CK_MECHANISM_TYPE is a value that identifies a mechanism
++ * type */
++/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_MECHANISM_TYPE;
++
++/* the following mechanism types are defined: */
++#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
++#define CKM_RSA_PKCS 0x00000001
++#define CKM_RSA_9796 0x00000002
++#define CKM_RSA_X_509 0x00000003
++
++/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
++ * are new for v2.0. They are mechanisms which hash and sign */
++#define CKM_MD2_RSA_PKCS 0x00000004
++#define CKM_MD5_RSA_PKCS 0x00000005
++#define CKM_SHA1_RSA_PKCS 0x00000006
++
++/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
++ * CKM_RSA_PKCS_OAEP are new for v2.10 */
++#define CKM_RIPEMD128_RSA_PKCS 0x00000007
++#define CKM_RIPEMD160_RSA_PKCS 0x00000008
++#define CKM_RSA_PKCS_OAEP 0x00000009
++
++/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
++ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
++#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
++#define CKM_RSA_X9_31 0x0000000B
++#define CKM_SHA1_RSA_X9_31 0x0000000C
++#define CKM_RSA_PKCS_PSS 0x0000000D
++#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
++
++#define CKM_DSA_KEY_PAIR_GEN 0x00000010
++#define CKM_DSA 0x00000011
++#define CKM_DSA_SHA1 0x00000012
++#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
++#define CKM_DH_PKCS_DERIVE 0x00000021
++
++/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
++ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
++ * v2.11 */
++#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
++#define CKM_X9_42_DH_DERIVE 0x00000031
++#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
++#define CKM_X9_42_MQV_DERIVE 0x00000033
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_RSA_PKCS 0x00000040
++#define CKM_SHA384_RSA_PKCS 0x00000041
++#define CKM_SHA512_RSA_PKCS 0x00000042
++#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
++#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
++#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
++
++/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_RSA_PKCS 0x00000046
++#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
++
++#define CKM_RC2_KEY_GEN 0x00000100
++#define CKM_RC2_ECB 0x00000101
++#define CKM_RC2_CBC 0x00000102
++#define CKM_RC2_MAC 0x00000103
++
++/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
++#define CKM_RC2_MAC_GENERAL 0x00000104
++#define CKM_RC2_CBC_PAD 0x00000105
++
++#define CKM_RC4_KEY_GEN 0x00000110
++#define CKM_RC4 0x00000111
++#define CKM_DES_KEY_GEN 0x00000120
++#define CKM_DES_ECB 0x00000121
++#define CKM_DES_CBC 0x00000122
++#define CKM_DES_MAC 0x00000123
++
++/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
++#define CKM_DES_MAC_GENERAL 0x00000124
++#define CKM_DES_CBC_PAD 0x00000125
++
++#define CKM_DES2_KEY_GEN 0x00000130
++#define CKM_DES3_KEY_GEN 0x00000131
++#define CKM_DES3_ECB 0x00000132
++#define CKM_DES3_CBC 0x00000133
++#define CKM_DES3_MAC 0x00000134
++
++/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
++ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
++ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
++#define CKM_DES3_MAC_GENERAL 0x00000135
++#define CKM_DES3_CBC_PAD 0x00000136
++#define CKM_CDMF_KEY_GEN 0x00000140
++#define CKM_CDMF_ECB 0x00000141
++#define CKM_CDMF_CBC 0x00000142
++#define CKM_CDMF_MAC 0x00000143
++#define CKM_CDMF_MAC_GENERAL 0x00000144
++#define CKM_CDMF_CBC_PAD 0x00000145
++
++/* the following four DES mechanisms are new for v2.20 */
++#define CKM_DES_OFB64 0x00000150
++#define CKM_DES_OFB8 0x00000151
++#define CKM_DES_CFB64 0x00000152
++#define CKM_DES_CFB8 0x00000153
++
++#define CKM_MD2 0x00000200
++
++/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD2_HMAC 0x00000201
++#define CKM_MD2_HMAC_GENERAL 0x00000202
++
++#define CKM_MD5 0x00000210
++
++/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD5_HMAC 0x00000211
++#define CKM_MD5_HMAC_GENERAL 0x00000212
++
++#define CKM_SHA_1 0x00000220
++
++/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
++#define CKM_SHA_1_HMAC 0x00000221
++#define CKM_SHA_1_HMAC_GENERAL 0x00000222
++
++/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
++ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
++ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
++#define CKM_RIPEMD128 0x00000230
++#define CKM_RIPEMD128_HMAC 0x00000231
++#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
++#define CKM_RIPEMD160 0x00000240
++#define CKM_RIPEMD160_HMAC 0x00000241
++#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256 0x00000250
++#define CKM_SHA256_HMAC 0x00000251
++#define CKM_SHA256_HMAC_GENERAL 0x00000252
++
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224 0x00000255
++#define CKM_SHA224_HMAC 0x00000256
++#define CKM_SHA224_HMAC_GENERAL 0x00000257
++
++#define CKM_SHA384 0x00000260
++#define CKM_SHA384_HMAC 0x00000261
++#define CKM_SHA384_HMAC_GENERAL 0x00000262
++#define CKM_SHA512 0x00000270
++#define CKM_SHA512_HMAC 0x00000271
++#define CKM_SHA512_HMAC_GENERAL 0x00000272
++
++/* SecurID is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_SECURID_KEY_GEN 0x00000280
++#define CKM_SECURID 0x00000282
++
++/* HOTP is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_HOTP_KEY_GEN 0x00000290
++#define CKM_HOTP 0x00000291
++
++/* ACTI is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_ACTI 0x000002A0
++#define CKM_ACTI_KEY_GEN 0x000002A1
++
++/* All of the following mechanisms are new for v2.0 */
++/* Note that CAST128 and CAST5 are the same algorithm */
++#define CKM_CAST_KEY_GEN 0x00000300
++#define CKM_CAST_ECB 0x00000301
++#define CKM_CAST_CBC 0x00000302
++#define CKM_CAST_MAC 0x00000303
++#define CKM_CAST_MAC_GENERAL 0x00000304
++#define CKM_CAST_CBC_PAD 0x00000305
++#define CKM_CAST3_KEY_GEN 0x00000310
++#define CKM_CAST3_ECB 0x00000311
++#define CKM_CAST3_CBC 0x00000312
++#define CKM_CAST3_MAC 0x00000313
++#define CKM_CAST3_MAC_GENERAL 0x00000314
++#define CKM_CAST3_CBC_PAD 0x00000315
++#define CKM_CAST5_KEY_GEN 0x00000320
++#define CKM_CAST128_KEY_GEN 0x00000320
++#define CKM_CAST5_ECB 0x00000321
++#define CKM_CAST128_ECB 0x00000321
++#define CKM_CAST5_CBC 0x00000322
++#define CKM_CAST128_CBC 0x00000322
++#define CKM_CAST5_MAC 0x00000323
++#define CKM_CAST128_MAC 0x00000323
++#define CKM_CAST5_MAC_GENERAL 0x00000324
++#define CKM_CAST128_MAC_GENERAL 0x00000324
++#define CKM_CAST5_CBC_PAD 0x00000325
++#define CKM_CAST128_CBC_PAD 0x00000325
++#define CKM_RC5_KEY_GEN 0x00000330
++#define CKM_RC5_ECB 0x00000331
++#define CKM_RC5_CBC 0x00000332
++#define CKM_RC5_MAC 0x00000333
++#define CKM_RC5_MAC_GENERAL 0x00000334
++#define CKM_RC5_CBC_PAD 0x00000335
++#define CKM_IDEA_KEY_GEN 0x00000340
++#define CKM_IDEA_ECB 0x00000341
++#define CKM_IDEA_CBC 0x00000342
++#define CKM_IDEA_MAC 0x00000343
++#define CKM_IDEA_MAC_GENERAL 0x00000344
++#define CKM_IDEA_CBC_PAD 0x00000345
++#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
++#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
++#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
++#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
++#define CKM_XOR_BASE_AND_DATA 0x00000364
++#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
++#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
++#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
++#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
++
++/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
++ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
++ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
++#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
++#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
++#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
++#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
++#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
++
++/* CKM_TLS_PRF is new for v2.20 */
++#define CKM_TLS_PRF 0x00000378
++
++#define CKM_SSL3_MD5_MAC 0x00000380
++#define CKM_SSL3_SHA1_MAC 0x00000381
++#define CKM_MD5_KEY_DERIVATION 0x00000390
++#define CKM_MD2_KEY_DERIVATION 0x00000391
++#define CKM_SHA1_KEY_DERIVATION 0x00000392
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_KEY_DERIVATION 0x00000393
++#define CKM_SHA384_KEY_DERIVATION 0x00000394
++#define CKM_SHA512_KEY_DERIVATION 0x00000395
++
++/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_KEY_DERIVATION 0x00000396
++
++#define CKM_PBE_MD2_DES_CBC 0x000003A0
++#define CKM_PBE_MD5_DES_CBC 0x000003A1
++#define CKM_PBE_MD5_CAST_CBC 0x000003A2
++#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
++#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
++#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
++#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
++#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
++#define CKM_PBE_SHA1_RC4_128 0x000003A6
++#define CKM_PBE_SHA1_RC4_40 0x000003A7
++#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
++#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
++#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
++#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
++
++/* CKM_PKCS5_PBKD2 is new for v2.10 */
++#define CKM_PKCS5_PBKD2 0x000003B0
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
++
++/* WTLS mechanisms are new for v2.20 */
++#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
++#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
++#define CKM_WTLS_PRF 0x000003D3
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
++
++#define CKM_KEY_WRAP_LYNKS 0x00000400
++#define CKM_KEY_WRAP_SET_OAEP 0x00000401
++
++/* CKM_CMS_SIG is new for v2.20 */
++#define CKM_CMS_SIG 0x00000500
++
++/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */
++#define CKM_KIP_DERIVE 0x00000510
++#define CKM_KIP_WRAP 0x00000511
++#define CKM_KIP_MAC 0x00000512
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_CAMELLIA_KEY_GEN 0x00000550
++#define CKM_CAMELLIA_ECB 0x00000551
++#define CKM_CAMELLIA_CBC 0x00000552
++#define CKM_CAMELLIA_MAC 0x00000553
++#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
++#define CKM_CAMELLIA_CBC_PAD 0x00000555
++#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
++#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
++#define CKM_CAMELLIA_CTR 0x00000558
++
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_ARIA_KEY_GEN 0x00000560
++#define CKM_ARIA_ECB 0x00000561
++#define CKM_ARIA_CBC 0x00000562
++#define CKM_ARIA_MAC 0x00000563
++#define CKM_ARIA_MAC_GENERAL 0x00000564
++#define CKM_ARIA_CBC_PAD 0x00000565
++#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
++#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
++
++/* Fortezza mechanisms */
++#define CKM_SKIPJACK_KEY_GEN 0x00001000
++#define CKM_SKIPJACK_ECB64 0x00001001
++#define CKM_SKIPJACK_CBC64 0x00001002
++#define CKM_SKIPJACK_OFB64 0x00001003
++#define CKM_SKIPJACK_CFB64 0x00001004
++#define CKM_SKIPJACK_CFB32 0x00001005
++#define CKM_SKIPJACK_CFB16 0x00001006
++#define CKM_SKIPJACK_CFB8 0x00001007
++#define CKM_SKIPJACK_WRAP 0x00001008
++#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
++#define CKM_SKIPJACK_RELAYX 0x0000100a
++#define CKM_KEA_KEY_PAIR_GEN 0x00001010
++#define CKM_KEA_KEY_DERIVE 0x00001011
++#define CKM_FORTEZZA_TIMESTAMP 0x00001020
++#define CKM_BATON_KEY_GEN 0x00001030
++#define CKM_BATON_ECB128 0x00001031
++#define CKM_BATON_ECB96 0x00001032
++#define CKM_BATON_CBC128 0x00001033
++#define CKM_BATON_COUNTER 0x00001034
++#define CKM_BATON_SHUFFLE 0x00001035
++#define CKM_BATON_WRAP 0x00001036
++
++/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
++ * CKM_EC_KEY_PAIR_GEN is preferred */
++#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
++#define CKM_EC_KEY_PAIR_GEN 0x00001040
++
++#define CKM_ECDSA 0x00001041
++#define CKM_ECDSA_SHA1 0x00001042
++
++/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
++ * are new for v2.11 */
++#define CKM_ECDH1_DERIVE 0x00001050
++#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
++#define CKM_ECMQV_DERIVE 0x00001052
++
++#define CKM_JUNIPER_KEY_GEN 0x00001060
++#define CKM_JUNIPER_ECB128 0x00001061
++#define CKM_JUNIPER_CBC128 0x00001062
++#define CKM_JUNIPER_COUNTER 0x00001063
++#define CKM_JUNIPER_SHUFFLE 0x00001064
++#define CKM_JUNIPER_WRAP 0x00001065
++#define CKM_FASTHASH 0x00001070
++
++/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
++ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
++ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
++ * new for v2.11 */
++#define CKM_AES_KEY_GEN 0x00001080
++#define CKM_AES_ECB 0x00001081
++#define CKM_AES_CBC 0x00001082
++#define CKM_AES_MAC 0x00001083
++#define CKM_AES_MAC_GENERAL 0x00001084
++#define CKM_AES_CBC_PAD 0x00001085
++
++/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_AES_CTR 0x00001086
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKM_BLOWFISH_KEY_GEN 0x00001090
++#define CKM_BLOWFISH_CBC 0x00001091
++#define CKM_TWOFISH_KEY_GEN 0x00001092
++#define CKM_TWOFISH_CBC 0x00001093
++
++
++/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
++#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
++#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
++#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
++#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
++#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
++#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
++
++#define CKM_DSA_PARAMETER_GEN 0x00002000
++#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
++#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
++
++#define CKM_VENDOR_DEFINED 0x80000000
++
++typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
++
++
++/* CK_MECHANISM is a structure that specifies a particular
++ * mechanism */
++typedef struct CK_MECHANISM {
++ CK_MECHANISM_TYPE mechanism;
++ CK_VOID_PTR pParameter;
++
++ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulParameterLen; /* in bytes */
++} CK_MECHANISM;
++
++typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
++
++
++/* CK_MECHANISM_INFO provides information about a particular
++ * mechanism */
++typedef struct CK_MECHANISM_INFO {
++ CK_ULONG ulMinKeySize;
++ CK_ULONG ulMaxKeySize;
++ CK_FLAGS flags;
++} CK_MECHANISM_INFO;
++
++/* The flags are defined as follows:
++ * Bit Flag Mask Meaning */
++#define CKF_HW 0x00000001 /* performed by HW */
++
++/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
++ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
++ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
++ * and CKF_DERIVE are new for v2.0. They specify whether or not
++ * a mechanism can be used for a particular task */
++#define CKF_ENCRYPT 0x00000100
++#define CKF_DECRYPT 0x00000200
++#define CKF_DIGEST 0x00000400
++#define CKF_SIGN 0x00000800
++#define CKF_SIGN_RECOVER 0x00001000
++#define CKF_VERIFY 0x00002000
++#define CKF_VERIFY_RECOVER 0x00004000
++#define CKF_GENERATE 0x00008000
++#define CKF_GENERATE_KEY_PAIR 0x00010000
++#define CKF_WRAP 0x00020000
++#define CKF_UNWRAP 0x00040000
++#define CKF_DERIVE 0x00080000
++
++/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
++ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
++ * describe a token's EC capabilities not available in mechanism
++ * information. */
++#define CKF_EC_F_P 0x00100000
++#define CKF_EC_F_2M 0x00200000
++#define CKF_EC_ECPARAMETERS 0x00400000
++#define CKF_EC_NAMEDCURVE 0x00800000
++#define CKF_EC_UNCOMPRESS 0x01000000
++#define CKF_EC_COMPRESS 0x02000000
++
++#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
++
++typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
++
++
++/* CK_RV is a value that identifies the return value of a
++ * Cryptoki function */
++/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_RV;
++
++#define CKR_OK 0x00000000
++#define CKR_CANCEL 0x00000001
++#define CKR_HOST_MEMORY 0x00000002
++#define CKR_SLOT_ID_INVALID 0x00000003
++
++/* CKR_FLAGS_INVALID was removed for v2.0 */
++
++/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
++#define CKR_GENERAL_ERROR 0x00000005
++#define CKR_FUNCTION_FAILED 0x00000006
++
++/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
++ * and CKR_CANT_LOCK are new for v2.01 */
++#define CKR_ARGUMENTS_BAD 0x00000007
++#define CKR_NO_EVENT 0x00000008
++#define CKR_NEED_TO_CREATE_THREADS 0x00000009
++#define CKR_CANT_LOCK 0x0000000A
++
++#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
++#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
++#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
++#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
++#define CKR_DATA_INVALID 0x00000020
++#define CKR_DATA_LEN_RANGE 0x00000021
++#define CKR_DEVICE_ERROR 0x00000030
++#define CKR_DEVICE_MEMORY 0x00000031
++#define CKR_DEVICE_REMOVED 0x00000032
++#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
++#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
++#define CKR_FUNCTION_CANCELED 0x00000050
++#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
++
++/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
++#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
++
++#define CKR_KEY_HANDLE_INVALID 0x00000060
++
++/* CKR_KEY_SENSITIVE was removed for v2.0 */
++
++#define CKR_KEY_SIZE_RANGE 0x00000062
++#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
++
++/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
++ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
++ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
++ * v2.0 */
++#define CKR_KEY_NOT_NEEDED 0x00000064
++#define CKR_KEY_CHANGED 0x00000065
++#define CKR_KEY_NEEDED 0x00000066
++#define CKR_KEY_INDIGESTIBLE 0x00000067
++#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
++#define CKR_KEY_NOT_WRAPPABLE 0x00000069
++#define CKR_KEY_UNEXTRACTABLE 0x0000006A
++
++#define CKR_MECHANISM_INVALID 0x00000070
++#define CKR_MECHANISM_PARAM_INVALID 0x00000071
++
++/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
++ * were removed for v2.0 */
++#define CKR_OBJECT_HANDLE_INVALID 0x00000082
++#define CKR_OPERATION_ACTIVE 0x00000090
++#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
++#define CKR_PIN_INCORRECT 0x000000A0
++#define CKR_PIN_INVALID 0x000000A1
++#define CKR_PIN_LEN_RANGE 0x000000A2
++
++/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
++#define CKR_PIN_EXPIRED 0x000000A3
++#define CKR_PIN_LOCKED 0x000000A4
++
++#define CKR_SESSION_CLOSED 0x000000B0
++#define CKR_SESSION_COUNT 0x000000B1
++#define CKR_SESSION_HANDLE_INVALID 0x000000B3
++#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
++#define CKR_SESSION_READ_ONLY 0x000000B5
++#define CKR_SESSION_EXISTS 0x000000B6
++
++/* CKR_SESSION_READ_ONLY_EXISTS and
++ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
++#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
++#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
++
++#define CKR_SIGNATURE_INVALID 0x000000C0
++#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
++#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
++#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
++#define CKR_TOKEN_NOT_PRESENT 0x000000E0
++#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
++#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
++#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
++#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
++#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
++#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
++#define CKR_USER_NOT_LOGGED_IN 0x00000101
++#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
++#define CKR_USER_TYPE_INVALID 0x00000103
++
++/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
++ * are new to v2.01 */
++#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
++#define CKR_USER_TOO_MANY_TYPES 0x00000105
++
++#define CKR_WRAPPED_KEY_INVALID 0x00000110
++#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
++#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
++#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
++#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
++#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
++
++/* These are new to v2.0 */
++#define CKR_RANDOM_NO_RNG 0x00000121
++
++/* These are new to v2.11 */
++#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
++
++/* These are new to v2.0 */
++#define CKR_BUFFER_TOO_SMALL 0x00000150
++#define CKR_SAVED_STATE_INVALID 0x00000160
++#define CKR_INFORMATION_SENSITIVE 0x00000170
++#define CKR_STATE_UNSAVEABLE 0x00000180
++
++/* These are new to v2.01 */
++#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
++#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
++#define CKR_MUTEX_BAD 0x000001A0
++#define CKR_MUTEX_NOT_LOCKED 0x000001A1
++
++/* The following return values are new for PKCS #11 v2.20 amendment 3 */
++#define CKR_NEW_PIN_MODE 0x000001B0
++#define CKR_NEXT_OTP 0x000001B1
++
++/* This is new to v2.20 */
++#define CKR_FUNCTION_REJECTED 0x00000200
++
++#define CKR_VENDOR_DEFINED 0x80000000
++
++
++/* CK_NOTIFY is an application callback that processes events */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication /* passed to C_OpenSession */
++);
++
++
++/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
++ * version and pointers of appropriate types to all the
++ * Cryptoki functions */
++/* CK_FUNCTION_LIST is new for v2.0 */
++typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
++
++typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
++
++typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
++
++
++/* CK_CREATEMUTEX is an application callback for creating a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
++ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
++);
++
++
++/* CK_DESTROYMUTEX is an application callback for destroying a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_LOCKMUTEX is an application callback for locking a mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_UNLOCKMUTEX is an application callback for unlocking a
++ * mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_C_INITIALIZE_ARGS provides the optional arguments to
++ * C_Initialize */
++typedef struct CK_C_INITIALIZE_ARGS {
++ CK_CREATEMUTEX CreateMutex;
++ CK_DESTROYMUTEX DestroyMutex;
++ CK_LOCKMUTEX LockMutex;
++ CK_UNLOCKMUTEX UnlockMutex;
++ CK_FLAGS flags;
++ CK_VOID_PTR pReserved;
++} CK_C_INITIALIZE_ARGS;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
++#define CKF_OS_LOCKING_OK 0x00000002
++
++typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
++
++
++/* additional flags for parameters to functions */
++
++/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
++#define CKF_DONT_BLOCK 1
++
++/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
++ * Generation Function (MGF) applied to a message block when
++ * formatting a message block for the PKCS #1 OAEP encryption
++ * scheme. */
++typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
++
++typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
++
++/* The following MGFs are defined */
++/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
++ * are new for v2.20 */
++#define CKG_MGF1_SHA1 0x00000001
++#define CKG_MGF1_SHA256 0x00000002
++#define CKG_MGF1_SHA384 0x00000003
++#define CKG_MGF1_SHA512 0x00000004
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKG_MGF1_SHA224 0x00000005
++
++/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
++ * of the encoding parameter when formatting a message block
++ * for the PKCS #1 OAEP encryption scheme. */
++typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
++
++typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
++
++/* The following encoding parameter sources are defined */
++#define CKZ_DATA_SPECIFIED 0x00000001
++
++/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
++ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_OAEP mechanism. */
++typedef struct CK_RSA_PKCS_OAEP_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
++ CK_VOID_PTR pSourceData;
++ CK_ULONG ulSourceDataLen;
++} CK_RSA_PKCS_OAEP_PARAMS;
++
++typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
++
++/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
++ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_PSS mechanism(s). */
++typedef struct CK_RSA_PKCS_PSS_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_ULONG sLen;
++} CK_RSA_PKCS_PSS_PARAMS;
++
++typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
++
++/* CK_EC_KDF_TYPE is new for v2.11. */
++typedef CK_ULONG CK_EC_KDF_TYPE;
++
++/* The following EC Key Derivation Functions are defined */
++#define CKD_NULL 0x00000001
++#define CKD_SHA1_KDF 0x00000002
++
++/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
++ * where each party contributes one key pair.
++ */
++typedef struct CK_ECDH1_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_ECDH1_DERIVE_PARAMS;
++
++typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
++
++
++/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
++typedef struct CK_ECDH2_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_ECDH2_DERIVE_PARAMS;
++
++typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_ECMQV_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_ECMQV_DERIVE_PARAMS;
++
++typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
++
++/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
++ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
++typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
++typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
++
++/* The following X9.42 DH key derivation functions are defined
++ (besides CKD_NULL already defined : */
++#define CKD_SHA1_KDF_ASN1 0x00000003
++#define CKD_SHA1_KDF_CONCATENATE 0x00000004
++
++/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
++ * contributes one key pair */
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_X9_42_DH1_DERIVE_PARAMS;
++
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
++
++/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
++ * mechanisms, where each party contributes two key pairs */
++typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_X9_42_DH2_DERIVE_PARAMS;
++
++typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_X9_42_MQV_DERIVE_PARAMS;
++
++typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
++
++/* CK_KEA_DERIVE_PARAMS provides the parameters to the
++ * CKM_KEA_DERIVE mechanism */
++/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
++typedef struct CK_KEA_DERIVE_PARAMS {
++ CK_BBOOL isSender;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pRandomB;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_KEA_DERIVE_PARAMS;
++
++typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
++
++
++/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
++ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
++ * holds the effective keysize */
++typedef CK_ULONG CK_RC2_PARAMS;
++
++typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
++
++
++/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
++ * mechanism */
++typedef struct CK_RC2_CBC_PARAMS {
++ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++
++ CK_BYTE iv[8]; /* IV for CBC mode */
++} CK_RC2_CBC_PARAMS;
++
++typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
++
++
++/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC2_MAC_GENERAL mechanism */
++/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC2_MAC_GENERAL_PARAMS {
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC2_MAC_GENERAL_PARAMS;
++
++typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC2_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
++ * CKM_RC5_MAC mechanisms */
++/* CK_RC5_PARAMS is new for v2.0 */
++typedef struct CK_RC5_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++} CK_RC5_PARAMS;
++
++typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
++
++
++/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
++ * mechanism */
++/* CK_RC5_CBC_PARAMS is new for v2.0 */
++typedef struct CK_RC5_CBC_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_BYTE_PTR pIv; /* pointer to IV */
++ CK_ULONG ulIvLen; /* length of IV in bytes */
++} CK_RC5_CBC_PARAMS;
++
++typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
++
++
++/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC5_MAC_GENERAL mechanism */
++/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC5_MAC_GENERAL_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC5_MAC_GENERAL_PARAMS;
++
++typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC5_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
++ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
++ * the MAC */
++/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
++
++typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
++
++/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
++typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[8];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pPassword;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPAndGLen;
++ CK_ULONG ulQLen;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pPrimeP;
++ CK_BYTE_PTR pBaseG;
++ CK_BYTE_PTR pSubprimeQ;
++} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
++
++typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
++ CK_SKIPJACK_PRIVATE_WRAP_PTR;
++
++
++/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_RELAYX mechanism */
++/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_RELAYX_PARAMS {
++ CK_ULONG ulOldWrappedXLen;
++ CK_BYTE_PTR pOldWrappedX;
++ CK_ULONG ulOldPasswordLen;
++ CK_BYTE_PTR pOldPassword;
++ CK_ULONG ulOldPublicDataLen;
++ CK_BYTE_PTR pOldPublicData;
++ CK_ULONG ulOldRandomLen;
++ CK_BYTE_PTR pOldRandomA;
++ CK_ULONG ulNewPasswordLen;
++ CK_BYTE_PTR pNewPassword;
++ CK_ULONG ulNewPublicDataLen;
++ CK_BYTE_PTR pNewPublicData;
++ CK_ULONG ulNewRandomLen;
++ CK_BYTE_PTR pNewRandomA;
++} CK_SKIPJACK_RELAYX_PARAMS;
++
++typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
++ CK_SKIPJACK_RELAYX_PARAMS_PTR;
++
++
++typedef struct CK_PBE_PARAMS {
++ CK_BYTE_PTR pInitVector;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pSalt;
++ CK_ULONG ulSaltLen;
++ CK_ULONG ulIteration;
++} CK_PBE_PARAMS;
++
++typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
++
++
++/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
++ * CKM_KEY_WRAP_SET_OAEP mechanism */
++/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
++typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
++ CK_BYTE bBC; /* block contents byte */
++ CK_BYTE_PTR pX; /* extra data */
++ CK_ULONG ulXLen; /* length of extra data in bytes */
++} CK_KEY_WRAP_SET_OAEP_PARAMS;
++
++typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
++ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_SSL3_RANDOM_DATA;
++
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_VERSION_PTR pVersion;
++} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hClientMacSecret;
++ CK_OBJECT_HANDLE hServerMacSecret;
++ CK_OBJECT_HANDLE hClientKey;
++ CK_OBJECT_HANDLE hServerKey;
++ CK_BYTE_PTR pIVClient;
++ CK_BYTE_PTR pIVServer;
++} CK_SSL3_KEY_MAT_OUT;
++
++typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_PARAMS {
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_BBOOL bIsExport;
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_SSL3_KEY_MAT_PARAMS;
++
++typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
++
++/* CK_TLS_PRF_PARAMS is new for version 2.20 */
++typedef struct CK_TLS_PRF_PARAMS {
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_TLS_PRF_PARAMS;
++
++typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
++
++/* WTLS is new for version 2.20 */
++typedef struct CK_WTLS_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_WTLS_RANDOM_DATA;
++
++typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
++
++typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_BYTE_PTR pVersion;
++} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
++
++typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++typedef struct CK_WTLS_PRF_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_WTLS_PRF_PARAMS;
++
++typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hMacSecret;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pIV;
++} CK_WTLS_KEY_MAT_OUT;
++
++typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_ULONG ulSequenceNumber;
++ CK_BBOOL bIsExport;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_WTLS_KEY_MAT_PARAMS;
++
++typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
++
++/* CMS is new for version 2.20 */
++typedef struct CK_CMS_SIG_PARAMS {
++ CK_OBJECT_HANDLE certificateHandle;
++ CK_MECHANISM_PTR pSigningMechanism;
++ CK_MECHANISM_PTR pDigestMechanism;
++ CK_UTF8CHAR_PTR pContentType;
++ CK_BYTE_PTR pRequestedAttributes;
++ CK_ULONG ulRequestedAttributesLen;
++ CK_BYTE_PTR pRequiredAttributes;
++ CK_ULONG ulRequiredAttributesLen;
++} CK_CMS_SIG_PARAMS;
++
++typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
++
++typedef struct CK_KEY_DERIVATION_STRING_DATA {
++ CK_BYTE_PTR pData;
++ CK_ULONG ulLen;
++} CK_KEY_DERIVATION_STRING_DATA;
++
++typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
++ CK_KEY_DERIVATION_STRING_DATA_PTR;
++
++
++/* The CK_EXTRACT_PARAMS is used for the
++ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
++ * of the base key should be used as the first bit of the
++ * derived key */
++/* CK_EXTRACT_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_EXTRACT_PARAMS;
++
++typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
++
++/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
++ * indicate the Pseudo-Random Function (PRF) used to generate
++ * key bits using PKCS #5 PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
++
++typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
++
++/* The following PRFs are defined in PKCS #5 v2.0. */
++#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
++
++
++/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
++ * source of the salt value when deriving a key using PKCS #5
++ * PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
++
++typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
++
++/* The following salt value sources are defined in PKCS #5 v2.0. */
++#define CKZ_SALT_SPECIFIED 0x00000001
++
++/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
++ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
++ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
++typedef struct CK_PKCS5_PBKD2_PARAMS {
++ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ CK_VOID_PTR pSaltSourceData;
++ CK_ULONG ulSaltSourceDataLen;
++ CK_ULONG iterations;
++ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ CK_VOID_PTR pPrfData;
++ CK_ULONG ulPrfDataLen;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG_PTR ulPasswordLen;
++} CK_PKCS5_PBKD2_PARAMS;
++
++typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
++
++/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */
++
++typedef CK_ULONG CK_OTP_PARAM_TYPE;
++typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */
++
++typedef struct CK_OTP_PARAM {
++ CK_OTP_PARAM_TYPE type;
++ CK_VOID_PTR pValue;
++ CK_ULONG ulValueLen;
++} CK_OTP_PARAM;
++
++typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
++
++typedef struct CK_OTP_PARAMS {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_PARAMS;
++
++typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
++
++typedef struct CK_OTP_SIGNATURE_INFO {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_SIGNATURE_INFO;
++
++typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CK_OTP_VALUE 0
++#define CK_OTP_PIN 1
++#define CK_OTP_CHALLENGE 2
++#define CK_OTP_TIME 3
++#define CK_OTP_COUNTER 4
++#define CK_OTP_FLAGS 5
++#define CK_OTP_OUTPUT_LENGTH 6
++#define CK_OTP_OUTPUT_FORMAT 7
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CKF_NEXT_OTP 0x00000001
++#define CKF_EXCLUDE_TIME 0x00000002
++#define CKF_EXCLUDE_COUNTER 0x00000004
++#define CKF_EXCLUDE_CHALLENGE 0x00000008
++#define CKF_EXCLUDE_PIN 0x00000010
++#define CKF_USER_FRIENDLY_OTP 0x00000020
++
++/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */
++typedef struct CK_KIP_PARAMS {
++ CK_MECHANISM_PTR pMechanism;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++} CK_KIP_PARAMS;
++
++typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
++
++/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_AES_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_AES_CTR_PARAMS;
++
++typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_CAMELLIA_CTR_PARAMS;
++
++typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++#endif
+Index: openssl/util/libeay.num
+diff -u openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.4.1.2.1 openssl/util/libeay.num:1.15
+--- openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.4.1.2.1 Mon Jun 13 15:11:04 2016
++++ openssl/util/libeay.num Mon Jun 13 15:21:08 2016
+@@ -4316,3 +4316,5 @@
+ BIO_s_datagram_sctp 4680 EXIST::FUNCTION:DGRAM,SCTP
+ BIO_dgram_is_sctp 4681 EXIST::FUNCTION:SCTP
+ BIO_dgram_sctp_notification_cb 4682 EXIST::FUNCTION:SCTP
++ENGINE_load_pk11ca 4683 EXIST::FUNCTION:HW_PKCS11CA,ENGINE
++ENGINE_load_pk11so 4683 EXIST::FUNCTION:HW_PKCS11SO,ENGINE
+Index: openssl/util/mk1mf.pl
+diff -u openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.4.1.2.1 openssl/util/mk1mf.pl:1.14
+--- openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.4.1.2.1 Mon Jun 13 15:11:05 2016
++++ openssl/util/mk1mf.pl Mon Jun 13 15:21:08 2016
+@@ -114,6 +114,8 @@
+ no-ecdh - No ECDH
+ no-engine - No engine
+ no-hw - No hw
++ no-hw-pkcs11ca - No hw PKCS#11 CA flavor
++ no-hw-pkcs11so - No hw PKCS#11 SO flavor
+ nasm - Use NASM for x86 asm
+ nw-nasm - Use NASM x86 asm for NetWare
+ nw-mwasm - Use Metrowerks x86 asm for NetWare
+@@ -278,6 +280,8 @@
+ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost;
+ $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine;
+ $cflags.=" -DOPENSSL_NO_HW" if $no_hw;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so;
+ $cflags.=" -DOPENSSL_FIPS" if $fips;
+ $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake;
+ $cflags.=" -DOPENSSL_NO_EC2M" if $no_ec2m;
+@@ -347,6 +351,9 @@
+ $dir=$val;
+ }
+
++ if ($key eq "PK11_LIB_LOCATION")
++ { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";}
++
+ if ($key eq "KRB5_INCLUDES")
+ { $cflags .= " $val";}
+
+@@ -1136,6 +1143,8 @@
+ "no-gost" => \$no_gost,
+ "no-engine" => \$no_engine,
+ "no-hw" => \$no_hw,
++ "no-hw-pkcs11ca" => \$no_hw_pkcs11ca,
++ "no-hw-pkcs11so" => \$no_hw_pkcs11so,
+ "no-rsax" => 0,
+ "just-ssl" =>
+ [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast,
+Index: openssl/util/mkdef.pl
+diff -u openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.6.1 openssl/util/mkdef.pl:1.12
+--- openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.6.1 Mon Jun 13 15:11:05 2016
++++ openssl/util/mkdef.pl Mon Jun 13 15:21:08 2016
+@@ -96,7 +96,7 @@
+ # External "algorithms"
+ "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM",
+ # Engines
+- "STATIC_ENGINE", "ENGINE", "HW", "GMP",
++ "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO",
+ # RFC3779
+ "RFC3779",
+ # TLS
+@@ -141,6 +141,7 @@
+ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
+ my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
+ my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw;
++my $no_pkcs11ca; my $no_pkcs11so;
+ my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
+ my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
+ my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc;
+@@ -248,6 +249,8 @@
+ elsif (/^no-sctp$/) { $no_sctp=1; }
+ elsif (/^no-srtp$/) { $no_srtp=1; }
+ elsif (/^no-unit-test$/){ $no_unit_test=1; }
++ elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; }
++ elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; }
+ }
+
+
+@@ -1202,6 +1205,8 @@
+ if ($keyword eq "KRB5" && $no_krb5) { return 0; }
+ if ($keyword eq "ENGINE" && $no_engine) { return 0; }
+ if ($keyword eq "HW" && $no_hw) { return 0; }
++ if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; }
++ if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; }
+ if ($keyword eq "FP_API" && $no_fp_api) { return 0; }
+ if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; }
+ if ($keyword eq "GMP" && $no_gmp) { return 0; }
+Index: openssl/util/pl/VC-32.pl
+diff -u openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.10.1.2.1 openssl/util/pl/VC-32.pl:1.12
+--- openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.10.1.2.1 Mon Jun 13 15:11:05 2016
++++ openssl/util/pl/VC-32.pl Mon Jun 13 15:21:08 2016
+@@ -48,7 +48,7 @@
+ my $f = $shlib || $fips ?' /MD':' /MT';
+ $lib_cflag='/Zl' if (!$shlib); # remove /DEFAULTLIBs from static lib
+ $opt_cflags=$f.' /Ox';
+- $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG';
++ $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG';
+ $lflags="/nologo /subsystem:console /opt:ref";
+
+ *::perlasm_compile_target = sub {
diff --git a/bin/pkcs11/openssl-1.0.2h-patch b/bin/pkcs11/openssl-1.0.2h-patch
new file mode 100644
index 0000000..f3a55fd
--- /dev/null
+++ b/bin/pkcs11/openssl-1.0.2h-patch
@@ -0,0 +1,15818 @@
+Index: openssl/Configure
+diff -u openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.2.1.2.1.2.1 openssl/Configure:1.17.2.3
+--- openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.2.1.2.1.2.1 Mon Jun 13 15:41:03 2016
++++ openssl/Configure Mon Jun 13 15:51:06 2016
+@@ -10,7 +10,7 @@
+
+ # see INSTALL for instructions.
+
+-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
++my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+
+ # Options:
+ #
+@@ -23,6 +23,12 @@
+ # default). This needn't be set in advance, you can
+ # just as well use "make INSTALL_PREFIX=/whatever install".
+ #
++# --pk11-libname PKCS#11 library name.
++# (No default)
++#
++# --pk11-flavor either crypto-accelerator or sign-only
++# (No default)
++#
+ # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected
+ # to live in the subdirectory lib/ and the header files in
+ # include/. A value is required.
+@@ -402,31 +408,30 @@
+ #
+ # ./Configure linux-armv4 -march=armv6 -D__ARM_MAX_ARCH__=8
+ #
+-"linux-armv4", "gcc: -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-aarch64","gcc: -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-armv4", "gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-aarch64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ # Configure script adds minimally required -march for assembly support,
+ # if no -march was specified at command line. mips32 and mips64 below
+ # refer to contemporary MIPS Architecture specifications, MIPS32 and
+ # MIPS64, rather than to kernel bitness.
+-"linux-mips32", "gcc:-mabi=32 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-mips64", "gcc:-mabi=n32 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:n32:dlfcn:linux-shared:-fPIC:-mabi=n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::32",
+-"linux64-mips64", "gcc:-mabi=64 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:64:dlfcn:linux-shared:-fPIC:-mabi=64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-mips32", "gcc:-mabi=32 -DTERMIO -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-mips64", "gcc:-mabi=n32 -DTERMIO -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:n32:dlfcn:linux-shared:-fPIC:-mabi=n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::32",
++"linux64-mips64", "gcc:-mabi=64 -DTERMIO -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:64:dlfcn:linux-shared:-fPIC:-mabi=64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ #### IA-32 targets...
+-"linux-ia32-icc", "icc:-DL_ENDIAN -O2::-D_REENTRANT::-ldl -no_cpprt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-elf", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-aout", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out",
++"linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2::-D_REENTRANT::-ldl -no_cpprt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out",
+ ####
+-"linux-generic64","gcc:-O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ppc64", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-ppc64le","gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:$ppc64_asm:linux64le:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::",
++"linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-ppc64", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-ppc64le","gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:$ppc64_asm:linux64le:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::",
+ "linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ia64-icc","icc:-DL_ENDIAN -O2 -Wall::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-x86_64", "gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-x86_64-clang", "clang: -m64 -DL_ENDIAN -O3 -Wall -Wextra $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"debug-linux-x86_64-clang", "clang: -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -m64 -DL_ENDIAN -g -Wall -Wextra $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-x86_64-icc", "icc:-DL_ENDIAN -O2::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-x32", "gcc:-mx32 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-mx32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::x32",
+-"linux64-s390x", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-x86_64-clang", "clang: -m64 -DL_ENDIAN -DTERMIO -O3 -Weverything $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-x86_64-icc", "icc:-DL_ENDIAN -DTERMIO -O2::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-x32", "gcc:-mx32 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-mx32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::x32",
++"linux64-s390x", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ #### So called "highgprs" target for z/Architecture CPUs
+ # "Highgprs" is kernel feature first implemented in Linux 2.6.32, see
+ # /proc/cpuinfo. The idea is to preserve most significant bits of
+@@ -724,6 +729,10 @@
+ my $idx_arflags = $idx++;
+ my $idx_multilib = $idx++;
+
++# PKCS#11 engine patch
++my $pk11_libname="";
++my $pk11_flavor="";
++
+ my $prefix="";
+ my $libdir="";
+ my $openssldir="";
+@@ -944,7 +953,15 @@
+ }
+ elsif (/^[-+]/)
+ {
+- if (/^--prefix=(.*)$/)
++ if (/^--pk11-libname=(.*)$/)
++ {
++ $pk11_libname=$1;
++ }
++ elsif (/^--pk11-flavor=(.*)$/)
++ {
++ $pk11_flavor=$1;
++ }
++ elsif (/^--prefix=(.*)$/)
+ {
+ $prefix=$1;
+ }
+@@ -1115,6 +1132,22 @@
+ exit 0;
+ }
+
++if (! $pk11_libname)
++ {
++ print STDERR "You must set --pk11-libname for PKCS#11 library.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
++if (! $pk11_flavor
++ || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only"))
++ {
++ print STDERR "You must set --pk11-flavor.\n";
++ print STDERR "Choices are crypto-accelerator and sign-only.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
+ if ($target =~ m/^CygWin32(-.*)$/) {
+ $target = "Cygwin".$1;
+ }
+@@ -1192,6 +1225,25 @@
+ $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO";
+ }
+
++if ($pk11_flavor eq "crypto-accelerator")
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11SO";
++ $options .= " no-hw-pkcs11so";
++ print " no-hw-pkcs11so [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11SO\n";
++ }
++else
++ {
++ $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n";
++ $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $depflags .= " -DOPENSSL_NO_HW_PKCS11CA";
++ $options .= " no-hw-pkcs11ca";
++ print " no-hw-pkcs11ca [pk11-flavor]";
++ print " OPENSSL_NO_HW_PKCS11CA\n";
++}
++
+ my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds;
+
+ $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target =~ /^mingw/);
+@@ -1289,6 +1341,8 @@
+ if ($flags ne "") { $cflags="$flags$cflags"; }
+ else { $no_user_cflags=1; }
+
++$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags";
++
+ # Kerberos settings. The flavor must be provided from outside, either through
+ # the script "config" or manually.
+ if (!$no_krb5)
+@@ -1698,6 +1752,7 @@
+ s/^VERSION=.*/VERSION=$version/;
+ s/^MAJOR=.*/MAJOR=$major/;
+ s/^MINOR=.*/MINOR=$minor/;
++ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/;
+ s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/;
+ s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/;
+ s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/;
+Index: openssl/Makefile.org
+diff -u openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.8.1.2.1.2.1 openssl/Makefile.org:1.10.2.3
+--- openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.8.1.2.1.2.1 Mon Jun 13 15:41:03 2016
++++ openssl/Makefile.org Mon Jun 13 15:51:08 2016
+@@ -26,6 +26,9 @@
+ INSTALL_PREFIX=
+ INSTALLTOP=/usr/local/ssl
+
++# You must set this through --pk11-libname configure option.
++PK11_LIB_LOCATION=
++
+ # Do not edit this manually. Use Configure --openssldir=DIR do change this!
+ OPENSSLDIR=/usr/local/ssl
+
+Index: openssl/README.pkcs11
+diff -u /dev/null openssl/README.pkcs11:1.8
+--- /dev/null Mon Jun 13 15:55:24 2016
++++ openssl/README.pkcs11 Fri Oct 4 14:16:43 2013
+@@ -0,0 +1,266 @@
++ISC modified
++============
++
++The previous key naming scheme was kept for backward compatibility.
++
++The PKCS#11 engine exists in two flavors, crypto-accelerator and
++sign-only. The first one is from the Solaris patch and uses the
++PKCS#11 device for all crypto operations it supports. The second
++is a stripped down version which provides only the useful
++function (i.e., signature with a RSA private key in the device
++protected key store and key loading).
++
++As a hint PKCS#11 boards should use the crypto-accelerator flavor,
++external PKCS#11 devices the sign-only. SCA 6000 is an example
++of the first, AEP Keyper of the second.
++
++Note it is mandatory to set a pk11-flavor (and only one) in
++config/Configure.
++
++It is highly recommended to compile in (vs. as a DSO) the engine.
++The way to configure this is system dependent, on Unixes it is no-shared
++(and is in general the default), on WIN32 it is enable-static-engine
++(and still enable to build the OpenSSL libraries as DLLs).
++
++PKCS#11 engine support for OpenSSL 0.9.8l
++=========================================
++
++[Nov 19, 2009]
++
++Contents:
++
++Overview
++Revisions of the patch for 0.9.8 branch
++FAQs
++Feedback
++
++Overview
++========
++
++This patch containing code available in OpenSolaris adds support for PKCS#11
++engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against
++OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system
++must provide PKCS#11 backend otherwise the patch is useless. You provide the
++PKCS#11 library name during the build configuration phase, see below.
++
++Patch can be applied like this:
++
++ # NOTE: use gtar if on Solaris
++ tar xfzv openssl-0.9.8l.tar.gz
++ # now download the patch to the current directory
++ # ...
++ cd openssl-0.9.8l
++ # NOTE: must use gpatch if on Solaris (is part of the system)
++ patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19
++
++It is designed to support pure acceleration for RSA, DSA, DH and all the
++symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share
++except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA.
++
++According to the PKCS#11 providers installed on your machine, it can support
++following mechanisms:
++
++ RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4,
++ AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB,
++ AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224,
++ SHA256, SHA384, SHA512
++
++Note that for AES counter mode the application must provide their own EVP
++functions since OpenSSL doesn't support counter mode through EVP yet. You may
++see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an
++example of code that uses the PKCS#11 engine and deals with the fork-safety
++problem (see engine.c and packet.c files if interested).
++
++You must provide the location of PKCS#11 library in your system to the
++configure script. You will be instructed to do that when you try to run the
++config script:
++
++ $ ./config
++ Operating system: i86pc-whatever-solaris2
++ Configuring for solaris-x86-cc
++ You must set --pk11-libname for PKCS#11 library.
++ See README.pkcs11 for more information.
++
++Taking openCryptoki project on Linux AMD64 box as an example, you would run
++configure script like this:
++
++ ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so
++
++To check whether newly built openssl really supports PKCS#11 it's enough to run
++"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the
++output. If you see no PKCS#11 engine support check that the built openssl binary
++and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits.
++
++The patch, during various phases of development, was tested on Solaris against
++PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and
++OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project
++(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more
++information). Some Linux distributions even ship those libraries with the
++system. The patch should work on any system that is supported by OpenSSL itself
++and has functional PKCS#11 library.
++
++The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are
++copyrighted by RSA Security Inc., see pkcs11.h for more information.
++
++Other added/modified code in this patch is copyrighted by Sun Microsystems,
++Inc. and is released under the OpenSSL license (see LICENSE file for more
++information).
++
++Revisions of the patch for 0.9.8 branch
++=======================================
++
++2009-11-19
++- adjusted for OpenSSL version 0.9.8l
++
++- bugs and RFEs:
++
++ 6479874 OpenSSL should support RSA key by reference/hardware keystores
++ 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split
++ 6732677 make check to trigger Solaris specific code automatic in the
++ PKCS#11 engine
++
++2009-03-11
++- adjusted for OpenSSL version 0.9.8j
++
++- README.pkcs11 moved out of the patch, and is shipped together with it in a
++ tarball instead so that it can be read before the patch is applied.
++
++- fixed bugs:
++
++ 6804216 pkcs#11 engine should support a key length range for RC4
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-12-02
++- fixed bugs and RFEs (most of the work done by Vladimir Kotal)
++
++ 6723504 more granular locking in PKCS#11 engine
++ 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true
++ 6710420 PKCS#11 engine source should be lint clean
++ 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take
++ it seriously
++ 6746712 PKCS#11 engine source code should be cstyle clean
++ 6731380 return codes of several functions are not checked in the PKCS#11
++ engine code
++ 6746735 PKCS#11 engine should use extended FILE space API
++ 6734038 Apache SSL web server using the pkcs11 engine fails to start if
++ meta slot is disabled
++
++2008-08-01
++- fixed bug
++
++ 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers
++ and digests
++
++- Solaris specific code for slot selection made automatic
++
++2008-07-29
++- update the patch to OpenSSL 0.9.8h version
++- pkcs11t.h updated to the latest version:
++
++ 6545665 make CKM_AES_CTR available to non-kernel users
++
++- fixed bugs in the engine code:
++
++ 6602801 PK11_SESSION cache has to employ reference counting scheme for
++ asymmetric key operations
++ 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called
++ atomically
++ 6607307 pkcs#11 engine can't read RSA private keys
++ 6652362 pk11_RSA_finish() is cutting corners
++ 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in
++ suboptimal way
++ 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more
++ resilient to destroy failures
++ 6667273 OpenSSL engine should not use free() but OPENSSL_free()
++ 6670363 PKCS#11 engine fails to reuse existing symmetric keys
++ 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine
++ 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size
++ of big numbers leading to failures
++ 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of
++ -1
++ 6706622 pk11_load_{pub,priv}key create corrupted RSA key references
++ 6707129 return values from BN_new() in pk11_DH_generate_key() are not
++ checked
++ 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to
++ structure reuse
++ 6707782 OpenSSL PKCS#11 engine pretends to be aware of
++ OPENSSL_NO_{RSA,DSA,DH}
++ defines but fails miserably
++ 6709966 make check_new_*() to return values to indicate cache hit/miss
++ 6705200 pk11_dh struct initialization in PKCS#11 engine is missing
++ generate_params parameter
++ 6709513 PKCS#11 engine sets IV length even for ECB modes
++ 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the
++ PKCS#11 engine
++ 6728871 PKCS#11 engine must reset global_session in pk11_finish()
++
++- new features and enhancements:
++
++ 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512
++ 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes
++ 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric
++ ciphers and digests
++
++2007-10-15
++- update for 0.9.8f version
++- update for "6607670 teach pkcs#11 engine how to use keys be reference"
++
++2007-10-02
++- draft for "6607670 teach pkcs#11 engine how to use keys be reference"
++- draft for "6607307 pkcs#11 engine can't read RSA private keys"
++
++2007-09-26
++- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes
++ significant performance drop
++- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine
++
++2007-05-25
++- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers
++
++2007-05-19
++- initial patch for 0.9.8e using latest OpenSolaris code
++
++FAQs
++====
++
++(1) my build failed on Linux distro with this error:
++
++../libcrypto.a(hw_pk11.o): In function `pk11_library_init':
++hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork'
++
++Answer:
++
++ - don't use "no-threads" when configuring
++ - if you didn't then OpenSSL failed to create a threaded library by
++ default. You may manually edit Configure and try again. Look for the
++ architecture that Configure printed, for example:
++
++Configured for linux-elf.
++
++ - then edit Configure, find string "linux-elf" (inluding the quotes),
++ and add flags to support threads to the 4th column of the 2nd string.
++ If you build with GCC then adding "-pthread" should be enough. With
++ "linux-elf" as an example, you would add " -pthread" right after
++ "-D_REENTRANT", like this:
++
++....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:.....
++
++(2) I'm using MinGW/MSYS environment and get undeclared reference error for
++pthread_atfork() function when trying to build OpenSSL with the patch.
++
++Answer:
++
++ Sorry, pthread_atfork() is not implemented in the current pthread-win32
++ (as of Nov 2009). You can not use the patch there.
++
++
++Feedback
++========
++
++Please send feedback to security-discuss@opensolaris.org. The patch was
++created by Jan.Pechanec@Sun.COM from code available in OpenSolaris.
++
++Latest version should be always available on http://blogs.sun.com/janp.
++
+Index: openssl/crypto/opensslconf.h
+diff -u openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.4.1.2.1.2.1 openssl/crypto/opensslconf.h:1.8.2.3
+--- openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.4.1.2.1.2.1 Mon Jun 13 15:41:06 2016
++++ openssl/crypto/opensslconf.h Mon Jun 13 15:51:23 2016
+@@ -53,6 +53,9 @@
+
+ #endif /* OPENSSL_DOING_MAKEDEPEND */
+
++#ifndef OPENSSL_THREADS
++# define OPENSSL_THREADS
++#endif
+ #ifndef OPENSSL_NO_DYNAMIC_ENGINE
+ # define OPENSSL_NO_DYNAMIC_ENGINE
+ #endif
+@@ -106,6 +109,8 @@
+ # endif
+ #endif
+
++#define OPENSSL_CPUID_OBJ
++
+ /* crypto/opensslconf.h.in */
+
+ /* Generate 80386 code? */
+@@ -152,7 +157,7 @@
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+-#undef RC4_CHUNK
++#define RC4_CHUNK unsigned long
+ #endif
+ #endif
+
+@@ -160,7 +165,7 @@
+ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+ #ifndef DES_LONG
+-#define DES_LONG unsigned long
++#define DES_LONG unsigned int
+ #endif
+ #endif
+
+@@ -171,9 +176,9 @@
+ /* Should we define BN_DIV2W here? */
+
+ /* Only one for the following should be defined */
+-#undef SIXTY_FOUR_BIT_LONG
++#define SIXTY_FOUR_BIT_LONG
+ #undef SIXTY_FOUR_BIT
+-#define THIRTY_TWO_BIT
++#undef THIRTY_TWO_BIT
+ #endif
+
+ #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+@@ -185,7 +190,7 @@
+
+ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+ #define CONFIG_HEADER_BF_LOCL_H
+-#undef BF_PTR
++#define BF_PTR2
+ #endif /* HEADER_BF_LOCL_H */
+
+ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+@@ -215,7 +220,7 @@
+ /* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+ #ifndef DES_UNROLL
+-#undef DES_UNROLL
++#define DES_UNROLL
+ #endif
+
+ /* These default values were supplied by
+Index: openssl/crypto/bio/bss_file.c
+diff -u openssl/crypto/bio/bss_file.c:1.6.2.1.28.1.2.1 openssl/crypto/bio/bss_file.c:1.6.10.2
+--- openssl/crypto/bio/bss_file.c:1.6.2.1.28.1.2.1 Wed Dec 23 18:55:13 2015
++++ openssl/crypto/bio/bss_file.c Wed Dec 23 19:28:46 2015
+@@ -174,7 +174,7 @@
+ if (file == NULL) {
+ SYSerr(SYS_F_FOPEN, get_last_sys_error());
+ ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
+- if (errno == ENOENT)
++ if ((errno == ENOENT) || ((*mode == 'r') && (errno == EACCES)))
+ BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
+ else
+ BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
+Index: openssl/crypto/engine/Makefile
+diff -u openssl/crypto/engine/Makefile:1.8.2.1.4.1.14.1.2.1 openssl/crypto/engine/Makefile:1.9.6.2
+--- openssl/crypto/engine/Makefile:1.8.2.1.4.1.14.1.2.1 Wed Dec 23 18:55:22 2015
++++ openssl/crypto/engine/Makefile Wed Dec 23 19:28:56 2015
+@@ -22,13 +22,15 @@
+ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \
+ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \
+ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \
+- eng_rdrand.c
++ eng_rdrand.c \
++ hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c
+ LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
+ eng_table.o eng_pkey.o eng_fat.o eng_all.o \
+ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \
+ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \
+ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \
+- eng_rdrand.o
++ eng_rdrand.o \
++ hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o
+
+ SRC= $(LIBSRC)
+
+@@ -282,6 +284,83 @@
+ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+ eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+ eng_table.o: eng_table.c
++hw_pk11.o: ../../e_os.h ../../include/openssl/aes.h
++hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
++hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h
++hw_pk11.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h
++hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
++hw_pk11.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
++hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/err.h
++hw_pk11.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
++hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/obj_mac.h
++hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
++hw_pk11.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
++hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
++hw_pk11.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
++hw_pk11.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
++hw_pk11.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
++hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
++hw_pk11.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h hw_pk11.c
++hw_pk11.o: hw_pk11_err.c hw_pk11_err.h hw_pk11ca.h pkcs11.h pkcs11f.h pkcs11t.h
++hw_pk11_pub.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
++hw_pk11_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
++hw_pk11_pub.o: ../../include/openssl/objects.h
++hw_pk11_pub.o: ../../include/openssl/opensslconf.h
++hw_pk11_pub.o: ../../include/openssl/opensslv.h
++hw_pk11_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
++hw_pk11_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
++hw_pk11_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
++hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
++hw_pk11_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
++hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
++hw_pk11_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11_pub.c hw_pk11ca.h
++hw_pk11_pub.o: pkcs11.h pkcs11f.h pkcs11t.h
++hw_pk11so.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11so.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11so.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11so.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11so.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11so.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11so.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/md5.h
++hw_pk11so.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
++hw_pk11so.o: ../../include/openssl/opensslconf.h
++hw_pk11so.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
++hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
++hw_pk11so.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
++hw_pk11so.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
++hw_pk11so.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
++hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
++hw_pk11so.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h
++hw_pk11so.o: hw_pk11_err.c hw_pk11_err.h hw_pk11so.c hw_pk11so.h pkcs11.h
++hw_pk11so.o: pkcs11f.h pkcs11t.h
++hw_pk11so_pub.o: ../../e_os.h ../../include/openssl/asn1.h
++hw_pk11so_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
++hw_pk11so_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
++hw_pk11so_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
++hw_pk11so_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
++hw_pk11so_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
++hw_pk11so_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h
++hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
++hw_pk11so_pub.o: ../../include/openssl/objects.h
++hw_pk11so_pub.o: ../../include/openssl/opensslconf.h
++hw_pk11so_pub.o: ../../include/openssl/opensslv.h
++hw_pk11so_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
++hw_pk11so_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
++hw_pk11so_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
++hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
++hw_pk11so_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
++hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
++hw_pk11so_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11so.h
++hw_pk11so_pub.o: hw_pk11so_pub.c pkcs11.h pkcs11f.h pkcs11t.h
+ tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h
+ tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+ tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+Index: openssl/crypto/engine/cryptoki.h
+diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4
+--- /dev/null Mon Jun 13 15:55:25 2016
++++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008
+@@ -0,0 +1,103 @@
++/*
++ * CDDL HEADER START
++ *
++ * The contents of this file are subject to the terms of the
++ * Common Development and Distribution License, Version 1.0 only
++ * (the "License"). You may not use this file except in compliance
++ * with the License.
++ *
++ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
++ * or http://www.opensolaris.org/os/licensing.
++ * See the License for the specific language governing permissions
++ * and limitations under the License.
++ *
++ * When distributing Covered Code, include this CDDL HEADER in each
++ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
++ * If applicable, add the following below this CDDL HEADER, with the
++ * fields enclosed by brackets "[]" replaced with your own identifying
++ * information: Portions Copyright [yyyy] [name of copyright owner]
++ *
++ * CDDL HEADER END
++ */
++/*
++ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _CRYPTOKI_H
++#define _CRYPTOKI_H
++
++/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef CK_PTR
++#define CK_PTR *
++#endif
++
++#ifndef CK_DEFINE_FUNCTION
++#define CK_DEFINE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION
++#define CK_DECLARE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION_POINTER
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
++#endif
++
++#ifndef CK_CALLBACK_FUNCTION
++#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
++#endif
++
++#ifndef NULL_PTR
++#include <unistd.h> /* For NULL */
++#define NULL_PTR NULL
++#endif
++
++/*
++ * pkcs11t.h defines TRUE and FALSE in a way that upsets lint
++ */
++#ifndef CK_DISABLE_TRUE_FALSE
++#define CK_DISABLE_TRUE_FALSE
++#ifndef TRUE
++#define TRUE 1
++#endif /* TRUE */
++#ifndef FALSE
++#define FALSE 0
++#endif /* FALSE */
++#endif /* CK_DISABLE_TRUE_FALSE */
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++#include "pkcs11.h"
++
++/* Solaris specific functions */
++
++#include <stdlib.h>
++
++/*
++ * SUNW_C_GetMechSession will initialize the framework and do all
++ * the necessary PKCS#11 calls to create a session capable of
++ * providing operations on the requested mechanism
++ */
++CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech,
++ CK_SESSION_HANDLE_PTR hSession);
++
++/*
++ * SUNW_C_KeyToObject will create a secret key object for the given
++ * mechanism from the rawkey data.
++ */
++CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len,
++ CK_OBJECT_HANDLE_PTR obj);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _CRYPTOKI_H */
+Index: openssl/crypto/engine/eng_all.c
+diff -u openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.14.1.4.1 openssl/crypto/engine/eng_all.c:1.6.6.2
+--- openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.14.1.4.1 Mon Jun 13 15:41:32 2016
++++ openssl/crypto/engine/eng_all.c Mon Jun 13 15:51:59 2016
+@@ -119,6 +119,14 @@
+ # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
+ ENGINE_load_capi();
+ # endif
++#ifndef OPENSSL_NO_HW_PKCS11
++#ifndef OPENSSL_NO_HW_PKCS11CA
++ ENGINE_load_pk11ca();
++#endif
++#ifndef OPENSSL_NO_HW_PKCS11SO
++ ENGINE_load_pk11so();
++#endif
++#endif
+ #endif
+ ENGINE_register_all_complete();
+ }
+Index: openssl/crypto/engine/engine.h
+diff -u openssl/crypto/engine/engine.h:1.5.2.1.4.1.14.1 openssl/crypto/engine/engine.h:1.6.6.1
+--- openssl/crypto/engine/engine.h:1.5.2.1.4.1.14.1 Wed Mar 4 14:43:55 2015
++++ openssl/crypto/engine/engine.h Wed Mar 4 15:22:32 2015
+@@ -405,6 +405,12 @@
+ void ENGINE_load_ubsec(void);
+ void ENGINE_load_padlock(void);
+ void ENGINE_load_capi(void);
++#ifndef OPENSSL_NO_HW_PKCS11CA
++void ENGINE_load_pk11ca(void);
++#endif
++#ifndef OPENSSL_NO_HW_PKCS11SO
++void ENGINE_load_pk11so(void);
++#endif
+ # ifndef OPENSSL_NO_GMP
+ void ENGINE_load_gmp(void);
+ # endif
+Index: openssl/crypto/engine/hw_pk11.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.33
+--- /dev/null Mon Jun 13 15:55:25 2016
++++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:07:41 2013
+@@ -0,0 +1,4010 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++#include <openssl/aes.h>
++#include <openssl/des.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/* #undef DEBUG_SLOT_SELECTION */
++/*
++ * Solaris specific code. See comment at check_hw_mechanisms() for more
++ * information.
++ */
++#if defined(__SVR4) && defined(__sun)
++#undef SOLARIS_HW_SLOT_SELECTION
++#endif
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.c"
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel
++ * library. See comment at check_hw_mechanisms() for more information.
++ */
++static int *hw_cnids;
++static int *hw_dnids;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++#ifndef OPENSSL_NO_RSA
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DSA
++int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++#endif
++#ifndef OPENSSL_NO_DH
++int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock);
++#endif
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++/* Symmetric cipher and digest support functions */
++static int cipher_nid_to_pk11(int nid);
++static int pk11_usable_ciphers(const int **nids);
++static int pk11_usable_digests(const int **nids);
++static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc);
++static int pk11_cipher_final(PK11_SESSION *sp);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl);
++#else
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl);
++#endif
++static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx);
++static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid);
++static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid);
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp);
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len);
++static int md_nid_to_pk11(int nid);
++static int pk11_digest_init(EVP_MD_CTX *ctx);
++static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data,
++ size_t count);
++static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md);
++static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from);
++static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
++
++static int pk11_choose_slots(int *any_slot_found);
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher,
++ int *local_cipher_nids);
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest,
++ int *local_digest_nids);
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids,
++ int id);
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++static int check_hw_mechanisms(void);
++static int nid_in_table(int nid, int *nid_table);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++/* Index for the supported ciphers */
++enum pk11_cipher_id {
++ PK11_DES_CBC,
++ PK11_DES3_CBC,
++ PK11_DES_ECB,
++ PK11_DES3_ECB,
++ PK11_RC4,
++ PK11_AES_128_CBC,
++ PK11_AES_192_CBC,
++ PK11_AES_256_CBC,
++ PK11_AES_128_ECB,
++ PK11_AES_192_ECB,
++ PK11_AES_256_ECB,
++ PK11_AES_128_CTR,
++ PK11_AES_192_CTR,
++ PK11_AES_256_CTR,
++ PK11_BLOWFISH_CBC,
++ PK11_CIPHER_MAX
++};
++
++/* Index for the supported digests */
++enum pk11_digest_id {
++ PK11_MD5,
++ PK11_SHA1,
++ PK11_SHA224,
++ PK11_SHA256,
++ PK11_SHA384,
++ PK11_SHA512,
++ PK11_DIGEST_MAX
++};
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static int cipher_nids[PK11_CIPHER_MAX];
++static int digest_nids[PK11_DIGEST_MAX];
++static int cipher_count = 0;
++static int digest_count = 0;
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_recover = CK_FALSE;
++static CK_BBOOL pk11_have_dsa = CK_FALSE;
++static CK_BBOOL pk11_have_dh = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++typedef struct PK11_CIPHER_st
++ {
++ enum pk11_cipher_id id;
++ int nid;
++ int iv_len;
++ int min_key_len;
++ int max_key_len;
++ CK_KEY_TYPE key_type;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_CIPHER;
++
++static PK11_CIPHER ciphers[] =
++ {
++ { PK11_DES_CBC, NID_des_cbc, 8, 8, 8,
++ CKK_DES, CKM_DES_CBC, },
++ { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24,
++ CKK_DES3, CKM_DES3_CBC, },
++ { PK11_DES_ECB, NID_des_ecb, 0, 8, 8,
++ CKK_DES, CKM_DES_ECB, },
++ { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24,
++ CKK_DES3, CKM_DES3_ECB, },
++ { PK11_RC4, NID_rc4, 0, 16, 256,
++ CKK_RC4, CKM_RC4, },
++ { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32,
++ CKK_AES, CKM_AES_CBC, },
++ { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32,
++ CKK_AES, CKM_AES_ECB, },
++ { PK11_AES_128_CTR, NID_aes_128_ctr, 16, 16, 16,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_192_CTR, NID_aes_192_ctr, 16, 24, 24,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_AES_256_CTR, NID_aes_256_ctr, 16, 32, 32,
++ CKK_AES, CKM_AES_CTR, },
++ { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16,
++ CKK_BLOWFISH, CKM_BLOWFISH_CBC, },
++ };
++
++typedef struct PK11_DIGEST_st
++ {
++ enum pk11_digest_id id;
++ int nid;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_DIGEST;
++
++static PK11_DIGEST digests[] =
++ {
++ {PK11_MD5, NID_md5, CKM_MD5, },
++ {PK11_SHA1, NID_sha1, CKM_SHA_1, },
++ {PK11_SHA224, NID_sha224, CKM_SHA224, },
++ {PK11_SHA256, NID_sha256, CKM_SHA256, },
++ {PK11_SHA384, NID_sha384, CKM_SHA384, },
++ {PK11_SHA512, NID_sha512, CKM_SHA512, },
++ {0, NID_undef, 0xFFFF, },
++ };
++
++/*
++ * Structure to be used for the cipher_data/md_data in
++ * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11
++ * session in multiple cipher_update calls
++ */
++typedef struct PK11_CIPHER_STATE_st
++ {
++ PK11_SESSION *sp;
++ } PK11_CIPHER_STATE;
++
++
++/*
++ * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets
++ * called when libcrypto requests a cipher NID.
++ *
++ * Note how the PK11_CIPHER_STATE is used here.
++ */
++
++/* DES CBC EVP */
++static const EVP_CIPHER pk11_des_cbc =
++ {
++ NID_des_cbc,
++ 8, 8, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/* 3DES CBC EVP */
++static const EVP_CIPHER pk11_3des_cbc =
++ {
++ NID_des_ede3_cbc,
++ 8, 24, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and
++ * get_asn1_parameters fields are set to NULL.
++ */
++static const EVP_CIPHER pk11_des_ecb =
++ {
++ NID_des_ecb,
++ 8, 8, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_3des_ecb =
++ {
++ NID_des_ede3_ecb,
++ 8, 24, 8,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++
++static const EVP_CIPHER pk11_aes_128_cbc =
++ {
++ NID_aes_128_cbc,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_cbc =
++ {
++ NID_aes_192_cbc,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_cbc =
++ {
++ NID_aes_256_cbc,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/*
++ * ECB modes don't use IV so that's why set_asn1_parameters and
++ * get_asn1_parameters are set to NULL.
++ */
++static const EVP_CIPHER pk11_aes_128_ecb =
++ {
++ NID_aes_128_ecb,
++ 16, 16, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_ecb =
++ {
++ NID_aes_192_ecb,
++ 16, 24, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_ecb =
++ {
++ NID_aes_256_ecb,
++ 16, 32, 0,
++ EVP_CIPH_ECB_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_128_ctr =
++ {
++ NID_aes_128_ctr,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_192_ctr =
++ {
++ NID_aes_192_ctr,
++ 16, 24, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_256_ctr =
++ {
++ NID_aes_256_ctr,
++ 16, 32, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_bf_cbc =
++ {
++ NID_bf_cbc,
++ 8, 16, 8,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_rc4 =
++ {
++ NID_rc4,
++ 1, 16, 0,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof (PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_MD pk11_md5 =
++ {
++ NID_md5,
++ NID_md5WithRSAEncryption,
++ MD5_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ MD5_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha1 =
++ {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha224 =
++ {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-224 uses the same cblock size as SHA-256 */
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha256 =
++ {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA256_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha384 =
++ {
++ NID_sha384,
++ NID_sha384WithRSAEncryption,
++ SHA384_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ /* SHA-384 uses the same cblock size as SHA-512 */
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha512 =
++ {
++ NID_sha512,
++ NID_sha512WithRSAEncryption,
++ SHA512_DIGEST_LENGTH,
++ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA512_CBLOCK,
++ sizeof (PK11_CIPHER_STATE),
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11SO
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name =
++ "PKCS #11 engine support (crypto accelerator)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++#ifndef OPENSSL_NO_RSA
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DSA], &attr);
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_DH] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_DH], &attr);
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++#ifndef OPENSSL_NO_RSA
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (find_lock[OP_DSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DSA]);
++ OPENSSL_free(find_lock[OP_DSA]);
++ find_lock[OP_DSA] = NULL;
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (find_lock[OP_DH] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_DH]);
++ OPENSSL_free(find_lock[OP_DH]);
++ find_lock[OP_DH] = NULL;
++ }
++#endif /* OPENSSL_NO_DH */
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++#ifndef OPENSSL_NO_RSA
++ const RSA_METHOD *rsa = NULL;
++ RSA_METHOD *pk11_rsa = PK11_RSA();
++#endif /* OPENSSL_NO_RSA */
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name) ||
++ !ENGINE_set_ciphers(e, pk11_engine_ciphers) ||
++ !ENGINE_set_digests(e, pk11_engine_digests))
++ return (0);
++#ifndef OPENSSL_NO_RSA
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ if (pk11_have_dsa == CK_TRUE)
++ {
++ if (!ENGINE_set_DSA(e, PK11_DSA()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ if (pk11_have_dh == CK_TRUE)
++ {
++ if (!ENGINE_set_DH(e, PK11_DH()))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered DH\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif /* OPENSSL_NO_DH */
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++/*
++ * Apache calls OpenSSL function RSA_blinding_on() once during startup
++ * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp
++ * here, we wire it back to the OpenSSL software implementation.
++ * Since it is used only once, performance is not a concern.
++ */
++#ifndef OPENSSL_NO_RSA
++ rsa = RSA_PKCS1_SSLeay();
++ pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp;
++ pk11_rsa->bn_mod_exp = rsa->bn_mod_exp;
++ if (pk11_have_recover != CK_TRUE)
++ pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec;
++#endif /* OPENSSL_NO_RSA */
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ LOCK_OBJSTORE(OP_DSA);
++ LOCK_OBJSTORE(OP_DH);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_DH);
++ UNLOCK_OBJSTORE(OP_DSA);
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ CK_ULONG ul_state_len;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ /*
++ * Disable digest if C_GetOperationState is not supported since
++ * this function is required by OpenSSL digest copy function
++ */
++ /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */
++ if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len)
++ != CKR_OK) {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: C_GetOperationState() not supported, "
++ "setting digest_count to 0\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ digest_count = 0;
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ break;
++#endif
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ break;
++#endif
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (check_hw_mechanisms() == 0)
++ goto err;
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++#ifndef OPENSSL_NO_RSA
++ (void) pk11_destroy_rsa_key_objects(NULL);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ (void) pk11_destroy_dsa_key_objects(NULL);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ (void) pk11_destroy_dh_key_objects(NULL);
++#endif /* OPENSSL_NO_DH */
++ (void) pk11_destroy_cipher_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ case OP_DIGEST:
++ case OP_CIPHER:
++ myslot = SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ switch (optype)
++ {
++#ifndef OPENSSL_NO_RSA
++ case OP_RSA:
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ break;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ case OP_DSA:
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ sp->opdata_dsa_pub_num = NULL;
++ sp->opdata_dsa_priv = NULL;
++ sp->opdata_dsa_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ case OP_DH:
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ sp->opdata_dh_priv_num = NULL;
++ break;
++#endif /* OPENSSL_NO_DH */
++ case OP_CIPHER:
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ sp->opdata_encrypt = -1;
++ break;
++ default:
++ break;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++/* Destroy DSA public key from single session. */
++int
++pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key,
++ ret, uselock, OP_DSA, CK_FALSE);
++ sp->opdata_dsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_pub = NULL;
++ if (sp->opdata_dsa_pub_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_pub_num);
++ sp->opdata_dsa_pub_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy DSA private key from single session. */
++int
++pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key,
++ ret, uselock, OP_DSA, CK_TRUE);
++ sp->opdata_dsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_dsa_priv = NULL;
++ if (sp->opdata_dsa_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dsa_priv_num);
++ sp->opdata_dsa_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_dsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_dsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++/* Destroy DH key from single session. */
++int
++pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_dh_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_dh_key,
++ ret, uselock, OP_DH, CK_TRUE);
++ sp->opdata_dh_key = CK_INVALID_HANDLE;
++ sp->opdata_dh = NULL;
++ if (sp->opdata_dh_priv_num != NULL)
++ {
++ BN_free(sp->opdata_dh_priv_num);
++ sp->opdata_dh_priv_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy DH key object wrapper.
++ *
++ * arg0: pointer to PKCS#11 engine session structure
++ * if session is NULL, try to destroy all objects in the free list
++ */
++int
++pk11_destroy_dh_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_DH].head;
++ uselock = FALSE;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_dh_object(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++#endif /* OPENSSL_NO_DH */
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/* Symmetric ciphers and digests support functions */
++
++static int
++cipher_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; i++)
++ if (ciphers[i].nid == nid)
++ return (ciphers[i].id);
++ return (-1);
++ }
++
++static int
++pk11_usable_ciphers(const int **nids)
++ {
++ if (cipher_count > 0)
++ *nids = cipher_nids;
++ else
++ *nids = NULL;
++ return (cipher_count);
++ }
++
++static int
++pk11_usable_digests(const int **nids)
++ {
++ if (digest_count > 0)
++ *nids = digest_nids;
++ else
++ *nids = NULL;
++ return (digest_count);
++ }
++
++/*
++ * Init context for encryption or decryption using a symmetric key.
++ */
++static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher,
++ PK11_SESSION *sp, CK_MECHANISM_PTR pmech)
++ {
++ CK_RV rv;
++ CK_AES_CTR_PARAMS ctr_params;
++
++ /*
++ * We expect pmech->mechanism to be already set and
++ * pParameter/ulParameterLen initialized to NULL/0 before
++ * pk11_init_symetric() is called.
++ */
++ OPENSSL_assert(pmech->mechanism != 0);
++ OPENSSL_assert(pmech->pParameter == NULL);
++ OPENSSL_assert(pmech->ulParameterLen == 0);
++
++ if (ctx->cipher->nid == NID_aes_128_ctr ||
++ ctx->cipher->nid == NID_aes_192_ctr ||
++ ctx->cipher->nid == NID_aes_256_ctr)
++ {
++ pmech->pParameter = (void *)(&ctr_params);
++ pmech->ulParameterLen = sizeof (ctr_params);
++ /*
++ * For now, we are limited to the fixed length of the counter,
++ * it covers the whole counter block. That's what RFC 4344
++ * needs. For more information on internal structure of the
++ * counter block, see RFC 3686. If needed in the future, we can
++ * add code so that the counter length can be set via
++ * ENGINE_ctrl() function.
++ */
++ ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8;
++ OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE);
++ (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE);
++ }
++ else
++ {
++ if (pcipher->iv_len > 0)
++ {
++ pmech->pParameter = (void *)ctx->iv;
++ pmech->ulParameterLen = pcipher->iv_len;
++ }
++ }
++
++ /* if we get here, the encryption needs to be reinitialized */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++ else
++ rv = pFuncList->C_DecryptInit(sp->session, pmech,
++ sp->opdata_cipher_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ?
++ PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/* ARGSUSED */
++static int
++pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc)
++ {
++ CK_MECHANISM mech;
++ int index;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ PK11_CIPHER *p_ciph_table_row;
++
++ state->sp = NULL;
++
++ index = cipher_nid_to_pk11(ctx->cipher->nid);
++ if (index < 0 || index >= PK11_CIPHER_MAX)
++ return (0);
++
++ p_ciph_table_row = &ciphers[index];
++ /*
++ * iv_len in the ctx->cipher structure is the maximum IV length for the
++ * current cipher and it must be less or equal to the IV length in our
++ * ciphers table. The key length must be in the allowed interval. From
++ * all cipher modes that the PKCS#11 engine supports only RC4 allows a
++ * key length to be in some range, all other NIDs have a precise key
++ * length. Every application can define its own EVP functions so this
++ * code serves as a sanity check.
++ *
++ * Note that the reason why the IV length in ctx->cipher might be
++ * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs
++ * macro to define functions that return EVP structures for all DES
++ * modes. So, even ECB modes get 8 byte IV.
++ */
++ if (ctx->cipher->iv_len < p_ciph_table_row->iv_len ||
++ ctx->key_len < p_ciph_table_row->min_key_len ||
++ ctx->key_len > p_ciph_table_row->max_key_len) {
++ PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM);
++ return (0);
++ }
++
++ if ((sp = pk11_get_session(OP_CIPHER)) == NULL)
++ return (0);
++
++ /* if applicable, the mechanism parameter is used for IV */
++ mech.mechanism = p_ciph_table_row->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ /* The key object is destroyed here if it is not the current key. */
++ (void) check_new_cipher_key(sp, key, ctx->key_len);
++
++ /*
++ * If the key is the same and the encryption is also the same, then
++ * just reuse it. However, we must not forget to reinitialize the
++ * context that was finalized in pk11_cipher_cleanup().
++ */
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE &&
++ sp->opdata_encrypt == ctx->encrypt)
++ {
++ state->sp = sp;
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ return (1);
++ }
++
++ /*
++ * Check if the key has been invalidated. If so, a new key object
++ * needs to be created.
++ */
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ sp->opdata_cipher_key = pk11_get_cipher_key(
++ ctx, key, p_ciph_table_row->key_type, sp);
++ }
++
++ if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1)
++ {
++ /*
++ * The previous encryption/decryption is different. Need to
++ * terminate the previous * active encryption/decryption here.
++ */
++ if (!pk11_cipher_final(sp))
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++ }
++
++ if (sp->opdata_cipher_key == CK_INVALID_HANDLE)
++ {
++ pk11_return_session(sp, OP_CIPHER);
++ return (0);
++ }
++
++ /* now initialize the context with a new key */
++ if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0)
++ return (0);
++
++ sp->opdata_encrypt = ctx->encrypt;
++ state->sp = sp;
++
++ return (1);
++ }
++
++/*
++ * When reusing the same key in an encryption/decryption session for a
++ * decryption/encryption session, we need to close the active session
++ * and recreate a new one. Note that the key is in the global session so
++ * that it needs not be recreated.
++ *
++ * It is more appropriate to use C_En/DecryptFinish here. At the time of this
++ * development, these two functions in the PKCS#11 libraries used return
++ * unexpected errors when passing in 0 length output. It may be a good
++ * idea to try them again if performance is a problem here and fix
++ * C_En/DecryptFinial if there are bugs there causing the problem.
++ */
++static int
++pk11_cipher_final(PK11_SESSION *sp)
++ {
++ CK_RV rv;
++
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * An engine interface function. The calling function allocates sufficient
++ * memory for the output buffer "out" to hold the results.
++ */
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl)
++#else
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, size_t inl)
++#endif
++ {
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ CK_RV rv;
++ unsigned long outl = inl;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ sp = (PK11_SESSION *) state->sp;
++
++ if (!inl)
++ return (1);
++
++ /* RC4 is the only stream cipher we support */
++ if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0)
++ return (0);
++
++ if (ctx->encrypt)
++ {
++ rv = pFuncList->C_EncryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_ENCRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++ else
++ {
++ rv = pFuncList->C_DecryptUpdate(sp->session,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_DECRYPTUPDATE, rv);
++ return (0);
++ }
++ }
++
++ /*
++ * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always
++ * the same size of input.
++ * The application has guaranteed to call the block ciphers with
++ * correctly aligned buffers.
++ */
++ if (inl != outl)
++ return (0);
++
++ return (1);
++ }
++
++/*
++ * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal()
++ * here is the right thing because in EVP_DecryptFinal_ex(), engine's
++ * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but
++ * the engine can't find out that it's the finalizing call. We wouldn't
++ * necessarily have to finalize the context here since reinitializing it with
++ * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness,
++ * let's do it. Some implementations might leak memory if the previously used
++ * context is initialized without finalizing it first.
++ */
++static int
++pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_ULONG len = EVP_MAX_BLOCK_LENGTH;
++ CK_BYTE buf[EVP_MAX_BLOCK_LENGTH];
++ PK11_CIPHER_STATE *state = ctx->cipher_data;
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * We are not interested in the data here, we just need to get
++ * rid of the context.
++ */
++ if (ctx->encrypt)
++ rv = pFuncList->C_EncryptFinal(
++ state->sp->session, buf, &len);
++ else
++ rv = pFuncList->C_DecryptFinal(
++ state->sp->session, buf, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ?
++ PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv);
++ pk11_return_session(state->sp, OP_CIPHER);
++ return (0);
++ }
++
++ pk11_return_session(state->sp, OP_CIPHER);
++ state->sp = NULL;
++ }
++
++ return (1);
++ }
++
++/*
++ * Registered by the ENGINE when used to find out how to deal with
++ * a particular NID in the ENGINE. This says what we'll do at the
++ * top level - note, that list is restricted by what we answer with
++ */
++/* ARGSUSED */
++static int
++pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid)
++ {
++ if (!cipher)
++ return (pk11_usable_ciphers(nids));
++
++ switch (nid)
++ {
++ case NID_des_ede3_cbc:
++ *cipher = &pk11_3des_cbc;
++ break;
++ case NID_des_cbc:
++ *cipher = &pk11_des_cbc;
++ break;
++ case NID_des_ede3_ecb:
++ *cipher = &pk11_3des_ecb;
++ break;
++ case NID_des_ecb:
++ *cipher = &pk11_des_ecb;
++ break;
++ case NID_aes_128_cbc:
++ *cipher = &pk11_aes_128_cbc;
++ break;
++ case NID_aes_192_cbc:
++ *cipher = &pk11_aes_192_cbc;
++ break;
++ case NID_aes_256_cbc:
++ *cipher = &pk11_aes_256_cbc;
++ break;
++ case NID_aes_128_ecb:
++ *cipher = &pk11_aes_128_ecb;
++ break;
++ case NID_aes_192_ecb:
++ *cipher = &pk11_aes_192_ecb;
++ break;
++ case NID_aes_256_ecb:
++ *cipher = &pk11_aes_256_ecb;
++ break;
++ case NID_bf_cbc:
++ *cipher = &pk11_bf_cbc;
++ break;
++ case NID_rc4:
++ *cipher = &pk11_rc4;
++ break;
++ case NID_aes_128_ctr:
++ *cipher = &pk11_aes_128_ctr;
++ break;
++ case NID_aes_192_ctr:
++ *cipher = &pk11_aes_192_ctr;
++ break;
++ case NID_aes_256_ctr:
++ *cipher = &pk11_aes_256_ctr;
++ break;
++ default:
++ *cipher = NULL;
++ break;
++ }
++ return (*cipher != NULL);
++ }
++
++/* ARGSUSED */
++static int
++pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid)
++ {
++ if (!digest)
++ return (pk11_usable_digests(nids));
++
++ switch (nid)
++ {
++ case NID_md5:
++ *digest = &pk11_md5;
++ break;
++ case NID_sha1:
++ *digest = &pk11_sha1;
++ break;
++ case NID_sha224:
++ *digest = &pk11_sha224;
++ break;
++ case NID_sha256:
++ *digest = &pk11_sha256;
++ break;
++ case NID_sha384:
++ *digest = &pk11_sha384;
++ break;
++ case NID_sha512:
++ *digest = &pk11_sha512;
++ break;
++ default:
++ *digest = NULL;
++ break;
++ }
++ return (*digest != NULL);
++ }
++
++
++/* Create a secret key object in a PKCS#11 session */
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY;
++ CK_ULONG ul_key_attr_count = 6;
++ unsigned char key_buf[PK11_KEY_LEN_MAX];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VALUE, (void*) NULL, 0},
++ };
++
++ /*
++ * Create secret key object in global_session. All other sessions
++ * can use the key handles. Here is why:
++ * OpenSSL will call EncryptInit and EncryptUpdate using a secret key.
++ * It may then call DecryptInit and DecryptUpdate using the same key.
++ * To use the same key object, we need to call EncryptFinal with
++ * a 0 length message. Currently, this does not work for 3DES
++ * mechanism. To get around this problem, we close the session and
++ * then create a new session to use the same key object. When a session
++ * is closed, all the object handles will be invalid. Thus, create key
++ * objects in a global session, an individual session may be closed to
++ * terminate the active operation.
++ */
++ CK_SESSION_HANDLE session = global_session;
++ a_key_template[0].pValue = &obj_key;
++ a_key_template[1].pValue = &key_type;
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ a_key_template[5].pValue = (void *) key;
++ }
++ else
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ memcpy(key_buf, key, ctx->key_len);
++ if ((key_type == CKK_DES) ||
++ (key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[0]);
++ if ((key_type == CKK_DES2) ||
++ (key_type == CKK_DES3))
++ DES_fixup_key_parity((DES_cblock *) &key_buf[8]);
++ if (key_type == CKK_DES3)
++ DES_fixup_key_parity((DES_cblock *) &key_buf[16]);
++ a_key_template[5].pValue = (void *) key_buf;
++ }
++ a_key_template[5].ulValueLen = (unsigned long) ctx->key_len;
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++ PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++
++ /*
++ * Save the key information used in this session.
++ * The max can be saved is PK11_KEY_LEN_MAX.
++ */
++ if (ctx->key_len > PK11_KEY_LEN_MAX)
++ {
++ sp->opdata_key_len = PK11_KEY_LEN_MAX;
++ (void) memcpy(sp->opdata_key, key, sp->opdata_key_len);
++ }
++ else
++ {
++ sp->opdata_key_len = ctx->key_len;
++ (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len);
++ }
++ memset(key_buf, 0, PK11_KEY_LEN_MAX);
++err:
++
++ return (h_key);
++ }
++
++static int
++md_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; i++)
++ if (digests[i].nid == nid)
++ return (digests[i].id);
++ return (-1);
++ }
++
++static int
++pk11_digest_init(EVP_MD_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_MECHANISM mech;
++ int index;
++ PK11_SESSION *sp;
++ PK11_DIGEST *pdp;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ state->sp = NULL;
++
++ index = md_nid_to_pk11(ctx->digest->type);
++ if (index < 0 || index >= PK11_DIGEST_MAX)
++ return (0);
++
++ pdp = &digests[index];
++ if ((sp = pk11_get_session(OP_DIGEST)) == NULL)
++ return (0);
++
++ /* at present, no parameter is needed for supported digests */
++ mech.mechanism = pdp->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ rv = pFuncList->C_DigestInit(sp->session, &mech);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv);
++ pk11_return_session(sp, OP_DIGEST);
++ return (0);
++ }
++
++ state->sp = sp;
++
++ return (1);
++ }
++
++static int
++pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
++ {
++ CK_RV rv;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ /* 0 length message will cause a failure in C_DigestFinal */
++ if (count == 0)
++ return (1);
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data,
++ count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ return (1);
++ }
++
++static int
++pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
++ {
++ CK_RV rv;
++ unsigned long len;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++ len = ctx->digest->md_size;
++
++ if (state == NULL || state->sp == NULL)
++ return (0);
++
++ rv = pFuncList->C_DigestFinal(state->sp->session, md, &len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv);
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++ return (0);
++ }
++
++ if (ctx->digest->md_size != len)
++ return (0);
++
++ /*
++ * Final is called and digest is returned, so return the session
++ * to the pool
++ */
++ pk11_return_session(state->sp, OP_DIGEST);
++ state->sp = NULL;
++
++ return (1);
++ }
++
++static int
++pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
++ {
++ CK_RV rv;
++ int ret = 0;
++ PK11_CIPHER_STATE *state, *state_to;
++ CK_BYTE_PTR pstate = NULL;
++ CK_ULONG ul_state_len;
++
++ /* The copy-from state */
++ state = (PK11_CIPHER_STATE *) from->md_data;
++ if (state == NULL || state->sp == NULL)
++ goto err;
++
++ /* Initialize the copy-to state */
++ if (!pk11_digest_init(to))
++ goto err;
++ state_to = (PK11_CIPHER_STATE *) to->md_data;
++
++ /* Get the size of the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, NULL,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++ if (ul_state_len == 0)
++ {
++ goto err;
++ }
++
++ pstate = OPENSSL_malloc(ul_state_len);
++ if (pstate == NULL)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, pstate,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE,
++ rv);
++ goto err;
++ }
++
++ /* Set the operation state of the copy-to session */
++ rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate,
++ ul_state_len, 0, 0);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DIGEST_COPY,
++ PK11_R_SET_OPERATION_STATE, rv);
++ goto err;
++ }
++
++ ret = 1;
++err:
++ if (pstate != NULL)
++ OPENSSL_free(pstate);
++
++ return (ret);
++ }
++
++/* Return any pending session state to the pool */
++static int
++pk11_digest_cleanup(EVP_MD_CTX *ctx)
++ {
++ PK11_CIPHER_STATE *state = ctx->md_data;
++ unsigned char buf[EVP_MAX_MD_SIZE];
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * If state->sp is not NULL then pk11_digest_final() has not
++ * been called yet. We must call it now to free any memory
++ * that might have been allocated in the token when
++ * pk11_digest_init() was called. pk11_digest_final()
++ * will return the session to the cache.
++ */
++ if (!pk11_digest_final(ctx, buf))
++ return (0);
++ }
++
++ return (1);
++ }
++
++/*
++ * Check if the new key is the same as the key object in the session. If the key
++ * is the same, no need to create a new key object. Otherwise, the old key
++ * object needs to be destroyed and a new one will be created. Return 1 for
++ * cache hit, 0 for cache miss. Note that we must check the key length first
++ * otherwise we could end up reusing a different, longer key with the same
++ * prefix.
++ */
++static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key,
++ int key_len)
++ {
++ if (sp->opdata_key_len != key_len ||
++ memcmp(sp->opdata_key, key, key_len) != 0)
++ {
++ (void) pk11_destroy_cipher_key_objects(sp);
++ return (0);
++ }
++ return (1);
++ }
++
++/* Destroy one or more secret key objects. */
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_CIPHER].head;
++ }
++
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->opdata_cipher_key != CK_INVALID_HANDLE)
++ {
++ /*
++ * The secret key object is created in the
++ * global_session. See pk11_get_cipher_key().
++ */
++ if (pk11_destroy_object(global_session,
++ sp->opdata_cipher_key, CK_FALSE) == 0)
++ goto err;
++ sp->opdata_cipher_key = CK_INVALID_HANDLE;
++ }
++ }
++ ret = 1;
++err:
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_X_509
++ * CKM_RSA_PKCS
++ * CKM_DSA
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * Symmetric ciphers optionally supported
++ *
++ * CKM_DES3_CBC
++ * CKM_DES_CBC
++ * CKM_AES_CBC
++ * CKM_DES3_ECB
++ * CKM_DES_ECB
++ * CKM_AES_ECB
++ * CKM_AES_CTR
++ * CKM_RC4
++ * CKM_BLOWFISH_CBC
++ *
++ * Digests optionally supported
++ *
++ * CKM_MD5
++ * CKM_SHA_1
++ * CKM_SHA224
++ * CKM_SHA256
++ * CKM_SHA384
++ * CKM_SHA512
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ int slot_n_cipher = 0;
++ int slot_n_digest = 0;
++ CK_SLOT_ID current_slot = 0;
++ int current_slot_n_cipher = 0;
++ int current_slot_n_digest = 0;
++
++ int local_cipher_nids[PK11_CIPHER_MAX];
++ int local_digest_nids[PK11_DIGEST_MAX];
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ CK_BBOOL slot_has_recover = CK_FALSE;
++ CK_BBOOL slot_has_dsa = CK_FALSE;
++ CK_BBOOL slot_has_dh = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_RSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ /*
++ * Check if this slot is capable of encryption,
++ * decryption, sign, and verify with CKM_RSA_X_509.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_RSA_X_509, &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY) &&
++ (mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT)))
++ {
++ slot_has_rsa = CK_TRUE;
++ if (mech_info.flags & CKF_VERIFY_RECOVER)
++ {
++ slot_has_recover = CK_TRUE;
++ }
++ }
++ }
++#endif /* OPENSSL_NO_RSA */
++
++#ifndef OPENSSL_NO_DSA
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_DSA.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
++ &mech_info);
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ slot_has_dsa = CK_TRUE;
++ }
++
++#endif /* OPENSSL_NO_DSA */
++
++#ifndef OPENSSL_NO_DH
++ /*
++ * Check if this slot is capable of DH key generataion and
++ * derivation.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
++
++ if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
++ {
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_DERIVE, &mech_info);
++ if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
++ {
++ slot_has_dh = CK_TRUE;
++ }
++ }
++#endif /* OPENSSL_NO_DH */
++
++ if (!found_candidate_slot &&
++ (slot_has_rsa || slot_has_dsa || slot_has_dh))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ pk11_have_recover = slot_has_recover;
++ pk11_have_dsa = slot_has_dsa;
++ pk11_have_dh = slot_has_dh;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa/dsa/dh\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ found_candidate_slot = CK_FALSE;
++ best_slot_sofar = 0;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ current_slot = pSlotList[i];
++ current_slot_n_cipher = 0;
++ current_slot_n_digest = 0;
++ (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
++ (void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
++
++ pk11_find_symmetric_ciphers(pFuncList, current_slot,
++ &current_slot_n_cipher, local_cipher_nids);
++
++ pk11_find_digests(pFuncList, current_slot,
++ &current_slot_n_digest, local_digest_nids);
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG,
++ current_slot_n_cipher);
++ fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG,
++ current_slot_n_digest);
++ fprintf(stderr, "%s: best so far cipher/digest slot: %d\n",
++ PK11_DBG, best_slot_sofar);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * If the current slot supports more ciphers/digests than
++ * the previous best one we change the current best to this one,
++ * otherwise leave it where it is.
++ */
++ if ((current_slot_n_cipher + current_slot_n_digest) >
++ (slot_n_cipher + slot_n_digest))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: changing best so far slot to %d\n",
++ PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = SLOTID = current_slot;
++ cipher_count = slot_n_cipher = current_slot_n_cipher;
++ digest_count = slot_n_digest = current_slot_n_digest;
++ (void) memcpy(cipher_nids, local_cipher_nids,
++ sizeof (local_cipher_nids));
++ (void) memcpy(digest_nids, local_digest_nids,
++ sizeof (local_digest_nids));
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover);
++ fprintf(stderr,
++ "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa);
++ fprintf(stderr,
++ "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++ fprintf(stderr,
++ "%s: cipher_count %d\n", PK11_DBG, cipher_count);
++ fprintf(stderr,
++ "%s: digest_count %d\n", PK11_DBG, digest_count);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ OPENSSL_free(hw_cnids);
++ OPENSSL_free(hw_dnids);
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist,
++ int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher,
++ int *local_cipher_nids, int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if ((mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT))
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(ciphers[id].nid, hw_cnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_cipher_nids[(*current_slot_n_cipher)++] =
++ ciphers[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id,
++ CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids,
++ int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " not found\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ return;
++ }
++
++ if (mech_info.flags & CKF_DIGEST)
++ {
++#ifdef SOLARIS_HW_SLOT_SELECTION
++ if (nid_in_table(digests[id].nid, hw_dnids))
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " usable\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ local_digest_nids[(*current_slot_n_digest)++] =
++ digests[id].nid;
++ }
++#ifdef SOLARIS_HW_SLOT_SELECTION
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " rejected, software implementation only\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++ }
++#ifdef DEBUG_SLOT_SELECTION
++ else
++ {
++ fprintf(stderr, " unusable\n");
++ }
++#endif /* DEBUG_SLOT_SELECTION */
++
++ return;
++ }
++
++/* Find what symmetric ciphers this slot supports. */
++static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; ++i)
++ {
++ pk11_get_symmetric_cipher(pflist, current_slot,
++ ciphers[i].mech_type, current_slot_n_cipher,
++ local_cipher_nids, ciphers[i].id);
++ }
++ }
++
++/* Find what digest algorithms this slot supports. */
++static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist,
++ CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; ++i)
++ {
++ pk11_get_digest(pflist, current_slot, digests[i].mech_type,
++ current_slot_n_digest, local_digest_nids, digests[i].id);
++ }
++ }
++
++#ifdef SOLARIS_HW_SLOT_SELECTION
++/*
++ * It would be great if we could use pkcs11_kernel directly since this library
++ * offers hardware slots only. That's the easiest way to achieve the situation
++ * where we use the hardware accelerators when present and OpenSSL native code
++ * otherwise. That presumes the fact that OpenSSL native code is faster than the
++ * code in the soft token. It's a logical assumption - Crypto Framework has some
++ * inherent overhead so going there for the software implementation of a
++ * mechanism should be logically slower in contrast to the OpenSSL native code,
++ * presuming that both implementations are of similar speed. For example, the
++ * soft token for AES is roughly three times slower than OpenSSL for 64 byte
++ * blocks and still 20% slower for 8KB blocks. So, if we want to ship products
++ * that use the PKCS#11 engine by default, we must somehow avoid that regression
++ * on machines without hardware acceleration. That's why switching to the
++ * pkcs11_kernel library seems like a very good idea.
++ *
++ * The problem is that OpenSSL built with SunStudio is roughly 2x slower for
++ * asymmetric operations (RSA/DSA/DH) than the soft token built with the same
++ * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11
++ * library, we would have had a performance regression on machines without
++ * hardware acceleration for asymmetric operations for all applications that use
++ * the PKCS#11 engine. There is one such application - Apache web server since
++ * it's shipped configured to use the PKCS#11 engine by default. Having said
++ * that, we can't switch to the pkcs11_kernel library now and have to come with
++ * a solution that, on non-accelerated machines, uses the OpenSSL native code
++ * for all symmetric ciphers and digests while it uses the soft token for
++ * asymmetric operations.
++ *
++ * This is the idea: dlopen() pkcs11_kernel directly and find out what
++ * mechanisms are there. We don't care about duplications (more slots can
++ * support the same mechanism), we just want to know what mechanisms can be
++ * possibly supported in hardware on that particular machine. As said before,
++ * pkcs11_kernel will show you hardware providers only.
++ *
++ * Then, we rely on the fact that since we use libpkcs11 library we will find
++ * the metaslot. When we go through the metaslot's mechanisms for symmetric
++ * ciphers and digests, we check that any found mechanism is in the table
++ * created using the pkcs11_kernel library. So, as a result we have two arrays
++ * of mechanisms that were advertised as supported in hardware which was the
++ * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token
++ * code for symmetric ciphers and digests. See pk11_choose_slots() for more
++ * information.
++ *
++ * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined
++ * the code won't be used.
++ */
++#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64)
++static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1";
++#else
++static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1";
++#endif
++
++/*
++ * Check hardware capabilities of the machines. The output are two lists,
++ * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware
++ * providers together. They are not sorted and may contain duplicate mechanisms.
++ */
++static int check_hw_mechanisms(void)
++ {
++ int i;
++ CK_RV rv;
++ void *handle;
++ CK_C_GetFunctionList p;
++ CK_TOKEN_INFO token_info;
++ CK_ULONG ulSlotCount = 0;
++ int n_cipher = 0, n_digest = 0;
++ CK_FUNCTION_LIST_PTR pflist = NULL;
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL;
++ int hw_ctable_size, hw_dtable_size;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n",
++ PK11_DBG);
++#endif
++ if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ if ((p = (CK_C_GetFunctionList)dlsym(handle,
++ PK11_GET_FUNCTION_LIST)) == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ if (p(&pflist) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /* no slots, set the hw mechanism tables as empty */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG);
++#endif
++ hw_cnids = OPENSSL_malloc(sizeof (int));
++ hw_dnids = OPENSSL_malloc(sizeof (int));
++ if (hw_cnids == NULL || hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS,
++ PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ /* this means empty tables */
++ hw_cnids[0] = NID_undef;
++ hw_dnids[0] = NID_undef;
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the slot list for processing */
++ if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST);
++ goto err;
++ }
++
++ /*
++ * We don't care about duplicit mechanisms in multiple slots and also
++ * reserve one slot for the terminal NID_undef which we use to stop the
++ * search.
++ */
++ hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1;
++ hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1;
++ tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int));
++ tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int));
++ if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL)
++ {
++ PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * Do not use memset since we should not rely on the fact that NID_undef
++ * is zero now.
++ */
++ for (i = 0; i < hw_ctable_size; ++i)
++ tmp_hw_cnids[i] = NID_undef;
++ for (i = 0; i < hw_dtable_size; ++i)
++ tmp_hw_dnids[i] = NID_undef;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel);
++ fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount);
++ fprintf(stderr, "%s: now looking for mechs supported in hw\n",
++ PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * We are filling the hw mech tables here. Global tables are
++ * still NULL so all mechanisms are put into tmp tables.
++ */
++ pk11_find_symmetric_ciphers(pflist, pSlotList[i],
++ &n_cipher, tmp_hw_cnids);
++ pk11_find_digests(pflist, pSlotList[i],
++ &n_digest, tmp_hw_dnids);
++ }
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects. Also, C_Finalize() is triggered by
++ * dlclose(3C).
++ */
++#if 0
++ pflist->C_Finalize(NULL);
++#endif
++ OPENSSL_free(pSlotList);
++ (void) dlclose(handle);
++ hw_cnids = tmp_hw_cnids;
++ hw_dnids = tmp_hw_dnids;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++
++err:
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++ if (tmp_hw_cnids != NULL)
++ OPENSSL_free(tmp_hw_cnids);
++ if (tmp_hw_dnids != NULL)
++ OPENSSL_free(tmp_hw_dnids);
++
++ return (0);
++ }
++
++/*
++ * Check presence of a NID in the table of NIDs. The table may be NULL (i.e.,
++ * non-existent).
++ */
++static int nid_in_table(int nid, int *nid_table)
++ {
++ int i = 0;
++
++ /*
++ * a special case. NULL means that we are initializing a new
++ * table.
++ */
++ if (nid_table == NULL)
++ return (1);
++
++ /*
++ * the table is never full, there is always at least one
++ * NID_undef.
++ */
++ while (nid_table[i] != NID_undef)
++ {
++ if (nid_table[i++] == nid)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++ }
++
++ return (0);
++ }
++#endif /* SOLARIS_HW_SLOT_SELECTION */
++
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11_err.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.5
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 00:43:26 2011
+@@ -0,0 +1,288 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_err.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <openssl/err.h>
++#include "hw_pk11_err.h"
++
++/* BEGIN ERROR CODES */
++#ifndef OPENSSL_NO_ERR
++static ERR_STRING_DATA pk11_str_functs[]=
++{
++{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"},
++{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"},
++{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"},
++{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"},
++{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"},
++{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"},
++{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"},
++{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"},
++{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"},
++{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"},
++{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"},
++{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"},
++{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"},
++{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"},
++{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"},
++{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"},
++{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"},
++{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"},
++{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"},
++{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"},
++{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"},
++{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"},
++{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"},
++{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"},
++{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"},
++{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"},
++{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"},
++{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"},
++{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"},
++{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"},
++{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"},
++{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"},
++{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"},
++{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"},
++{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"},
++{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"},
++{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"},
++{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"},
++{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"},
++{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"},
++{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"},
++{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"},
++{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"},
++{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"},
++{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"},
++{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"},
++{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"},
++{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"},
++{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"},
++{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"},
++{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"},
++{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"},
++{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"},
++{ 0, NULL}
++};
++
++static ERR_STRING_DATA pk11_str_reasons[]=
++{
++{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"},
++{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"},
++{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"},
++{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"},
++{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"},
++{ PK11_R_INITIALIZE, "C_Initialize failed"},
++{ PK11_R_FINALIZE, "C_Finalize failed"},
++{ PK11_R_GETINFO, "C_GetInfo faile"},
++{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"},
++{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"},
++{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"},
++{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"},
++{ PK11_R_NO_MODULUS, "no modulus"},
++{ PK11_R_NO_EXPONENT, "no exponent"},
++{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"},
++{ PK11_R_FINDOBJECTS, "C_FindObjects failed"},
++{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"},
++{ PK11_R_CREATEOBJECT, "C_CreateObject failed"},
++{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"},
++{ PK11_R_OPENSESSION, "C_OpenSession failed"},
++{ PK11_R_CLOSESESSION, "C_CloseSession failed"},
++{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"},
++{ PK11_R_ENCRYPT, "C_Encrypt failed"},
++{ PK11_R_SIGNINIT, "C_SignInit failed"},
++{ PK11_R_SIGN, "C_Sign failed"},
++{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"},
++{ PK11_R_DECRYPT, "C_Decrypt failed"},
++{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"},
++{ PK11_R_VERIFY, "C_Verify failed"},
++{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"},
++{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"},
++{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"},
++{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"},
++{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"},
++{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"},
++{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"},
++{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"},
++{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"},
++{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"},
++{ PK11_R_DIGEST_TOO_BIG, "digest too big"},
++{ PK11_R_MALLOC_FAILURE, "malloc failure"},
++{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"},
++{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"},
++{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"},
++{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"},
++{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"},
++{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"},
++{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"},
++{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"},
++{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"},
++{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"},
++{ PK11_R_DIGESTINIT, "C_DigestInit failed"},
++{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"},
++{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"},
++{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"},
++{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"},
++{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"},
++{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"},
++{ PK11_R_DERIVEKEY, "C_DeriveKey failed"},
++{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"},
++{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"},
++{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"},
++{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"},
++{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"},
++{ PK11_R_ADD_NID_FAILED, "failed to add NID" },
++{ PK11_R_ATFORK_FAILED, "atfork() failed" },
++{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" },
++{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" },
++{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" },
++{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" },
++{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" },
++{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" },
++{ PK11_R_PIPE_FAILED, "pipe() failed" },
++{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" },
++{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" },
++{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" },
++{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" },
++{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" },
++{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" },
++{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" },
++{ PK11_R_NO_OBJECT_FOUND, "specified object not found" },
++{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" },
++{ PK11_R_SYSCONF_FAILED, "sysconf() failed" },
++{ PK11_R_MMAP_FAILED, "mmap() failed" },
++{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" },
++{ PK11_R_MLOCK_FAILED, "mlock() failed" },
++{ PK11_R_FORK_FAILED, "fork() failed" },
++{ 0, NULL}
++};
++#endif /* OPENSSL_NO_ERR */
++
++static int pk11_lib_error_code = 0;
++static int pk11_error_init = 1;
++
++static void
++ERR_load_pk11_strings(void)
++ {
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++
++ if (pk11_error_init)
++ {
++ pk11_error_init = 0;
++#ifndef OPENSSL_NO_ERR
++ ERR_load_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_load_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ }
++}
++
++static void
++ERR_unload_pk11_strings(void)
++ {
++ if (pk11_error_init == 0)
++ {
++#ifndef OPENSSL_NO_ERR
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_functs);
++ ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons);
++#endif
++ pk11_error_init = 1;
++ }
++}
++
++void
++ERR_pk11_error(int function, int reason, char *file, int line)
++{
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++ ERR_PUT_error(pk11_lib_error_code, function, reason, file, line);
++}
++
++void
++PK11err_add_data(int function, int reason, CK_RV rv)
++{
++ char tmp_buf[20];
++
++ PK11err(function, reason);
++ (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++}
+Index: openssl/crypto/engine/hw_pk11_err.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.13
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:04:20 2013
+@@ -0,0 +1,440 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#ifndef HW_PK11_ERR_H
++#define HW_PK11_ERR_H
++
++void ERR_pk11_error(int function, int reason, char *file, int line);
++void PK11err_add_data(int function, int reason, CK_RV rv);
++#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__)
++
++/* Error codes for the PK11 functions. */
++
++/* Function codes. */
++
++#define PK11_F_INIT 100
++#define PK11_F_FINISH 101
++#define PK11_F_DESTROY 102
++#define PK11_F_CTRL 103
++#define PK11_F_RSA_INIT 104
++#define PK11_F_RSA_FINISH 105
++#define PK11_F_GET_PUB_RSA_KEY 106
++#define PK11_F_GET_PRIV_RSA_KEY 107
++#define PK11_F_RSA_GEN_KEY 108
++#define PK11_F_RSA_PUB_ENC 109
++#define PK11_F_RSA_PRIV_ENC 110
++#define PK11_F_RSA_PUB_DEC 111
++#define PK11_F_RSA_PRIV_DEC 112
++#define PK11_F_RSA_SIGN 113
++#define PK11_F_RSA_VERIFY 114
++#define PK11_F_RAND_ADD 115
++#define PK11_F_RAND_BYTES 116
++#define PK11_F_GET_SESSION 117
++#define PK11_F_FREE_SESSION 118
++#define PK11_F_LOAD_PUBKEY 119
++#define PK11_F_LOAD_PRIVKEY 120
++#define PK11_F_RSA_PUB_ENC_LOW 121
++#define PK11_F_RSA_PRIV_ENC_LOW 122
++#define PK11_F_RSA_PUB_DEC_LOW 123
++#define PK11_F_RSA_PRIV_DEC_LOW 124
++#define PK11_F_DSA_SIGN 125
++#define PK11_F_DSA_VERIFY 126
++#define PK11_F_DSA_INIT 127
++#define PK11_F_DSA_FINISH 128
++#define PK11_F_GET_PUB_DSA_KEY 129
++#define PK11_F_GET_PRIV_DSA_KEY 130
++#define PK11_F_DH_INIT 131
++#define PK11_F_DH_FINISH 132
++#define PK11_F_MOD_EXP_DH 133
++#define PK11_F_GET_DH_KEY 134
++#define PK11_F_FREE_ALL_SESSIONS 135
++#define PK11_F_SETUP_SESSION 136
++#define PK11_F_DESTROY_OBJECT 137
++#define PK11_F_CIPHER_INIT 138
++#define PK11_F_CIPHER_DO_CIPHER 139
++#define PK11_F_GET_CIPHER_KEY 140
++#define PK11_F_DIGEST_INIT 141
++#define PK11_F_DIGEST_UPDATE 142
++#define PK11_F_DIGEST_FINAL 143
++#define PK11_F_CHOOSE_SLOT 144
++#define PK11_F_CIPHER_FINAL 145
++#define PK11_F_LIBRARY_INIT 146
++#define PK11_F_LOAD 147
++#define PK11_F_DH_GEN_KEY 148
++#define PK11_F_DH_COMP_KEY 149
++#define PK11_F_DIGEST_COPY 150
++#define PK11_F_CIPHER_CLEANUP 151
++#define PK11_F_ACTIVE_ADD 152
++#define PK11_F_ACTIVE_DELETE 153
++#define PK11_F_CHECK_HW_MECHANISMS 154
++#define PK11_F_INIT_SYMMETRIC 155
++#define PK11_F_ADD_AES_CTR_NIDS 156
++#define PK11_F_INIT_ALL_LOCKS 157
++#define PK11_F_RETURN_SESSION 158
++#define PK11_F_GET_PIN 159
++#define PK11_F_FIND_ONE_OBJECT 160
++#define PK11_F_CHECK_TOKEN_ATTRS 161
++#define PK11_F_CACHE_PIN 162
++#define PK11_F_MLOCK_PIN_IN_MEMORY 163
++#define PK11_F_TOKEN_LOGIN 164
++#define PK11_F_TOKEN_RELOGIN 165
++#define PK11_F_RUN_ASKPASS 166
++
++/* Reason codes. */
++#define PK11_R_ALREADY_LOADED 100
++#define PK11_R_DSO_FAILURE 101
++#define PK11_R_NOT_LOADED 102
++#define PK11_R_PASSED_NULL_PARAMETER 103
++#define PK11_R_COMMAND_NOT_IMPLEMENTED 104
++#define PK11_R_INITIALIZE 105
++#define PK11_R_FINALIZE 106
++#define PK11_R_GETINFO 107
++#define PK11_R_GETSLOTLIST 108
++#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109
++#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110
++#define PK11_R_GETATTRIBUTVALUE 111
++#define PK11_R_NO_MODULUS 112
++#define PK11_R_NO_EXPONENT 113
++#define PK11_R_FINDOBJECTSINIT 114
++#define PK11_R_FINDOBJECTS 115
++#define PK11_R_FINDOBJECTSFINAL 116
++#define PK11_R_CREATEOBJECT 118
++#define PK11_R_DESTROYOBJECT 119
++#define PK11_R_OPENSESSION 120
++#define PK11_R_CLOSESESSION 121
++#define PK11_R_ENCRYPTINIT 122
++#define PK11_R_ENCRYPT 123
++#define PK11_R_SIGNINIT 124
++#define PK11_R_SIGN 125
++#define PK11_R_DECRYPTINIT 126
++#define PK11_R_DECRYPT 127
++#define PK11_R_VERIFYINIT 128
++#define PK11_R_VERIFY 129
++#define PK11_R_VERIFYRECOVERINIT 130
++#define PK11_R_VERIFYRECOVER 131
++#define PK11_R_GEN_KEY 132
++#define PK11_R_SEEDRANDOM 133
++#define PK11_R_GENERATERANDOM 134
++#define PK11_R_INVALID_MESSAGE_LENGTH 135
++#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136
++#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137
++#define PK11_R_UNKNOWN_PADDING_TYPE 138
++#define PK11_R_PADDING_CHECK_FAILED 139
++#define PK11_R_DIGEST_TOO_BIG 140
++#define PK11_R_MALLOC_FAILURE 141
++#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142
++#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143
++#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144
++#define PK11_R_MISSING_KEY_COMPONENT 145
++#define PK11_R_INVALID_SIGNATURE_LENGTH 146
++#define PK11_R_INVALID_DSA_SIGNATURE_R 147
++#define PK11_R_INVALID_DSA_SIGNATURE_S 148
++#define PK11_R_INCONSISTENT_KEY 149
++#define PK11_R_ENCRYPTUPDATE 150
++#define PK11_R_DECRYPTUPDATE 151
++#define PK11_R_DIGESTINIT 152
++#define PK11_R_DIGESTUPDATE 153
++#define PK11_R_DIGESTFINAL 154
++#define PK11_R_ENCRYPTFINAL 155
++#define PK11_R_DECRYPTFINAL 156
++#define PK11_R_NO_PRNG_SUPPORT 157
++#define PK11_R_GETTOKENINFO 158
++#define PK11_R_DERIVEKEY 159
++#define PK11_R_GET_OPERATION_STATE 160
++#define PK11_R_SET_OPERATION_STATE 161
++#define PK11_R_INVALID_HANDLE 162
++#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163
++#define PK11_R_INVALID_OPERATION_TYPE 164
++#define PK11_R_ADD_NID_FAILED 165
++#define PK11_R_ATFORK_FAILED 166
++
++#define PK11_R_TOKEN_LOGIN_FAILED 167
++#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168
++#define PK11_R_INVALID_PKCS11_URI 169
++#define PK11_R_COULD_NOT_READ_PIN 170
++#define PK11_R_COULD_NOT_OPEN_COMMAND 171
++#define PK11_R_PIPE_FAILED 172
++#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173
++#define PK11_R_BAD_PASSPHRASE_SPEC 174
++#define PK11_R_TOKEN_NOT_INITIALIZED 175
++#define PK11_R_TOKEN_PIN_NOT_SET 176
++#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177
++#define PK11_R_MISSING_OBJECT_LABEL 178
++#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179
++#define PK11_R_PRIV_KEY_NOT_FOUND 180
++#define PK11_R_NO_OBJECT_FOUND 181
++#define PK11_R_PIN_CACHING_POLICY_INVALID 182
++#define PK11_R_SYSCONF_FAILED 183
++#define PK11_R_MMAP_FAILED 183
++#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184
++#define PK11_R_MLOCK_FAILED 185
++#define PK11_R_FORK_FAILED 186
++
++/* max byte length of a symetric key we support */
++#define PK11_KEY_LEN_MAX 32
++
++#ifdef NOPTHREADS
++/*
++ * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the
++ * free_session list and active_list but generally serves as a global
++ * per-process lock for the whole engine.
++ *
++ * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as
++ * the global engine lock. This is not optimal w.r.t. performance but
++ * it's safe.
++ */
++#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC
++#endif
++
++/*
++ * This structure encapsulates all reusable information for a PKCS#11
++ * session. A list of these objects is created on behalf of the
++ * calling application using an on-demand method. Each operation
++ * type (see PK11_OPTYPE below) has its own per-process list.
++ * Each of the lists is basically a cache for faster PKCS#11 object
++ * access to avoid expensive C_Find{,Init,Final}Object() calls.
++ *
++ * When a new request comes in, an object will be taken from the list
++ * (if there is one) or a new one is created to handle the request
++ * (if the list is empty). See pk11_get_session() on how it is done.
++ */
++typedef struct PK11_st_SESSION
++ {
++ struct PK11_st_SESSION *next;
++ CK_SESSION_HANDLE session; /* PK11 session handle */
++ pid_t pid; /* Current process ID */
++ CK_BBOOL pub_persistent; /* is pub key in keystore? */
++ CK_BBOOL priv_persistent;/* is priv key in keystore? */
++ union
++ {
++#ifndef OPENSSL_NO_RSA
++ struct
++ {
++ CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */
++ RSA *rsa_pub; /* pub key addr */
++ BIGNUM *rsa_n_num; /* pub modulus */
++ BIGNUM *rsa_e_num; /* pub exponent */
++ RSA *rsa_priv; /* priv key addr */
++ BIGNUM *rsa_pn_num; /* pub modulus */
++ BIGNUM *rsa_pe_num; /* pub exponent */
++ BIGNUM *rsa_d_num; /* priv exponent */
++ } u_RSA;
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++ struct
++ {
++ CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */
++ CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */
++ DSA *dsa_pub; /* pub key addr */
++ BIGNUM *dsa_pub_num; /* pub key */
++ DSA *dsa_priv; /* priv key addr */
++ BIGNUM *dsa_priv_num; /* priv key */
++ } u_DSA;
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++ struct
++ {
++ CK_OBJECT_HANDLE dh_key; /* key handle */
++ DH *dh; /* dh key addr */
++ BIGNUM *dh_priv_num; /* priv dh key */
++ } u_DH;
++#endif /* OPENSSL_NO_DH */
++ struct
++ {
++ CK_OBJECT_HANDLE cipher_key; /* key handle */
++ unsigned char key[PK11_KEY_LEN_MAX];
++ int key_len; /* priv key len */
++ int encrypt; /* 1/0 enc/decr */
++ } u_cipher;
++ } opdata_u;
++ } PK11_SESSION;
++
++#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key
++#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key
++#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub
++#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv
++#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num
++#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num
++#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num
++#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num
++#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num
++#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key
++#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key
++#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub
++#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num
++#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv
++#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num
++#define opdata_dh_key opdata_u.u_DH.dh_key
++#define opdata_dh opdata_u.u_DH.dh
++#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num
++#define opdata_cipher_key opdata_u.u_cipher.cipher_key
++#define opdata_key opdata_u.u_cipher.key
++#define opdata_key_len opdata_u.u_cipher.key_len
++#define opdata_encrypt opdata_u.u_cipher.encrypt
++
++/*
++ * We have 3 different groups of operation types:
++ * 1) asymmetric operations
++ * 2) random operations
++ * 3) symmetric and digest operations
++ *
++ * This division into groups stems from the fact that it's common that hardware
++ * providers may support operations from one group only. For example, hardware
++ * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support
++ * only a single group of operations.
++ *
++ * For every group a different slot can be chosen. That means that we must have
++ * at least 3 different lists of cached PKCS#11 sessions since sessions from
++ * different groups may be initialized in different slots.
++ *
++ * To provide locking granularity in multithreaded environment, the groups are
++ * further splitted into types with each type having a separate session cache.
++ */
++typedef enum PK11_OPTYPE_ENUM
++ {
++ OP_RAND,
++ OP_RSA,
++ OP_DSA,
++ OP_DH,
++ OP_CIPHER,
++ OP_DIGEST,
++ OP_MAX
++ } PK11_OPTYPE;
++
++/*
++ * This structure contains the heads of the lists forming the object caches
++ * and locks associated with the lists.
++ */
++typedef struct PK11_st_CACHE
++ {
++ PK11_SESSION *head;
++#ifndef NOPTHREADS
++ pthread_mutex_t *lock;
++#endif
++ } PK11_CACHE;
++
++/* structure for tracking handles of asymmetric key objects */
++typedef struct PK11_active_st
++ {
++ CK_OBJECT_HANDLE h;
++ unsigned int refcnt;
++ struct PK11_active_st *prev;
++ struct PK11_active_st *next;
++ } PK11_active;
++
++#ifndef NOPTHREADS
++extern pthread_mutex_t *find_lock[];
++#endif
++extern PK11_active *active_list[];
++/*
++ * These variables are specific for the RSA keys by reference code. See
++ * hw_pk11_pub.c for explanation.
++ */
++extern CK_FLAGS pubkey_token_flags;
++
++#ifndef NOPTHREADS
++#define LOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0)
++#define UNLOCK_OBJSTORE(alg_type) \
++ OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0)
++#else
++#define LOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE)
++#define UNLOCK_OBJSTORE(alg_type) \
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE)
++#endif
++
++extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++extern int pk11_token_relogin(CK_SESSION_HANDLE session);
++
++#ifndef OPENSSL_NO_RSA
++extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern RSA_METHOD *PK11_RSA(void);
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DSA_METHOD *PK11_DSA(void);
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++extern int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock);
++extern DH_METHOD *PK11_DH(void);
++#endif /* OPENSSL_NO_DH */
++
++extern CK_FUNCTION_LIST_PTR pFuncList;
++
++#endif /* HW_PK11_ERR_H */
+Index: openssl/crypto/engine/hw_pk11_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.42
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:27:06 2013
+@@ -0,0 +1,3556 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#ifndef OPENSSL_NO_RSA
++#include <openssl/rsa.h>
++#endif /* OPENSSL_NO_RSA */
++#ifndef OPENSSL_NO_DSA
++#include <openssl/dsa.h>
++#endif /* OPENSSL_NO_DSA */
++#ifndef OPENSSL_NO_DH
++#include <openssl/dh.h>
++#endif /* OPENSSL_NO_DH */
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11CA
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11ca.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++#ifndef OPENSSL_NO_RSA
++/* RSA stuff */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_init(RSA *rsa);
++static int pk11_RSA_finish(RSA *rsa);
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#else
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++#endif
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++#endif
++
++/* DSA stuff */
++#ifndef OPENSSL_NO_DSA
++static int pk11_DSA_init(DSA *dsa);
++static int pk11_DSA_finish(DSA *dsa);
++static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen,
++ DSA *dsa);
++static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len,
++ DSA_SIG *sig, DSA *dsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr,
++ BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session);
++
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa);
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa);
++#endif
++
++/* DH stuff */
++#ifndef OPENSSL_NO_DH
++static int pk11_DH_init(DH *dh);
++static int pk11_DH_finish(DH *dh);
++static int pk11_DH_generate_key(DH *dh);
++static int pk11_DH_compute_key(unsigned char *key,
++ const BIGNUM *pub_key, DH *dh);
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr,
++ BIGNUM **priv_key, CK_SESSION_HANDLE session);
++
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh);
++#endif
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++#ifndef OPENSSL_NO_RSA
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa =
++ {
++ "PKCS#11 RSA method",
++ pk11_RSA_public_encrypt, /* rsa_pub_encrypt */
++ pk11_RSA_public_decrypt, /* rsa_pub_decrypt */
++ pk11_RSA_private_encrypt, /* rsa_priv_encrypt */
++ pk11_RSA_private_decrypt, /* rsa_priv_decrypt */
++ NULL, /* rsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_RSA_init, /* init */
++ pk11_RSA_finish, /* finish */
++ RSA_FLAG_SIGN_VER, /* flags */
++ NULL, /* app_data */
++ pk11_RSA_sign, /* rsa_sign */
++ pk11_RSA_verify /* rsa_verify */
++ };
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ return (&pk11_rsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* Our internal DSA_METHOD that we provide pointers to */
++static DSA_METHOD pk11_dsa =
++ {
++ "PKCS#11 DSA method",
++ pk11_dsa_do_sign, /* dsa_do_sign */
++ NULL, /* dsa_sign_setup */
++ pk11_dsa_do_verify, /* dsa_do_verify */
++ NULL, /* dsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_DSA_init, /* init */
++ pk11_DSA_finish, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++ };
++
++DSA_METHOD *
++PK11_DSA(void)
++ {
++ return (&pk11_dsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DH
++/*
++ * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for
++ * output buffer may somewhat exceed the precise number of bytes needed, but
++ * should not exceed it by a large amount. That may be caused, for example, by
++ * rounding it up to multiple of X in the underlying bignum library. 8 should be
++ * enough.
++ */
++#define DH_BUF_RESERVE 8
++
++/* Our internal DH_METHOD that we provide pointers to */
++static DH_METHOD pk11_dh =
++ {
++ "PKCS#11 DH method",
++ pk11_DH_generate_key, /* generate_key */
++ pk11_DH_compute_key, /* compute_key */
++ NULL, /* bn_mod_exp */
++ pk11_DH_init, /* init */
++ pk11_DH_finish, /* finish */
++ 0, /* flags */
++ NULL, /* app_data */
++ NULL /* generate_params */
++ };
++
++DH_METHOD *
++PK11_DH(void)
++ {
++ return (&pk11_dh);
++ }
++#endif
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++/* Lengths of DSA data and signature */
++#define DSA_DATA_LEN 20
++#define DSA_SIGNATURE_LEN 40
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++#ifndef OPENSSL_NO_RSA
++/*
++ * Similiar to OpenSSL to take advantage of the paddings. The goal is to
++ * support all paddings in this engine although PK11 library does not
++ * support all the paddings used in OpenSSL.
++ * The input errors should have been checked in the padding functions.
++ */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ i = RSA_padding_add_SSLv23(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++
++/*
++ * Similar to Openssl to take advantage of the paddings. The input errors
++ * should be catched in the padding functions
++ */
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i, num = 0, r = -1;
++ unsigned char *buf = NULL;
++
++ num = BN_num_bytes(rsa->n);
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
++ break;
++ case RSA_NO_PADDING:
++ i = RSA_padding_add_none(buf, num, from, flen);
++ break;
++ case RSA_SSLV23_PADDING:
++ default:
++ RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int j, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++
++ num = BN_num_bytes(rsa->n);
++
++ if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ /* make data into a big number */
++ if (BN_bin2bn(from, (int)flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's paddings here.
++ */
++ for (j = 0; j < r; j++)
++ if (buf[j] != 0)
++ break;
++
++ p = buf + j;
++ j = r - j; /* j is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ r = RSA_padding_check_SSLv23(to, num, p, j, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, j, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/* Similar to OpenSSL code. Input errors are also checked here */
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int i, num = 0, r = -1;
++ unsigned char *p;
++ unsigned char *buf = NULL;
++
++ BN_init(&f);
++ num = BN_num_bytes(rsa->n);
++ buf = (unsigned char *)OPENSSL_malloc(num);
++ if (buf == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /*
++ * This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes
++ */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ if (BN_bin2bn(from, flen, &f) == NULL)
++ goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa);
++
++ /*
++ * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's here
++ */
++ for (i = 0; i < r; i++)
++ if (buf[i] != 0)
++ break;
++
++ p = buf + i;
++ i = r - i; /* i is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num);
++ break;
++ case RSA_NO_PADDING:
++ r = RSA_padding_check_none(to, num, p, i, num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf, num);
++ OPENSSL_free(buf);
++ }
++ return (r);
++ }
++
++/*
++ * This function implements RSA public encryption using C_EncryptInit and
++ * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_encrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_EncryptInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Encrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_encrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_encrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private encryption using C_SignInit and
++ * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG ul_sig_len = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ {
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW,
++ PK11_R_SIGNINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char *)from, flen, to, &ul_sig_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN,
++ rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ retval = ul_sig_len;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA private decryption using C_DecryptInit and
++ * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DecryptInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPTINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_Decrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++
++/*
++ * This function implements RSA public decryption using C_VerifyRecoverInit
++ * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (-1);
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyRecoverInit(sp->session,
++ p_mech, h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVERINIT, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++
++ rv = pFuncList->C_VerifyRecover(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVER, rv);
++ pk11_return_session(sp, OP_RSA);
++ return (-1);
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (retval);
++ }
++
++static int pk11_RSA_init(RSA *rsa)
++ {
++ /*
++ * This flag in the RSA_METHOD enables the new rsa_sign,
++ * rsa_verify functions. See rsa.h for details.
++ */
++ rsa->flags |= RSA_FLAG_SIGN_VER;
++
++ return (1);
++ }
++
++static int pk11_RSA_finish(RSA *rsa)
++ {
++ /*
++ * Since we are overloading OpenSSL's native RSA_eay_finish() we need
++ * to do the same as in the original function, i.e. to free bignum
++ * structures.
++ */
++ if (rsa->_method_mod_n != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_n);
++ if (rsa->_method_mod_p != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_p);
++ if (rsa->_method_mod_q != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_q);
++
++ return (1);
++ }
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#else
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++#endif
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_pub(sp, rsa);
++
++ h_pub_key = sp->opdata_rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub,
++ &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
++ sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto err;
++ }
++ rv = pFuncList->C_Verify(sp->session, s, i,
++ (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* The DSA function implementation */
++/* ARGSUSED */
++static int pk11_DSA_init(DSA *dsa)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DSA_finish(DSA *dsa)
++ {
++ return (1);
++ }
++
++
++static DSA_SIG *
++pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
++ {
++ BIGNUM *r = NULL, *s = NULL;
++ int i;
++ DSA_SIG *dsa_sig = NULL;
++
++ CK_RV rv;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_priv_key;
++
++ /*
++ * The signature is the concatenation of r and s,
++ * each is 20 bytes long
++ */
++ unsigned char sigret[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned int siglen2 = DSA_SIGNATURE_LEN / 2;
++
++ PK11_SESSION *sp = NULL;
++
++ if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_priv(sp, dsa);
++
++ h_priv_key = sp->opdata_dsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_dsa_priv_key =
++ pk11_get_private_dsa_key((DSA *)dsa,
++ &sp->opdata_dsa_priv,
++ &sp->opdata_dsa_priv_num, sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto ret;
++ }
++
++ (void) memset(sigret, 0, siglen);
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char*) dgst, dlen, sigret,
++ (CK_ULONG_PTR) &siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv);
++ goto ret;
++ }
++ }
++
++
++ if ((s = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((r = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((dsa_sig = DSA_SIG_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if (BN_bin2bn(sigret, siglen2, r) == NULL ||
++ BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ dsa_sig->r = r;
++ dsa_sig->s = s;
++
++ret:
++ if (dsa_sig == NULL)
++ {
++ if (r != NULL)
++ BN_free(r);
++ if (s != NULL)
++ BN_free(s);
++ }
++
++ pk11_return_session(sp, OP_DSA);
++ return (dsa_sig);
++ }
++
++static int
++pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig,
++ DSA *dsa)
++ {
++ int i;
++ CK_RV rv;
++ int retval = 0;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_pub_key;
++
++ unsigned char sigbuf[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned long siglen2 = DSA_SIGNATURE_LEN/2;
++
++ PK11_SESSION *sp = NULL;
++
++ if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_R);
++ goto ret;
++ }
++
++ if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_S);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session(OP_DSA)) == NULL)
++ goto ret;
++
++ (void) check_new_dsa_key_pub(sp, dsa);
++
++ h_pub_key = sp->opdata_dsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->opdata_dsa_pub_key =
++ pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub,
++ &sp->opdata_dsa_pub_num, sp->session);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT,
++ rv);
++ goto ret;
++ }
++
++ /*
++ * The representation of each of the two big numbers could
++ * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need
++ * to act accordingly and shift if necessary.
++ */
++ (void) memset(sigbuf, 0, siglen);
++ BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r));
++ BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 -
++ BN_num_bytes(sig->s));
++
++ rv = pFuncList->C_Verify(sp->session,
++ (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv);
++ goto ret;
++ }
++ }
++
++ retval = 1;
++ret:
++
++ pk11_return_session(sp, OP_DSA);
++ return (retval);
++ }
++
++
++/*
++ * Create a public key object in a session from a given dsa structure.
++ * The *dsa_pub_num pointer is non-NULL for DSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ if (init_template_value(dsa->p, &a_key_template[4].pValue,
++ &a_key_template[4].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->pub_key, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_pub_num != NULL)
++ if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ for (i = 4; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given dsa structure
++ * The *dsa_priv_num pointer is non-NULL for DSA private keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa,
++ DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ int i;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 9;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */
++ };
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(dsa->p, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(dsa->priv_key, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DSA);
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (dsa_priv_num != NULL)
++ if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DSA);
++
++malloc_err:
++ /*
++ * 5 to 8 entries in the key template are key components.
++ * They need to be freed apon exit or error.
++ */
++ for (i = 5; i <= 8; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only public key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_pub != dsa) ||
++ (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa)
++ {
++ /*
++ * Provide protection against DSA structure reuse by making the
++ * check for cache hit stronger. Only private key component of DSA
++ * key matters here so it is sufficient to compare it with value
++ * cached in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dsa_priv != dsa) ||
++ (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++
++#ifndef OPENSSL_NO_DH
++/* The DH function implementation */
++/* ARGSUSED */
++static int pk11_DH_init(DH *dh)
++ {
++ return (1);
++ }
++
++/* ARGSUSED */
++static int pk11_DH_finish(DH *dh)
++ {
++ return (1);
++ }
++
++/*
++ * Generate DH key-pair.
++ *
++ * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key
++ * and override it even if it is set. OpenSSL does not touch dh->priv_key
++ * if set and just computes dh->pub_key. It looks like PKCS#11 standard
++ * is not capable of providing this functionality. This could be a problem
++ * for applications relying on OpenSSL's semantics.
++ */
++static int pk11_DH_generate_key(DH *dh)
++ {
++ CK_ULONG i;
++ CK_RV rv, rv1;
++ int reuse_mem_len = 0, ret = 0;
++ PK11_SESSION *sp = NULL;
++ CK_BYTE_PTR reuse_mem;
++
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++
++ CK_ULONG ul_pub_key_attr_count = 3;
++ CK_ATTRIBUTE pub_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *)NULL, 0},
++ {CKA_BASE, (void *)NULL, 0}
++ };
++
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)}
++ };
++
++ CK_ULONG pub_key_attr_result_count = 1;
++ CK_ATTRIBUTE pub_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ pub_key_template[1].ulValueLen = BN_num_bytes(dh->p);
++ if (pub_key_template[1].ulValueLen > 0)
++ {
++ /*
++ * We must not increase ulValueLen by DH_BUF_RESERVE since that
++ * could cause the same rounding problem. See definition of
++ * DH_BUF_RESERVE above.
++ */
++ pub_key_template[1].pValue =
++ OPENSSL_malloc(pub_key_template[1].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[1].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->p, pub_key_template[1].pValue);
++ }
++ else
++ goto err;
++
++ pub_key_template[2].ulValueLen = BN_num_bytes(dh->g);
++ if (pub_key_template[2].ulValueLen > 0)
++ {
++ pub_key_template[2].pValue =
++ OPENSSL_malloc(pub_key_template[2].ulValueLen +
++ DH_BUF_RESERVE);
++ if (pub_key_template[2].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->g, pub_key_template[2].pValue);
++ }
++ else
++ goto err;
++
++ /*
++ * Note: we are only using PK11_SESSION structure for getting
++ * a session handle. The objects created in this function are
++ * destroyed before return and thus not cached.
++ */
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ rv = pFuncList->C_GenerateKeyPair(sp->session,
++ &mechanism,
++ pub_key_template,
++ ul_pub_key_attr_count,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_pub_key,
++ &h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv);
++ goto err;
++ }
++
++ /*
++ * Reuse the larger memory allocated. We know the larger memory
++ * should be sufficient for reuse.
++ */
++ if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen)
++ {
++ reuse_mem = pub_key_template[1].pValue;
++ reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE;
++ }
++ else
++ {
++ reuse_mem = pub_key_template[2].pValue;
++ reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++ rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK || rv1 != CKR_OK)
++ {
++ rv = (rv != CKR_OK) ? rv : rv1;
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 ||
++ ((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++
++ /* Reuse the memory allocated */
++ pub_key_result[0].pValue = reuse_mem;
++ pub_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (pub_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->pub_key == NULL)
++ if ((dh->pub_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->pub_key = BN_bin2bn(pub_key_result[0].pValue,
++ pub_key_result[0].ulValueLen, dh->pub_key);
++ if (dh->pub_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ /* Reuse the memory allocated */
++ priv_key_result[0].pValue = reuse_mem;
++ priv_key_result[0].ulValueLen = reuse_mem_len;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->priv_key == NULL)
++ if ((dh->priv_key = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ dh->priv_key = BN_bin2bn(priv_key_result[0].pValue,
++ priv_key_result[0].ulValueLen, dh->priv_key);
++ if (dh->priv_key == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ }
++
++ ret = 1;
++
++err:
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_pub_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_GEN_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++
++ for (i = 1; i <= 2; i++)
++ {
++ if (pub_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(pub_key_template[i].pValue);
++ pub_key_template[i].pValue = NULL;
++ }
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key,
++ DH *dh)
++ {
++ unsigned int i;
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0};
++ CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
++ CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
++ CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++
++ CK_ULONG seclen;
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (key_class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_VALUE_LEN, &seclen, sizeof (seclen)},
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_RV rv;
++ int ret = -1;
++ PK11_SESSION *sp = NULL;
++
++ if (dh->priv_key == NULL)
++ goto err;
++
++ priv_key_template[0].pValue = &key_class;
++ priv_key_template[1].pValue = &key_type;
++ seclen = BN_num_bytes(dh->p);
++
++ if ((sp = pk11_get_session(OP_DH)) == NULL)
++ goto err;
++
++ mechanism.ulParameterLen = BN_num_bytes(pub_key);
++ mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen);
++ if (mechanism.pParameter == NULL)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ BN_bn2bin(pub_key, mechanism.pParameter);
++
++ (void) check_new_dh_key(sp, dh);
++
++ h_key = sp->opdata_dh_key;
++ if (h_key == CK_INVALID_HANDLE)
++ h_key = sp->opdata_dh_key =
++ pk11_get_dh_key((DH*) dh, &sp->opdata_dh,
++ &sp->opdata_dh_priv_num, sp->session);
++
++ if (h_key == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT);
++ goto err;
++ }
++
++ rv = pFuncList->C_DeriveKey(sp->session,
++ &mechanism,
++ h_key,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++ priv_key_result[0].pValue =
++ OPENSSL_malloc(priv_key_result[0].ulValueLen);
++ if (!priv_key_result[0].pValue)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
++ rv);
++ goto err;
++ }
++
++ /*
++ * OpenSSL allocates the output buffer 'key' which is the same
++ * length of the public key. It is long enough for the derived key
++ */
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ /*
++ * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip
++ * leading zeros from a computed shared secret. However,
++ * OpenSSL always did it so we must do the same here. The
++ * vagueness of the spec regarding leading zero bytes was
++ * finally cleared with TLS 1.1 (RFC 4346) saying that leading
++ * zeros are stripped before the computed data is used as the
++ * pre-master secret.
++ */
++ for (i = 0; i < priv_key_result[0].ulValueLen; ++i)
++ {
++ if (((char *)priv_key_result[0].pValue)[i] != 0)
++ break;
++ }
++
++ (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i,
++ priv_key_result[0].ulValueLen - i);
++ ret = priv_key_result[0].ulValueLen - i;
++ }
++
++err:
++
++ if (h_derived_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DH_COMP_KEY,
++ PK11_R_DESTROYOBJECT, rv);
++ }
++ }
++ if (priv_key_result[0].pValue)
++ {
++ OPENSSL_free(priv_key_result[0].pValue);
++ priv_key_result[0].pValue = NULL;
++ }
++
++ if (mechanism.pParameter)
++ {
++ OPENSSL_free(mechanism.pParameter);
++ mechanism.pParameter = NULL;
++ }
++
++ pk11_return_session(sp, OP_DH);
++ return (ret);
++ }
++
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh,
++ DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE key_type = CKK_DH;
++ CK_ULONG found;
++ CK_BBOOL rollback = FALSE;
++ int i;
++
++ CK_ULONG ul_key_attr_count = 7;
++ CK_ATTRIBUTE key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof (class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
++ {CKA_DERIVE, &mytrue, sizeof (mytrue)},
++ {CKA_PRIVATE, &myfalse, sizeof (myfalse)},
++ {CKA_PRIME, (void *) NULL, 0},
++ {CKA_BASE, (void *) NULL, 0},
++ {CKA_VALUE, (void *) NULL, 0},
++ };
++
++ key_template[0].pValue = &class;
++ key_template[1].pValue = &key_type;
++
++ key_template[4].ulValueLen = BN_num_bytes(dh->p);
++ key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[4].ulValueLen);
++ if (key_template[4].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->p, key_template[4].pValue);
++
++ key_template[5].ulValueLen = BN_num_bytes(dh->g);
++ key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[5].ulValueLen);
++ if (key_template[5].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->g, key_template[5].pValue);
++
++ key_template[6].ulValueLen = BN_num_bytes(dh->priv_key);
++ key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[6].ulValueLen);
++ if (key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(dh->priv_key, key_template[6].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_DH);
++ rv = pFuncList->C_FindObjectsInit(session, key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL,
++ rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT,
++ rv);
++ goto err;
++ }
++ }
++
++ if (dh_priv_num != NULL)
++ if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = dh;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_DH);
++
++malloc_err:
++ for (i = 4; i <= 6; i++)
++ {
++ if (key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(key_template[i].pValue);
++ key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ *
++ * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh
++ * to CK_INVALID_HANDLE even when it fails to destroy the object.
++ */
++static int check_new_dh_key(PK11_SESSION *sp, DH *dh)
++ {
++ /*
++ * Provide protection against DH structure reuse by making the
++ * check for cache hit stronger. Private key component of DH key
++ * is unique so it is sufficient to compare it with value cached
++ * in PK11_SESSION structure.
++ */
++ if ((sp->opdata_dh != dh) ||
++ (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_dh_object(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++#endif
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11CA */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11ca.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.4
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:20 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */
++
++#define token_lock pk11ca_token_lock
++#define find_lock pk11ca_find_lock
++#define active_list pk11ca_active_list
++#define pubkey_token_flags pk11ca_pubkey_token_flags
++#define pubkey_SLOTID pk11ca_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11ca_error
++#define PK11err_add_data PK11CAerr_add_data
++#define pk11_get_session pk11ca_get_session
++#define pk11_return_session pk11ca_return_session
++#define pk11_active_add pk11ca_active_add
++#define pk11_active_delete pk11ca_active_delete
++#define pk11_active_remove pk11ca_active_remove
++#define pk11_free_active_list pk11ca_free_active_list
++#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv
++#define pk11_load_privkey pk11ca_load_privkey
++#define pk11_load_pubkey pk11ca_load_pubkey
++#define PK11_RSA PK11CA_RSA
++#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv
++#define PK11_DSA PK11CA_DSA
++#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11ca_destroy_dh_object
++#define PK11_DH PK11CA_DH
++#define pk11_token_relogin pk11ca_token_relogin
++#define pFuncList pk11ca_pFuncList
++#define pk11_pin pk11ca_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11ca
+Index: openssl/crypto/engine/hw_pk11so.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.8
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:05:16 2013
+@@ -0,0 +1,1775 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++typedef int pid_t;
++#define getpid() GetCurrentProcessId()
++#define NOPTHREADS
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <signal.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#endif
++
++/* Debug mutexes */
++/*#undef DEBUG_MUTEX */
++#define DEBUG_MUTEX
++
++#ifndef NOPTHREADS
++/* for pthread error check on Linuxes */
++#ifdef DEBUG_MUTEX
++#define __USE_UNIX98
++#endif
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++/* label for debug messages printed on stderr */
++#define PK11_DBG "PKCS#11 ENGINE DEBUG"
++/* prints a lot of debug messages on stderr about slot selection process */
++/*#undef DEBUG_SLOT_SELECTION */
++
++#ifndef OPENSSL_NO_DSA
++#define OPENSSL_NO_DSA
++#endif
++#ifndef OPENSSL_NO_DH
++#define OPENSSL_NO_DH
++#endif
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.c"
++
++/*
++ * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
++ * uri_struct manipulation, and static token info. All of that is used by the
++ * RSA keys by reference feature.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *token_lock;
++#endif
++
++/* PKCS#11 session caches and their locks for all operation types */
++static PK11_CACHE session_cache[OP_MAX];
++
++/*
++ * We cache the flags so that we do not have to run C_GetTokenInfo() again when
++ * logging into the token.
++ */
++CK_FLAGS pubkey_token_flags;
++
++/*
++ * As stated in v2.20, 11.7 Object Management Function, in section for
++ * C_FindObjectsInit(), at most one search operation may be active at a given
++ * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be
++ * grouped together to form one atomic search operation. This is already
++ * ensured by the property of unique PKCS#11 session handle used for each
++ * PK11_SESSION object.
++ *
++ * This is however not the biggest concern - maintaining consistency of the
++ * underlying object store is more important. The same section of the spec also
++ * says that one thread can be in the middle of a search operation while another
++ * thread destroys the object matching the search template which would result in
++ * invalid handle returned from the search operation.
++ *
++ * Hence, the following locks are used for both protection of the object stores.
++ * They are also used for active list protection.
++ */
++#ifndef NOPTHREADS
++pthread_mutex_t *find_lock[OP_MAX] = { NULL };
++#endif
++
++/*
++ * lists of asymmetric key handles which are active (referenced by at least one
++ * PK11_SESSION structure, either held by a thread or present in free_session
++ * list) for given algorithm type
++ */
++PK11_active *active_list[OP_MAX] = { NULL };
++
++/*
++ * Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects.
++ */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session(PK11_OPTYPE optype);
++void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++
++/* active list manipulation functions used in this file */
++extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type);
++extern void pk11_free_active_list(PK11_OPTYPE type);
++
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock);
++int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock);
++
++/* Local helper functions */
++static int pk11_free_all_sessions(void);
++static int pk11_free_session_list(PK11_OPTYPE optype);
++static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype);
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++static int pk11_choose_slots(int *any_slot_found);
++
++static int pk11_init_all_locks(void);
++static void pk11_free_all_locks(void);
++
++#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \
++ { \
++ if (uselock) \
++ LOCK_OBJSTORE(alg_type); \
++ if (pk11_active_delete(obj_hdl, alg_type) == 1) \
++ { \
++ retval = pk11_destroy_object(sp->session, obj_hdl, \
++ priv ? sp->priv_persistent : sp->pub_persistent); \
++ } \
++ if (uselock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ }
++
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE */
++#ifdef OPENSSL_NO_HW_PK11CA
++#error "can't load both crypto-accelerator and sign-only PKCS#11 engines"
++#endif
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name = "PKCS #11 engine support (sign only)";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/*
++ * This is a static string constant for the DSO file name and the function
++ * symbol names to bind to. We set it in the Configure script based on whether
++ * this is 32 or 64 bit build.
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++/* Needed in hw_pk11_pub.c as well so that's why it is not static. */
++CK_SLOT_ID pubkey_SLOTID = 0;
++static CK_SLOT_ID rand_SLOTID = 0;
++static CK_SLOT_ID SLOTID = 0;
++char *pk11_pin = NULL;
++static CK_BBOOL pk11_library_initialized = FALSE;
++static CK_BBOOL pk11_atfork_initialized = FALSE;
++static int pk11_pid = 0;
++
++static DSO *pk11_dso = NULL;
++
++/* allocate and initialize all locks used by the engine itself */
++static int pk11_init_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++ pthread_mutexattr_t attr;
++
++ if (pthread_mutexattr_init(&attr) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 100);
++ return (0);
++ }
++
++#ifdef DEBUG_MUTEX
++ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
++ {
++ PK11err(PK11_F_INIT_ALL_LOCKS, 101);
++ return (0);
++ }
++#endif
++
++ if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(token_lock, &attr);
++
++ find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (find_lock[OP_RSA] == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(find_lock[OP_RSA], &attr);
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ session_cache[type].lock =
++ OPENSSL_malloc(sizeof (pthread_mutex_t));
++ if (session_cache[type].lock == NULL)
++ goto malloc_err;
++ (void) pthread_mutex_init(session_cache[type].lock, &attr);
++ }
++
++ return (1);
++
++malloc_err:
++ pk11_free_all_locks();
++ PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE);
++ return (0);
++#else
++ return (1);
++#endif
++ }
++
++static void pk11_free_all_locks(void)
++ {
++#ifndef NOPTHREADS
++ int type;
++
++ if (token_lock != NULL)
++ {
++ (void) pthread_mutex_destroy(token_lock);
++ OPENSSL_free(token_lock);
++ token_lock = NULL;
++ }
++
++ if (find_lock[OP_RSA] != NULL)
++ {
++ (void) pthread_mutex_destroy(find_lock[OP_RSA]);
++ OPENSSL_free(find_lock[OP_RSA]);
++ find_lock[OP_RSA] = NULL;
++ }
++
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (session_cache[type].lock != NULL)
++ {
++ (void) pthread_mutex_destroy(session_cache[type].lock);
++ OPENSSL_free(session_cache[type].lock);
++ session_cache[type].lock = NULL;
++ }
++ }
++#endif
++ }
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++ if (!pk11_library_initialized)
++ if (!pk11_library_init(e))
++ return (0);
++
++ if (!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name))
++ return (0);
++
++ if (pk11_have_rsa == CK_TRUE)
++ {
++ if (!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered RSA\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++
++ if (pk11_have_random)
++ {
++ if (!ENGINE_set_RAND(e, &pk11_random))
++ return (0);
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: registered random\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if (!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return (0);
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return (1);
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++#error "dynamic engine not supported"
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return (0);
++
++ if (!bind_pk11(e))
++ return (0);
++
++ return (1);
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return (NULL);
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return (NULL);
++ }
++
++ return (ret);
++ }
++
++void
++ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /*
++ * Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically.
++ */
++ /* Attempt to load PKCS#11 library */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /*
++ * At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif /* ENGINE_DYNAMIC_SUPPORT */
++
++/*
++ * These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return (PK11_LIBNAME);
++
++ return (def_PK11_LIBNAME);
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* acquire all engine specific mutexes before fork */
++static void pk11_fork_prepare(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ LOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++ for (i = 0; i < OP_MAX; i++)
++ {
++ OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0);
++ }
++#endif
++ }
++
++/* release all engine specific mutexes */
++static void pk11_fork_parent(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/*
++ * same situation as in parent - we need to unlock all locks to make them
++ * accessible to all threads.
++ */
++static void pk11_fork_child(void)
++ {
++#ifndef NOPTHREADS
++ int i;
++
++ if (!pk11_library_initialized)
++ return;
++
++ for (i = OP_MAX - 1; i >= 0; i--)
++ {
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0);
++ }
++ UNLOCK_OBJSTORE(OP_RSA);
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#endif
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return (pk11_library_init(e));
++}
++
++static CK_C_INITIALIZE_ARGS pk11_init_args =
++ {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++ };
++
++/*
++ * Initialization function. Sets up various PKCS#11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++/* ARGSUSED */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ int any_slot_found;
++ int i;
++#ifndef OPENSSL_SYS_WIN32
++ struct sigaction sigint_act, sigterm_act, sighup_act;
++#endif
++
++ /*
++ * pk11_library_initialized is set to 0 in pk11_finish() which
++ * is called from ENGINE_finish(). However, if there is still
++ * at least one existing functional reference to the engine
++ * (see engine(3) for more information), pk11_finish() is
++ * skipped. For example, this can happen if an application
++ * forgets to clear one cipher context. In case of a fork()
++ * when the application is finishing the engine so that it can
++ * be reinitialized in the child, forgotten functional
++ * reference causes pk11_library_initialized to stay 1. In
++ * that case we need the PID check so that we properly
++ * initialize the engine again.
++ */
++ if (pk11_library_initialized)
++ {
++ if (pk11_pid == getpid())
++ {
++ return (1);
++ }
++ else
++ {
++ global_session = CK_INVALID_HANDLE;
++ /*
++ * free the locks first to prevent memory leak in case
++ * the application calls fork() without finishing the
++ * engine first.
++ */
++ pk11_free_all_locks();
++ }
++ }
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the C_GetFunctionList function from the loaded library */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if (!p)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv);
++ goto err;
++ }
++
++#ifndef OPENSSL_SYS_WIN32
++ /* Not all PKCS#11 library are signal safe! */
++
++ (void) memset(&sigint_act, 0, sizeof(sigint_act));
++ (void) memset(&sigterm_act, 0, sizeof(sigterm_act));
++ (void) memset(&sighup_act, 0, sizeof(sighup_act));
++ (void) sigaction(SIGINT, NULL, &sigint_act);
++ (void) sigaction(SIGTERM, NULL, &sigterm_act);
++ (void) sigaction(SIGHUP, NULL, &sighup_act);
++#endif
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++#ifndef OPENSSL_SYS_WIN32
++ (void) sigaction(SIGINT, &sigint_act, NULL);
++ (void) sigaction(SIGTERM, &sigterm_act, NULL);
++ (void) sigaction(SIGHUP, &sighup_act, NULL);
++#endif
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv);
++ goto err;
++ }
++
++ if (pk11_choose_slots(&any_slot_found) == 0)
++ goto err;
++
++ /*
++ * The library we use, set in def_PK11_LIBNAME, may not offer any
++ * slot(s). In that case, we must not proceed but we must not return an
++ * error. The reason is that applications that try to set up the PKCS#11
++ * engine don't exit on error during the engine initialization just
++ * because no slot was present.
++ */
++ if (any_slot_found == 0)
++ return (1);
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_LIBRARY_INIT,
++ PK11_R_OPENSESSION, rv);
++ goto err;
++ }
++ }
++
++ pk11_library_initialized = TRUE;
++ pk11_pid = getpid();
++ /*
++ * if initialization of the locks fails pk11_init_all_locks()
++ * will do the cleanup.
++ */
++ if (!pk11_init_all_locks())
++ goto err;
++ for (i = 0; i < OP_MAX; i++)
++ session_cache[i].head = NULL;
++ /*
++ * initialize active lists. We only use active lists
++ * for asymmetric ciphers.
++ */
++ for (i = 0; i < OP_MAX; i++)
++ active_list[i] = NULL;
++
++#ifndef NOPTHREADS
++ if (!pk11_atfork_initialized)
++ {
++ if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent,
++ pk11_fork_child) != 0)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED);
++ goto err;
++ }
++ pk11_atfork_initialized = TRUE;
++ }
++#endif
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor) */
++/* ARGSUSED */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return (1);
++ }
++
++/*
++ * Termination function to clean up the session, the token, and the pk11
++ * library.
++ */
++/* ARGSUSED */
++static int pk11_finish(ENGINE *e)
++ {
++ int i;
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ OPENSSL_assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ /* free all active lists */
++ for (i = 0; i < OP_MAX; i++)
++ pk11_free_active_list(i);
++
++ pFuncList->C_CloseSession(global_session);
++ global_session = CK_INVALID_HANDLE;
++
++ /*
++ * Since we are part of a library (libcrypto.so), calling this function
++ * may have side-effects.
++ */
++#if 0
++ pFuncList->C_Finalize(NULL);
++#endif
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = FALSE;
++ pk11_pid = 0;
++ /*
++ * There is no way how to unregister atfork handlers (other than
++ * unloading the library) so we just free the locks. For this reason
++ * the atfork handlers check if the engine is initialized and bail out
++ * immediately if not. This is necessary in case a process finishes
++ * the engine before calling fork().
++ */
++ pk11_free_all_locks();
++
++ return (1);
++
++err:
++ return (0);
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++/* ARGSUSED */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch (cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return (0);
++ }
++
++ return (set_PK11_LIBNAME((const char *)p));
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return (0);
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++ return (1);
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: slot set\n", PK11_DBG);
++#endif
++ return (1);
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return (0);
++ }
++
++
++/* Required function by the engine random interface. It does nothing here */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++/* ARGSUSED */
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return;
++
++ /*
++ * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp, OP_RAND);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session(OP_RAND)) == NULL)
++ return (0);
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv);
++ pk11_return_session(sp, OP_RAND);
++ return (0);
++ }
++
++ pk11_return_session(sp, OP_RAND);
++ return (1);
++ }
++
++/* Required function by the engine random interface. It does nothing here */
++static int pk11_rand_status(void)
++ {
++ return (1);
++ }
++
++/* Free all BIGNUM structures from PK11_SESSION. */
++static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ switch (optype)
++ {
++ case OP_RSA:
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++/*
++ * Get new PK11_SESSION structure ready for use. Every process must have
++ * its own freelist of PK11_SESSION structures so handle fork() here
++ * by destroying the old and creating new freelist.
++ * The returned PK11_SESSION structure is disconnected from the freelist.
++ */
++PK11_SESSION *
++pk11_get_session(PK11_OPTYPE optype)
++ {
++ PK11_SESSION *sp = NULL, *sp1, *freelist;
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock = NULL;
++#endif
++ static pid_t pid = 0;
++ pid_t new_pid;
++ CK_RV rv;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (NULL);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ /*
++ * Will use it to find out if we forked. We cannot use the PID field in
++ * the session structure because we could get a newly allocated session
++ * here, with no PID information.
++ */
++ if (pid == 0)
++ pid = getpid();
++
++ freelist = session_cache[optype].head;
++ sp = freelist;
++
++ /*
++ * If the free list is empty, allocate new unitialized (filled
++ * with zeroes) PK11_SESSION structure otherwise return first
++ * structure from the freelist.
++ */
++ if (sp == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ (void) memset(sp, 0, sizeof (PK11_SESSION));
++
++ /*
++ * It is a new session so it will look like a cache miss to the
++ * code below. So, we must not try to to destroy its members so
++ * mark them as unused.
++ */
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ }
++ else
++ {
++ freelist = sp->next;
++ }
++
++ /*
++ * Check whether we have forked. In that case, we must get rid of all
++ * inherited sessions and start allocating new ones.
++ */
++ if (pid != (new_pid = getpid()))
++ {
++ pid = new_pid;
++
++ /*
++ * We are a new process and thus need to free any inherited
++ * PK11_SESSION objects aside from the first session (sp) which
++ * is the only PK11_SESSION structure we will reuse (for the
++ * head of the list).
++ */
++ while ((sp1 = freelist) != NULL)
++ {
++ freelist = sp1->next;
++ /*
++ * NOTE: we do not want to call pk11_free_all_sessions()
++ * here because it would close underlying PKCS#11
++ * sessions and destroy all objects.
++ */
++ pk11_free_nums(sp1, optype);
++ OPENSSL_free(sp1);
++ }
++
++ /* we have to free the active list as well. */
++ pk11_free_active_list(optype);
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * Choose slot here since the slot table is different on this
++ * process. If we are here then we must have found at least one
++ * usable slot before so we don't need to check any_slot_found.
++ * See pk11_library_init()'s usage of this function for more
++ * information.
++ */
++ if (pk11_choose_slots(NULL) == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION,
++ rv);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /*
++ * It is an inherited session from our parent so it needs
++ * re-initialization.
++ */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++ if (pk11_token_relogin(sp->session) == 0)
++ {
++ /*
++ * We will keep the session in the cache list and let
++ * the caller cope with the situation.
++ */
++ freelist = sp;
++ sp = NULL;
++ goto err;
++ }
++ }
++
++ if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization. */
++ if (pk11_setup_session(sp, optype) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++ /* set new head for the list of PK11_SESSION objects */
++ session_cache[optype].head = freelist;
++
++err:
++ if (sp != NULL)
++ sp->next = NULL;
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (sp);
++ }
++
++
++void
++pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ PK11_SESSION *freelist;
++
++ /*
++ * If this is a session from the parent it will be taken care of and
++ * freed in pk11_get_session() as part of the post-fork clean up the
++ * next time we will ask for a new session.
++ */
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_RETURN_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return;
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ sp->next = freelist;
++ session_cache[optype].head = sp;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished */
++static int pk11_free_all_sessions()
++ {
++ int ret = 1;
++ int type;
++
++ (void) pk11_destroy_rsa_key_objects(NULL);
++
++ /*
++ * We try to release as much as we can but any error means that we will
++ * return 0 on exit.
++ */
++ for (type = 0; type < OP_MAX; type++)
++ {
++ if (pk11_free_session_list(type) == 0)
++ ret = 0;
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy session structures from the linked list specified. Free as many
++ * sessions as possible but any failure in C_CloseSession() means that we
++ * return an error on return.
++ */
++static int pk11_free_session_list(PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *freelist = NULL;
++ pid_t mypid = getpid();
++#ifndef NOPTHREADS
++ pthread_mutex_t *freelist_lock;
++#endif
++ int ret = 1;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ case OP_DSA:
++ case OP_DH:
++ case OP_RAND:
++ case OP_DIGEST:
++ case OP_CIPHER:
++#ifndef NOPTHREADS
++ freelist_lock = session_cache[optype].lock;
++#endif
++ break;
++ default:
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ freelist = session_cache[optype].head;
++ while ((sp = freelist) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION, rv);
++ ret = 0;
++ }
++ }
++ freelist = sp->next;
++ pk11_free_nums(sp, optype);
++ OPENSSL_free(sp);
++ }
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (ret);
++ }
++
++
++static int
++pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype)
++ {
++ CK_RV rv;
++ CK_SLOT_ID myslot;
++
++ switch (optype)
++ {
++ case OP_RSA:
++ myslot = pubkey_SLOTID;
++ break;
++ case OP_RAND:
++ myslot = rand_SLOTID;
++ break;
++ default:
++ PK11err(PK11_F_SETUP_SESSION,
++ PK11_R_INVALID_OPERATION_TYPE);
++ return (0);
++ }
++
++ sp->session = CK_INVALID_HANDLE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = FALSE;
++ if (!pk11_library_init(NULL))
++ return (0);
++ rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv);
++ return (0);
++ }
++
++ sp->pid = getpid();
++
++ if (optype == OP_RSA)
++ {
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ sp->opdata_rsa_n_num = NULL;
++ sp->opdata_rsa_e_num = NULL;
++ sp->opdata_rsa_priv = NULL;
++ sp->opdata_rsa_pn_num = NULL;
++ sp->opdata_rsa_pe_num = NULL;
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * We always initialize the session as containing a non-persistent
++ * object. The key load functions set it to persistent if that is so.
++ */
++ sp->pub_persistent = CK_FALSE;
++ sp->priv_persistent = CK_FALSE;
++ return (1);
++ }
++
++/* Destroy RSA public key from single session. */
++int
++pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key,
++ ret, uselock, OP_RSA, CK_FALSE);
++ sp->opdata_rsa_pub_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_pub = NULL;
++ if (sp->opdata_rsa_n_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_n_num);
++ sp->opdata_rsa_n_num = NULL;
++ }
++ if (sp->opdata_rsa_e_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_e_num);
++ sp->opdata_rsa_e_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/* Destroy RSA private key from single session. */
++int
++pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock)
++ {
++ int ret = 0;
++
++ if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key,
++ ret, uselock, OP_RSA, CK_TRUE);
++ sp->opdata_rsa_priv_key = CK_INVALID_HANDLE;
++ sp->opdata_rsa_priv = NULL;
++ if (sp->opdata_rsa_d_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_d_num);
++ sp->opdata_rsa_d_num = NULL;
++ }
++
++ /*
++ * For the RSA key by reference code, public components 'n'/'e'
++ * are the key components we use to check for the cache hit. We
++ * must free those as well.
++ */
++ if (sp->opdata_rsa_pn_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pn_num);
++ sp->opdata_rsa_pn_num = NULL;
++ }
++ if (sp->opdata_rsa_pe_num != NULL)
++ {
++ BN_free(sp->opdata_rsa_pe_num);
++ sp->opdata_rsa_pe_num = NULL;
++ }
++ }
++
++ return (ret);
++ }
++
++/*
++ * Destroy RSA key object wrapper. If session is NULL, try to destroy all
++ * objects in the free list.
++ */
++int
++pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 1;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++ CK_BBOOL uselock = TRUE;
++
++ if (session != NULL)
++ local_free_session = session;
++ else
++ {
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ local_free_session = session_cache[OP_RSA].head;
++ uselock = FALSE;
++ }
++
++ /*
++ * go through the list of sessions and delete key objects
++ */
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ /*
++ * Do not terminate list traversal if one of the
++ * destroy operations fails.
++ */
++ if (pk11_destroy_rsa_object_pub(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ if (pk11_destroy_rsa_object_priv(sp, uselock) == 0)
++ {
++ ret = 0;
++ continue;
++ }
++ }
++
++#ifndef NOPTHREADS
++ if (session == NULL)
++ OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0);
++#else
++ if (session == NULL)
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (ret);
++ }
++
++static int
++pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh,
++ CK_BBOOL persistent)
++ {
++ CK_RV rv;
++
++ /*
++ * We never try to destroy persistent objects which are the objects
++ * stored in the keystore. Also, we always use read-only sessions so
++ * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here.
++ */
++ if (persistent == CK_TRUE)
++ return (1);
++
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT,
++ rv);
++ return (0);
++ }
++
++ return (1);
++ }
++
++
++/*
++ * Public key mechanisms optionally supported
++ *
++ * CKM_RSA_PKCS
++ *
++ * The first slot that supports at least one of those mechanisms is chosen as a
++ * public key slot.
++ *
++ * The output of this function is a set of global variables indicating which
++ * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of
++ * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global
++ * variables carry information about which slot was chosen for (a) public key
++ * mechanisms, (b) random operations, and (c) symmetric ciphers and digests.
++ */
++static int
++pk11_choose_slots(int *any_slot_found)
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ unsigned int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar = 0;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ CK_SLOT_ID current_slot = 0;
++
++ /* let's initialize the output parameter */
++ if (any_slot_found != NULL)
++ *any_slot_found = 0;
++
++ /* Get slot list for memory allocation */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ return (0);
++ }
++
++ /* it's not an error if we didn't find any providers */
++ if (ulSlotCount == 0)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ return (1);
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE);
++ return (0);
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv);
++ OPENSSL_free(pSlotList);
++ return (0);
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME);
++ fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount);
++
++ fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (token_info.flags & CKF_RNG)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++ pk11_have_random = CK_TRUE;
++ rand_SLOTID = current_slot;
++ break;
++ }
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ pubkey_SLOTID = pSlotList[0];
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ current_slot = pSlotList[i];
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i);
++#endif /* DEBUG_SLOT_SELECTION */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ /*
++ * Check if this slot is capable of signing with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN)))
++ {
++ slot_has_rsa = CK_TRUE;
++ }
++
++ if (!found_candidate_slot && slot_has_rsa)
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: potential slot: %d\n", PK11_DBG, current_slot);
++#endif /* DEBUG_SLOT_SELECTION */
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ found_candidate_slot = CK_TRUE;
++ /*
++ * Cache the flags for later use. We might
++ * need those if RSA keys by reference feature
++ * is used.
++ */
++ pubkey_token_flags = token_info.flags;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: setting found_candidate_slot to CK_TRUE\n",
++ PK11_DBG);
++ fprintf(stderr,
++ "%s: best so far slot: %d\n", PK11_DBG,
++ best_slot_sofar);
++ fprintf(stderr, "%s: pubkey flags changed to "
++ "%lu.\n", PK11_DBG, pubkey_token_flags);
++ }
++ else
++ {
++ fprintf(stderr,
++ "%s: no rsa\n", PK11_DBG);
++ }
++#else
++ } /* if */
++#endif /* DEBUG_SLOT_SELECTION */
++ } /* for */
++
++ if (found_candidate_slot == CK_TRUE)
++ {
++ pubkey_SLOTID = best_slot_sofar;
++ }
++
++ /*SLOTID = pSlotList[0];*/
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID);
++ fprintf(stderr,
++ "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID);
++ fprintf(stderr,
++ "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa);
++ fprintf(stderr,
++ "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList != NULL)
++ OPENSSL_free(pSlotList);
++
++ if (any_slot_found != NULL)
++ *any_slot_found = 1;
++ return (1);
++ }
++
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/hw_pk11so.h
+diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.4
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:20 2011
+@@ -0,0 +1,32 @@
++/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */
++
++#define token_lock pk11so_token_lock
++#define find_lock pk11so_find_lock
++#define active_list pk11so_active_list
++#define pubkey_token_flags pk11so_pubkey_token_flags
++#define pubkey_SLOTID pk11so_pubkey_SLOTID
++#define ERR_pk11_error ERR_pk11so_error
++#define PK11err_add_data PK11SOerr_add_data
++#define pk11_get_session pk11so_get_session
++#define pk11_return_session pk11so_return_session
++#define pk11_active_add pk11so_active_add
++#define pk11_active_delete pk11so_active_delete
++#define pk11_active_remove pk11so_active_remove
++#define pk11_free_active_list pk11so_free_active_list
++#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects
++#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub
++#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv
++#define pk11_load_privkey pk11so_load_privkey
++#define pk11_load_pubkey pk11so_load_pubkey
++#define PK11_RSA PK11SO_RSA
++#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects
++#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub
++#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv
++#define PK11_DSA PK11SO_DSA
++#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects
++#define pk11_destroy_dh_object pk11so_destroy_dh_object
++#define PK11_DH PK11SO_DH
++#define pk11_token_relogin pk11so_token_relogin
++#define pFuncList pk11so_pFuncList
++#define pk11_pin pk11so_pin
++#define ENGINE_load_pk11 ENGINE_load_pk11so
+Index: openssl/crypto/engine/hw_pk11so_pub.c
+diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.10
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:05:38 2013
+@@ -0,0 +1,1642 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/* crypto/engine/hw_pk11_pub.c */
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++/* Modified to keep only RNG and RSA Sign */
++
++#ifdef OPENSSL_NO_RSA
++#error RSA is disabled
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/crypto.h>
++#include <cryptlib.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++
++#ifdef OPENSSL_SYS_WIN32
++#define NOPTHREADS
++typedef int pid_t;
++#define HAVE_GETPASSPHRASE
++static char *getpassphrase(const char *prompt);
++#ifndef NULL_PTR
++#define NULL_PTR NULL
++#endif
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType __declspec(dllexport) name
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType __declspec(dllimport) name
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType __declspec(dllimport) (* name)
++#else
++#include <unistd.h>
++#endif
++
++#ifndef NOPTHREADS
++#include <pthread.h>
++#endif
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++#ifndef OPENSSL_NO_HW_PK11SO
++
++#ifdef OPENSSL_SYS_WIN32
++#pragma pack(push, cryptoki, 1)
++#include "cryptoki.h"
++#include "pkcs11.h"
++#pragma pack(pop, cryptoki)
++#else
++#include "cryptoki.h"
++#include "pkcs11.h"
++#endif
++#include "hw_pk11so.h"
++#include "hw_pk11_err.h"
++
++static CK_BBOOL pk11_login_done = CK_FALSE;
++extern CK_SLOT_ID pubkey_SLOTID;
++#ifndef NOPTHREADS
++extern pthread_mutex_t *token_lock;
++#endif
++
++#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
++#define getpassphrase(x) getpass(x)
++#endif
++
++/* RSA stuff */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
++ BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session);
++
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
++
++static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey);
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private);
++
++/* Read mode string to be used for fopen() */
++#if SOLARIS_OPENSSL
++static char *read_mode_flags = "rF";
++#else
++static char *read_mode_flags = "r";
++#endif
++
++/*
++ * increment/create reference for an asymmetric key handle via active list
++ * manipulation. If active list operation fails, unlock (if locked), set error
++ * variable and jump to the specified label.
++ */
++#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \
++ { \
++ if (pk11_active_add(key_handle, alg_type) < 0) \
++ { \
++ var = TRUE; \
++ if (unlock) \
++ UNLOCK_OBJSTORE(alg_type); \
++ goto label; \
++ } \
++ }
++
++/*
++ * Find active list entry according to object handle and return pointer to the
++ * entry otherwise return NULL.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ for (entry = active_list[type]; entry != NULL; entry = entry->next)
++ if (entry->h == h)
++ return (entry);
++
++ return (NULL);
++ }
++
++/*
++ * Search for an entry in the active list using PKCS#11 object handle as a
++ * search key and return refcnt of the found/created entry or -1 in case of
++ * failure.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if (h == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ /* search for entry in the active list */
++ if ((entry = pk11_active_find(h, type)) != NULL)
++ entry->refcnt++;
++ else
++ {
++ /* not found, create new entry and add it to the list */
++ entry = OPENSSL_malloc(sizeof (PK11_active));
++ if (entry == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
++ return (-1);
++ }
++ entry->h = h;
++ entry->refcnt = 1;
++ entry->prev = NULL;
++ entry->next = NULL;
++ /* connect the newly created entry to the list */
++ if (active_list[type] == NULL)
++ active_list[type] = entry;
++ else /* make the entry first in the list */
++ {
++ entry->next = active_list[type];
++ active_list[type]->prev = entry;
++ active_list[type] = entry;
++ }
++ }
++
++ return (entry->refcnt);
++ }
++
++/*
++ * Remove active list entry from the list and free it.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++void
++pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
++ {
++ PK11_active *prev_entry;
++
++ /* remove the entry from the list and free it */
++ if ((prev_entry = entry->prev) != NULL)
++ {
++ prev_entry->next = entry->next;
++ if (entry->next != NULL)
++ entry->next->prev = prev_entry;
++ }
++ else
++ {
++ active_list[type] = entry->next;
++ /* we were the first but not the only one */
++ if (entry->next != NULL)
++ entry->next->prev = NULL;
++ }
++
++ /* sanitization */
++ entry->h = CK_INVALID_HANDLE;
++ entry->prev = NULL;
++ entry->next = NULL;
++ OPENSSL_free(entry);
++ }
++
++/* Free all entries from the active list. */
++void
++pk11_free_active_list(PK11_OPTYPE type)
++ {
++ PK11_active *entry;
++
++ /* only for asymmetric types since only they have C_Find* locks. */
++ switch (type)
++ {
++ case OP_RSA:
++ break;
++ default:
++ return;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(type);
++ while ((entry = active_list[type]) != NULL)
++ pk11_active_remove(entry, type);
++ UNLOCK_OBJSTORE(type);
++ }
++
++/*
++ * Search for active list entry associated with given PKCS#11 object handle,
++ * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
++ *
++ * Return 1 if the PKCS#11 object associated with the entry has no references,
++ * return 0 if there is at least one reference, -1 on error.
++ *
++ * This function presumes it is called with lock protecting the active list
++ * held.
++ */
++int
++pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
++ {
++ PK11_active *entry = NULL;
++
++ if ((entry = pk11_active_find(h, type)) == NULL)
++ {
++ PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
++ return (-1);
++ }
++
++ OPENSSL_assert(entry->refcnt > 0);
++ entry->refcnt--;
++ if (entry->refcnt == 0)
++ {
++ pk11_active_remove(entry, type);
++ return (1);
++ }
++
++ return (0);
++ }
++
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa;
++
++RSA_METHOD *
++PK11_RSA(void)
++ {
++ const RSA_METHOD *rsa;
++
++ if (pk11_rsa.name == NULL)
++ {
++ rsa = RSA_PKCS1_SSLeay();
++ memcpy(&pk11_rsa, rsa, sizeof(*rsa));
++ pk11_rsa.name = "PKCS#11 RSA method";
++ pk11_rsa.rsa_sign = pk11_RSA_sign;
++ }
++ return (&pk11_rsa);
++ }
++
++/* Size of an SSL signature: MD5+SHA1 */
++#define SSL_SIG_LENGTH 36
++
++static CK_BBOOL mytrue = TRUE;
++static CK_BBOOL myfalse = FALSE;
++
++/*
++ * Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c
++ */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i, j = 0;
++ unsigned char *p, *s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor = &algor;
++ sig.algor->algorithm = OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type = V_ASN1_NULL;
++ parameter.value.ptr = NULL;
++ sig.algor->parameter = &parameter;
++
++ sig.digest = &digest;
++ sig.digest->data = (unsigned char *)m;
++ sig.digest->length = m_len;
++
++ i = i2d_X509_SIG(&sig, NULL);
++ }
++
++ j = RSA_size(rsa);
++ if ((i - RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p = s;
++ (void) i2d_X509_SIG(&sig, &p);
++ }
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ goto err;
++
++ (void) check_new_rsa_key_priv(sp, rsa);
++
++ h_priv_key = sp->opdata_rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa,
++ &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num,
++ sp->session);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if ((type != NID_md5_sha1) && (s != NULL))
++ {
++ (void) memset(s, 0, (unsigned int)(j + 1));
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (ret);
++ }
++
++static int hndidx_rsa = -1;
++
++#define MAXATTR 1024
++
++/*
++ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BBOOL rollback = FALSE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize the OpenSSL RSA
++ * structure with something we can use to look up the key. Note that we
++ * never ask for private components.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_TRUE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, NULL);
++
++ /*
++ * We might have a cache hit which we could confirm
++ * according to the 'n'/'e' params, RSA public pointer
++ * as NULL, and non-NULL RSA private pointer. However,
++ * it is easier just to recreate everything. We expect
++ * the keys to be loaded once and used many times. We
++ * do not check the return value because even in case
++ * of failure the sp structure will have both key
++ * pointer and object handle cleaned and
++ * pk11_destroy_object() reports the failure to the
++ * OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, FALSE);
++
++ sp->opdata_rsa_priv_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->priv_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA private structure pointer. We do not
++ * use it now for key-by-ref keys but let's do it for
++ * consistency reasons.
++ */
++ if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PRIVKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ /*
++ * We do not use pk11_get_private_rsa_key() here so we
++ * must take care of handle management ourselves.
++ */
++ KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err);
++
++ /*
++ * Those are the sensitive components we do not want to export
++ * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
++ */
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ /*
++ * Must have 'n'/'e' components in the session structure as
++ * well. They serve as a public look-up key for the private key
++ * in the keystore.
++ */
++ attr_to_BN(&get_templ[0], attr_data[0],
++ &sp->opdata_rsa_pn_num);
++ attr_to_BN(&get_templ[1], attr_data[1],
++ &sp->opdata_rsa_pe_num);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++ }
++ else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ (void) fclose(privkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_priv(sp, rsa);
++ sp->priv_persistent = CK_FALSE;
++
++ h_priv_key = sp->opdata_rsa_priv_key =
++ pk11_get_private_rsa_key(rsa,
++ &sp->opdata_rsa_priv,
++ &sp->opdata_rsa_d_num,
++ &sp->opdata_rsa_pn_num,
++ &sp->opdata_rsa_pe_num, sp->session);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ rollback = rollback;
++ return (pkey);
++ }
++
++/*
++ * Load RSA public key from a file or get its PKCS#11 handle if stored in the
++ * PKCS#11 token.
++ */
++/* ARGSUSED */
++EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey = NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa = NULL;
++ PK11_SESSION *sp;
++ /* Anything else below is needed for the key by reference extension. */
++ CK_RV rv;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][MAXATTR];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++
++ /* we look for public keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /*
++ * These public attributes are needed to initialize OpenSSL RSA
++ * structure with something we can use to look up the key.
++ */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */
++ };
++
++ if ((sp = pk11_get_session(OP_RSA)) == NULL)
++ return (NULL);
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_token_login(sp->session, &pk11_login_done,
++ CK_FALSE) == 0)
++ goto err;
++
++ /* see find_lock array definition
++ for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * Now let's try to find the key in the token. It is a failure
++ * if we can't find it.
++ */
++ if (find_one_object(OP_RSA, sp->session, search_templ, 3,
++ &ks_key) == 0)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * We load a new public key so we will create a new RSA
++ * structure. No cache hit is possible.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, FALSE);
++
++ sp->opdata_rsa_pub_key = ks_key;
++ /* This object shall not be deleted on a cache miss. */
++ sp->pub_persistent = CK_TRUE;
++
++ /*
++ * Cache the RSA public structure pointer.
++ */
++ if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ UNLOCK_OBJSTORE(OP_RSA);
++ PK11err_add_data(PK11_F_LOAD_PUBKEY,
++ PK11_R_GETATTRIBUTVALUE, rv);
++ goto err;
++ }
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++ if ((pkey = EVP_PKEY_new()) == NULL)
++ goto err;
++
++ if (EVP_PKEY_assign_RSA(pkey, rsa) == 0)
++ goto err;
++
++ /*
++ * Create a session object from it so that when calling
++ * pk11_get_public_rsa_key() the next time, we can find it. The
++ * reason why we do that is that we cannot tell from the RSA
++ * structure (OpenSSL RSA structure does not have any room for
++ * additional data used by the engine, for example) if it bears
++ * a public key stored in the keystore or not so it's better if
++ * we always have a session key. Note that this is different
++ * from what we do for the private keystore objects but in that
++ * case, we can tell from the RSA structure that the keystore
++ * object is in play - the 'd' component is NULL in that case.
++ */
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ (void) fclose(pubkey);
++ if (pkey != NULL)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa != NULL)
++ {
++ /*
++ * This will always destroy the RSA
++ * object since we have a new RSA
++ * structure here.
++ */
++ (void) check_new_rsa_key_pub(sp, rsa);
++ sp->pub_persistent = CK_FALSE;
++
++ h_pub_key = sp->opdata_rsa_pub_key =
++ pk11_get_public_rsa_key(rsa,
++ &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
++ &sp->opdata_rsa_e_num, sp->session);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ goto err;
++ }
++ else
++ goto err;
++ }
++ }
++
++ pk11_return_session(sp, OP_RSA);
++ return (pkey);
++err:
++ pk11_return_session(sp, OP_RSA);
++ if (rsa != NULL)
++ RSA_free(rsa);
++ if (pkey != NULL)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ return (pkey);
++ }
++
++/*
++ * Create a public key object in a session from a given rsa structure.
++ * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa,
++ RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
++ CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 8;
++ CK_BBOOL rollback = FALSE;
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_ENCRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY, &mytrue, sizeof (mytrue)},
++ {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[6].pValue);
++
++ a_key_template[7].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[7].ulValueLen);
++ if (a_key_template[7].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[7].pValue);
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++ if (rsa_n_num != NULL)
++ if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ if (rsa_e_num != NULL)
++ if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ BN_free(*rsa_n_num);
++ *rsa_n_num = NULL;
++ rollback = TRUE;
++ goto err;
++ }
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ for (i = 6; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Create a private key object in the session from a given rsa structure.
++ * The *rsa_d_num pointer is non-NULL for RSA private keys.
++ */
++static CK_OBJECT_HANDLE
++pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num,
++ BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ CK_BBOOL rollback = FALSE;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
++ {CKA_TOKEN, &myfalse, sizeof (myfalse)},
++ {CKA_SENSITIVE, &myfalse, sizeof (myfalse)},
++ {CKA_DECRYPT, &mytrue, sizeof (mytrue)},
++ {CKA_SIGN, &mytrue, sizeof (mytrue)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0},
++ };
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa);
++ LOCK_OBJSTORE(OP_RSA);
++ goto set;
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto malloc_err;
++ }
++
++ /* see find_lock array definition for more info on object locking */
++ LOCK_OBJSTORE(OP_RSA);
++
++ /*
++ * We are getting the private key but the private 'd'
++ * component is NULL. That means this is key by reference RSA
++ * key. In that case, we can use only public components for
++ * searching for the private key handle.
++ */
++ if (rsa->d == NULL)
++ {
++ ul_key_attr_count = 8;
++ /*
++ * We will perform the search in the token, not in the existing
++ * session keys.
++ */
++ a_key_template[2].pValue = &mytrue;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSINIT, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(session);
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTS, rv);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_FINDOBJECTSFINAL, rv);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ /*
++ * We have an RSA structure with 'n'/'e' components
++ * only so we tried to find the private key in the
++ * keystore. If it was really a token key we have a
++ * problem. Note that for other key types we just
++ * create a new session key using the private
++ * components from the RSA structure.
++ */
++ if (rsa->d == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_PRIV_KEY_NOT_FOUND);
++ goto err;
++ }
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT, rv);
++ goto err;
++ }
++ }
++
++set:
++ if (rsa_d_num != NULL)
++ {
++ /*
++ * When RSA keys by reference code is used, we never
++ * extract private components from the keystore. In
++ * that case 'd' was set to NULL and we expect the
++ * application to properly cope with that. It is
++ * documented in openssl(5). In general, if keys by
++ * reference are used we expect it to be used
++ * exclusively using the high level API and then there
++ * is no problem. If the application expects the
++ * private components to be read from the keystore
++ * then that is not a supported way of usage.
++ */
++ if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ rollback = TRUE;
++ goto err;
++ }
++ else
++ *rsa_d_num = NULL;
++ }
++
++ /*
++ * For the key by reference code, we need public components as well
++ * since 'd' component is always NULL. For that reason, we always cache
++ * 'n'/'e' components as well.
++ */
++ *rsa_n_num = BN_dup(rsa->n);
++ *rsa_e_num = BN_dup(rsa->e);
++
++ /* LINTED: E_CONSTANT_CONDITION */
++ KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
++ if (key_ptr != NULL)
++ *key_ptr = rsa;
++
++err:
++ if (rollback)
++ {
++ /*
++ * We do not care about the return value from C_DestroyObject()
++ * since we are doing rollback.
++ */
++ if (found == 0 &&
++ (rsa->flags & RSA_FLAG_EXT_PKEY) == 0)
++ (void) pFuncList->C_DestroyObject(session, h_key);
++ h_key = CK_INVALID_HANDLE;
++ }
++
++ UNLOCK_OBJSTORE(OP_RSA);
++
++malloc_err:
++ /*
++ * 6 to 13 entries in the key template are key components.
++ * They need to be freed upon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ (void) memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return (h_key);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making the
++ * check for cache hit stronger. Only public components of RSA
++ * key matter here so it is sufficient to compare them with values
++ * cached in PK11_SESSION structure.
++ *
++ * We must check the handle as well since with key by reference, public
++ * components 'n'/'e' are cached in private keys as well. That means we
++ * could have a cache hit in a private key when looking for a public
++ * key. That would not work, you cannot have one PKCS#11 object for
++ * both data signing and verifying.
++ */
++ if ((sp->opdata_rsa_pub != rsa) ||
++ (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_pub(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Check for cache miss and clean the object pointer and handle
++ * in such case. Return 1 for cache hit, 0 for cache miss.
++ */
++static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
++ {
++ /*
++ * Provide protection against RSA structure reuse by making
++ * the check for cache hit stronger. Comparing public exponent
++ * of RSA key with value cached in PK11_SESSION structure
++ * should be sufficient. Note that we want to compare the
++ * public component since with the keys by reference
++ * mechanism, private components are not in the RSA
++ * structure. Also, see check_new_rsa_key_pub() about why we
++ * compare the handle as well.
++ */
++ if ((sp->opdata_rsa_priv != rsa) ||
++ (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) ||
++ (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) ||
++ (sp->opdata_rsa_pn_num == NULL) ||
++ (sp->opdata_rsa_pe_num == NULL) ||
++ (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE))
++ {
++ /*
++ * We do not check the return value because even in case of
++ * failure the sp structure will have both key pointer
++ * and object handle cleaned and pk11_destroy_object()
++ * reports the failure to the OpenSSL error message buffer.
++ */
++ (void) pk11_destroy_rsa_object_priv(sp, TRUE);
++ return (0);
++ }
++ return (1);
++ }
++
++/*
++ * Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int
++init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = 0;
++
++ /*
++ * This function can be used on non-initialized BIGNUMs. It is
++ * easier to check that here than individually in the callers.
++ */
++ if (bn != NULL)
++ len = BN_num_bytes(bn);
++
++ if (bn == NULL || len == 0)
++ return (1);
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
++ if (*p_value == NULL)
++ return (0);
++
++ BN_bn2bin(bn, *p_value);
++
++ return (1);
++ }
++
++static void
++attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++
++/*
++ * Find one object in the token. It is an error if we can not find the
++ * object or if we find more objects based on the template we got.
++ * Assume object store locked.
++ *
++ * Returns:
++ * 1 OK
++ * 0 no object or more than 1 object found
++ */
++static int
++find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s,
++ CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey)
++ {
++ CK_RV rv;
++ CK_ULONG objcnt;
++
++ if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_FINDOBJECTSINIT, rv);
++ return (0);
++ }
++
++ rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ (void) pFuncList->C_FindObjectsFinal(s);
++ PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS,
++ rv);
++ return (0);
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(s);
++
++ if (objcnt > 1)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT,
++ PK11_R_MORE_THAN_ONE_OBJECT_FOUND);
++ return (0);
++ }
++ else if (objcnt == 0)
++ {
++ PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND);
++ return (0);
++ }
++ return (1);
++ }
++
++/* from uri stuff */
++
++extern char *pk11_pin;
++
++static int pk11_get_pin(void);
++
++static int
++pk11_get_pin(void)
++{
++ char *pin;
++
++ /* The getpassphrase() function is not MT safe. */
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ pin = getpassphrase("Enter PIN: ");
++ if (pin == NULL)
++ {
++ PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ pk11_pin = BUF_strdup(pin);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++ memset(pin, 0, strlen(pin));
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (1);
++ }
++
++/*
++ * Log in to the keystore if we are supposed to do that at all. Take care of
++ * reading and caching the PIN etc. Log in only once even when called from
++ * multiple threads.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++static int
++pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
++ CK_BBOOL is_private)
++ {
++ CK_RV rv;
++
++#if 0
++ /* doesn't work on the AEP Keyper??? */
++ if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0)
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_NOT_INITIALIZED);
++ return (0);
++ }
++#endif
++
++ /*
++ * If login is required or needed but the PIN has not been
++ * even initialized we can bail out right now. Note that we
++ * are supposed to always log in if we are going to access
++ * private keys. However, we may need to log in even for
++ * accessing public keys in case that the CKF_LOGIN_REQUIRED
++ * flag is set.
++ */
++ if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE)) &&
++ (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
++ return (0);
++ }
++
++ /*
++ * Note on locking: it is possible that more than one thread
++ * gets into pk11_get_pin() so we must deal with that. We
++ * cannot avoid it since we cannot guard fork() in there with
++ * a lock because we could end up in a dead lock in the
++ * child. Why? Remember we are in a multithreaded environment
++ * so we must lock all mutexes in the prefork function to
++ * avoid a situation in which a thread that did not call
++ * fork() held a lock, making future unlocking impossible. We
++ * lock right before C_Login().
++ */
++ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) ||
++ (is_private == CK_TRUE))
++ {
++ if (*login_done == CK_FALSE)
++ {
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ {
++ PK11err(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_PIN_NOT_PROVIDED);
++ return (0);
++ }
++ }
++
++ /*
++ * Note that what we are logging into is the keystore from
++ * pubkey_SLOTID because we work with OP_RSA session type here.
++ * That also means that we can work with only one keystore in
++ * the engine.
++ *
++ * We must make sure we do not try to login more than once.
++ * Also, see the comment above on locking strategy.
++ */
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if (*login_done == CK_FALSE)
++ {
++ if ((rv = pFuncList->C_Login(session,
++ CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_LOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++ goto err_locked;
++ }
++
++ *login_done = CK_TRUE;
++
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ }
++ else
++ {
++ /*
++ * If token does not require login we take it as the
++ * login was done.
++ */
++ *login_done = CK_TRUE;
++ }
++
++ return (1);
++
++err_locked:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++
++/*
++ * Log in to the keystore in the child if we were logged in in the
++ * parent. There are similarities in the code with pk11_token_login()
++ * but still it is quite different so we need a separate function for
++ * this.
++ *
++ * Note that this function is called under the locked session mutex when fork is
++ * detected. That means that C_Login() will be called from the child just once.
++ *
++ * Returns:
++ * 1 on success
++ * 0 on failure
++ */
++int
++pk11_token_relogin(CK_SESSION_HANDLE session)
++ {
++ CK_RV rv;
++
++ if ((pk11_pin == NULL) && (pk11_get_pin() == 0))
++ return (0);
++
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_lock(token_lock) == 0);
++#else
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ if ((rv = pFuncList->C_Login(session, CKU_USER,
++ (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK)
++ {
++ PK11err_add_data(PK11_F_TOKEN_RELOGIN,
++ PK11_R_TOKEN_LOGIN_FAILED, rv);
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++ return (0);
++ }
++#ifndef NOPTHREADS
++ OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0);
++#else
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++#endif
++
++ return (1);
++ }
++
++#ifdef OPENSSL_SYS_WIN32
++char *getpassphrase(const char *prompt)
++ {
++ static char buf[128];
++ HANDLE h;
++ DWORD cc, mode;
++ int cnt;
++
++ h = GetStdHandle(STD_INPUT_HANDLE);
++ fputs(prompt, stderr);
++ fflush(stderr);
++ fflush(stdout);
++ FlushConsoleInputBuffer(h);
++ GetConsoleMode(h, &mode);
++ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
++
++ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
++ {
++ ReadFile(h, buf + cnt, 1, &cc, NULL);
++ if (buf[cnt] == '\r')
++ break;
++ fputc('*', stdout);
++ fflush(stderr);
++ fflush(stdout);
++ }
++
++ SetConsoleMode(h, mode);
++ buf[cnt] = '\0';
++ fputs("\n", stderr);
++ return buf;
++ }
++#endif /* OPENSSL_SYS_WIN32 */
++#endif /* OPENSSL_NO_HW_PK11SO */
++#endif /* OPENSSL_NO_HW_PK11 */
++#endif /* OPENSSL_NO_HW */
+Index: openssl/crypto/engine/pkcs11.h
+diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,299 @@
++/* pkcs11.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++#ifndef _PKCS11_H_
++#define _PKCS11_H_ 1
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Before including this file (pkcs11.h) (or pkcs11t.h by
++ * itself), 6 platform-specific macros must be defined. These
++ * macros are described below, and typical definitions for them
++ * are also given. Be advised that these definitions can depend
++ * on both the platform and the compiler used (and possibly also
++ * on whether a Cryptoki library is linked statically or
++ * dynamically).
++ *
++ * In addition to defining these 6 macros, the packing convention
++ * for Cryptoki structures should be set. The Cryptoki
++ * convention on packing is that structures should be 1-byte
++ * aligned.
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, this might be done by using the following
++ * preprocessor directive before including pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(push, cryptoki, 1)
++ *
++ * and using the following preprocessor directive after including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(pop, cryptoki)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, this might be done by using
++ * the following preprocessor directive before including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(1)
++ *
++ * In a UNIX environment, you're on your own for this. You might
++ * not need to do (or be able to do!) anything.
++ *
++ *
++ * Now for the macros:
++ *
++ *
++ * 1. CK_PTR: The indirection string for making a pointer to an
++ * object. It can be used like this:
++ *
++ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, it might be defined by:
++ *
++ * #define CK_PTR far *
++ *
++ * In a typical UNIX environment, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ *
++ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
++ * an exportable Cryptoki library function definition out of a
++ * return type and a function name. It should be used in the
++ * following fashion to define the exposed Cryptoki functions in
++ * a Cryptoki library:
++ *
++ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * )
++ * {
++ * ...
++ * }
++ *
++ * If you're using Microsoft Developer Studio 5.0 to define a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllexport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to define a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
++ * an importable Cryptoki library function declaration out of a
++ * return type and a function name. It should be used in the
++ * following fashion:
++ *
++ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * );
++ *
++ * If you're using Microsoft Developer Studio 5.0 to declare a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllimport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to declare a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
++ * which makes a Cryptoki API function pointer declaration or
++ * function pointer type declaration out of a return type and a
++ * function name. It should be used in the following fashion:
++ *
++ * // Define funcPtr to be a pointer to a Cryptoki API function
++ * // taking arguments args and returning CK_RV.
++ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
++ *
++ * or
++ *
++ * // Define funcPtrType to be the type of a pointer to a
++ * // Cryptoki API function taking arguments args and returning
++ * // CK_RV, and then define funcPtr to be a variable of type
++ * // funcPtrType.
++ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
++ * funcPtrType funcPtr;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to access
++ * functions in a Win32 Cryptoki .dll, in might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __declspec(dllimport) (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to access functions in a Win16 Cryptoki .dll, it might
++ * be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __export _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
++ * a function pointer type for an application callback out of
++ * a return type for the callback and a name for the callback.
++ * It should be used in the following fashion:
++ *
++ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
++ *
++ * to declare a function pointer, myCallback, to a callback
++ * which takes arguments args and returns a CK_RV. It can also
++ * be used like this:
++ *
++ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
++ * myCallbackType myCallback;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to do Win32
++ * Cryptoki development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to do Win16 development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 6. NULL_PTR: This macro is the value of a NULL pointer.
++ *
++ * In any ANSI/ISO C environment (and in many others as well),
++ * this should best be defined by
++ *
++ * #ifndef NULL_PTR
++ * #define NULL_PTR 0
++ * #endif
++ */
++
++
++/* All the various Cryptoki types and #define'd values are in the
++ * file pkcs11t.h. */
++#include "pkcs11t.h"
++
++#define __PASTE(x,y) x##y
++
++
++/* ==============================================================
++ * Define the "extern" form of all the entry points.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ extern CK_DECLARE_FUNCTION(CK_RV, name)
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define the typedef form of all the entry points. That is, for
++ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
++ * a pointer to that kind of function.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define structed vector of entry points. A CK_FUNCTION_LIST
++ * contains a CK_VERSION indicating a library's Cryptoki version
++ * and then a whole slew of function pointers to the routines in
++ * the library. This type was declared, but not defined, in
++ * pkcs11t.h.
++ * ==============================================================
++ */
++
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ __PASTE(CK_,name) name;
++
++struct CK_FUNCTION_LIST {
++
++ CK_VERSION version; /* Cryptoki version */
++
++/* Pile all the function pointers into the CK_FUNCTION_LIST. */
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++};
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++#undef __PASTE
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+Index: openssl/crypto/engine/pkcs11f.h
+diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007
+@@ -0,0 +1,912 @@
++/* pkcs11f.h include file for PKCS #11. */
++/* $Revision: 1.1.1.1 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This header file contains pretty much everything about all the */
++/* Cryptoki function prototypes. Because this information is */
++/* used for more than just declaring function prototypes, the */
++/* order of the functions appearing herein is important, and */
++/* should not be altered. */
++
++/* General-purpose */
++
++/* C_Initialize initializes the Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Initialize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
++ * cast to CK_C_INITIALIZE_ARGS_PTR
++ * and dereferenced */
++);
++#endif
++
++
++/* C_Finalize indicates that an application is done with the
++ * Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Finalize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
++);
++#endif
++
++
++/* C_GetInfo returns general information about Cryptoki. */
++CK_PKCS11_FUNCTION_INFO(C_GetInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_INFO_PTR pInfo /* location that receives information */
++);
++#endif
++
++
++/* C_GetFunctionList returns the function list. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
++ * function list */
++);
++#endif
++
++
++
++/* Slot and token management */
++
++/* C_GetSlotList obtains a list of slots in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_BBOOL tokenPresent, /* only slots with tokens? */
++ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
++ CK_ULONG_PTR pulCount /* receives number of slots */
++);
++#endif
++
++
++/* C_GetSlotInfo obtains information about a particular slot in
++ * the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the ID of the slot */
++ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
++);
++#endif
++
++
++/* C_GetTokenInfo obtains information about a particular token
++ * in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
++);
++#endif
++
++
++/* C_GetMechanismList obtains a list of mechanism types
++ * supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of token's slot */
++ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
++ CK_ULONG_PTR pulCount /* gets # of mechs. */
++);
++#endif
++
++
++/* C_GetMechanismInfo obtains information about a particular
++ * mechanism possibly supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_MECHANISM_TYPE type, /* type of mechanism */
++ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
++);
++#endif
++
++
++/* C_InitToken initializes a token. */
++CK_PKCS11_FUNCTION_INFO(C_InitToken)
++#ifdef CK_NEED_ARG_LIST
++/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
++ CK_ULONG ulPinLen, /* length in bytes of the PIN */
++ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
++);
++#endif
++
++
++/* C_InitPIN initializes the normal user's PIN. */
++CK_PKCS11_FUNCTION_INFO(C_InitPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
++ CK_ULONG ulPinLen /* length in bytes of the PIN */
++);
++#endif
++
++
++/* C_SetPIN modifies the PIN of the user who is logged in. */
++CK_PKCS11_FUNCTION_INFO(C_SetPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
++ CK_ULONG ulOldLen, /* length of the old PIN */
++ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
++ CK_ULONG ulNewLen /* length of the new PIN */
++);
++#endif
++
++
++
++/* Session management */
++
++/* C_OpenSession opens a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_OpenSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the slot's ID */
++ CK_FLAGS flags, /* from CK_SESSION_INFO */
++ CK_VOID_PTR pApplication, /* passed to callback */
++ CK_NOTIFY Notify, /* callback function */
++ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
++);
++#endif
++
++
++/* C_CloseSession closes a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CloseAllSessions closes all sessions with a token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID /* the token's slot */
++);
++#endif
++
++
++/* C_GetSessionInfo obtains information about the session. */
++CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_SESSION_INFO_PTR pInfo /* receives session info */
++);
++#endif
++
++
++/* C_GetOperationState obtains the state of the cryptographic operation
++ * in a session. */
++CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* gets state */
++ CK_ULONG_PTR pulOperationStateLen /* gets state length */
++);
++#endif
++
++
++/* C_SetOperationState restores the state of the cryptographic
++ * operation in a session. */
++CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* holds state */
++ CK_ULONG ulOperationStateLen, /* holds state length */
++ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
++ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
++);
++#endif
++
++
++/* C_Login logs a user into a token. */
++CK_PKCS11_FUNCTION_INFO(C_Login)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_USER_TYPE userType, /* the user type */
++ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
++ CK_ULONG ulPinLen /* the length of the PIN */
++);
++#endif
++
++
++/* C_Logout logs a user out from a token. */
++CK_PKCS11_FUNCTION_INFO(C_Logout)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Object management */
++
++/* C_CreateObject creates a new object. */
++CK_PKCS11_FUNCTION_INFO(C_CreateObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
++);
++#endif
++
++
++/* C_CopyObject copies an object, creating a new object for the
++ * copy. */
++CK_PKCS11_FUNCTION_INFO(C_CopyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
++);
++#endif
++
++
++/* C_DestroyObject destroys an object. */
++CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject /* the object's handle */
++);
++#endif
++
++
++/* C_GetObjectSize gets the size of an object in bytes. */
++CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ULONG_PTR pulSize /* receives size of object */
++);
++#endif
++
++
++/* C_GetAttributeValue obtains the value of one or more object
++ * attributes. */
++CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_SetAttributeValue modifies the value of one or more object
++ * attributes */
++CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_FindObjectsInit initializes a search for token and session
++ * objects that match a template. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
++ CK_ULONG ulCount /* attrs in search template */
++);
++#endif
++
++
++/* C_FindObjects continues a search for token and session
++ * objects that match a template, obtaining additional object
++ * handles. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjects)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
++ CK_ULONG ulMaxObjectCount, /* max handles to get */
++ CK_ULONG_PTR pulObjectCount /* actual # returned */
++);
++#endif
++
++
++/* C_FindObjectsFinal finishes a search for token and session
++ * objects. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Encryption and decryption */
++
++/* C_EncryptInit initializes an encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of encryption key */
++);
++#endif
++
++
++/* C_Encrypt encrypts single-part data. */
++CK_PKCS11_FUNCTION_INFO(C_Encrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pData, /* the plaintext data */
++ CK_ULONG ulDataLen, /* bytes of plaintext */
++ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptUpdate continues a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext data len */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptFinal finishes a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session handle */
++ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
++ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
++);
++#endif
++
++
++/* C_DecryptInit initializes a decryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of decryption key */
++);
++#endif
++
++
++/* C_Decrypt decrypts encrypted data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Decrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedData, /* ciphertext */
++ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
++ CK_BYTE_PTR pData, /* gets plaintext */
++ CK_ULONG_PTR pulDataLen /* gets p-text size */
++);
++#endif
++
++
++/* C_DecryptUpdate continues a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
++ CK_ULONG ulEncryptedPartLen, /* input length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* p-text size */
++);
++#endif
++
++
++/* C_DecryptFinal finishes a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pLastPart, /* gets plaintext */
++ CK_ULONG_PTR pulLastPartLen /* p-text size */
++);
++#endif
++
++
++
++/* Message digesting */
++
++/* C_DigestInit initializes a message-digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
++);
++#endif
++
++
++/* C_Digest digests data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Digest)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* data to be digested */
++ CK_ULONG ulDataLen, /* bytes of data to digest */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets digest length */
++);
++#endif
++
++
++/* C_DigestUpdate continues a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* data to be digested */
++ CK_ULONG ulPartLen /* bytes of data to be digested */
++);
++#endif
++
++
++/* C_DigestKey continues a multi-part message-digesting
++ * operation, by digesting the value of a secret key as part of
++ * the data already digested. */
++CK_PKCS11_FUNCTION_INFO(C_DigestKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hKey /* secret key to digest */
++);
++#endif
++
++
++/* C_DigestFinal finishes a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
++);
++#endif
++
++
++
++/* Signing and MACing */
++
++/* C_SignInit initializes a signature (private key encryption)
++ * operation, where the signature is (will be) an appendix to
++ * the data, and plaintext cannot be recovered from the
++ *signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of signature key */
++);
++#endif
++
++
++/* C_Sign signs (encrypts with private key) data in a single
++ * part, where the signature is (will be) an appendix to the
++ * data, and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Sign)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignUpdate continues a multiple-part signature operation,
++ * where the signature is (will be) an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* the data to sign */
++ CK_ULONG ulPartLen /* count of bytes to sign */
++);
++#endif
++
++
++/* C_SignFinal finishes a multiple-part signature operation,
++ * returning the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignRecoverInit initializes a signature operation, where
++ * the data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of the signature key */
++);
++#endif
++
++
++/* C_SignRecover signs data in a single operation, where the
++ * data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++
++/* Verifying signatures and MACs */
++
++/* C_VerifyInit initializes a verification operation, where the
++ * signature is an appendix to the data, and plaintext cannot
++ * cannot be recovered from the signature (e.g. DSA). */
++CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_Verify verifies a signature in a single-part operation,
++ * where the signature is an appendix to the data, and plaintext
++ * cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Verify)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* signed data */
++ CK_ULONG ulDataLen, /* length of signed data */
++ CK_BYTE_PTR pSignature, /* signature */
++ CK_ULONG ulSignatureLen /* signature length*/
++);
++#endif
++
++
++/* C_VerifyUpdate continues a multiple-part verification
++ * operation, where the signature is an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* signed data */
++ CK_ULONG ulPartLen /* length of signed data */
++);
++#endif
++
++
++/* C_VerifyFinal finishes a multiple-part verification
++ * operation, checking the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen /* signature length */
++);
++#endif
++
++
++/* C_VerifyRecoverInit initializes a signature verification
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_VerifyRecover verifies a signature in a single-part
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen, /* signature length */
++ CK_BYTE_PTR pData, /* gets signed data */
++ CK_ULONG_PTR pulDataLen /* gets signed data len */
++);
++#endif
++
++
++
++/* Dual-function cryptographic operations */
++
++/* C_DigestEncryptUpdate continues a multiple-part digesting
++ * and encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptDigestUpdate continues a multiple-part decryption and
++ * digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets plaintext len */
++);
++#endif
++
++
++/* C_SignEncryptUpdate continues a multiple-part signing and
++ * encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptVerifyUpdate continues a multiple-part decryption and
++ * verify operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets p-text length */
++);
++#endif
++
++
++
++/* Key management */
++
++/* C_GenerateKey generates a secret key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
++ CK_ULONG ulCount, /* # of attrs in template */
++ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
++);
++#endif
++
++
++/* C_GenerateKeyPair generates a public-key/private-key pair,
++ * creating new key objects. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session
++ * handle */
++ CK_MECHANISM_PTR pMechanism, /* key-gen
++ * mech. */
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
++ * for pub.
++ * key */
++ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
++ * attrs. */
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
++ * for priv.
++ * key */
++ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
++ * attrs. */
++ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
++ * key
++ * handle */
++ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
++ * priv. key
++ * handle */
++);
++#endif
++
++
++/* C_WrapKey wraps (i.e., encrypts) a key. */
++CK_PKCS11_FUNCTION_INFO(C_WrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
++ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
++ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
++ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
++ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
++);
++#endif
++
++
++/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
++ * key object. */
++CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
++ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
++ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
++ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++/* C_DeriveKey derives a key from a base key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
++ CK_OBJECT_HANDLE hBaseKey, /* base key */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++
++/* Random number generation */
++
++/* C_SeedRandom mixes additional seed material into the token's
++ * random number generator. */
++CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSeed, /* the seed material */
++ CK_ULONG ulSeedLen /* length of seed material */
++);
++#endif
++
++
++/* C_GenerateRandom generates random data. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR RandomData, /* receives the random data */
++ CK_ULONG ulRandomLen /* # of bytes to generate */
++);
++#endif
++
++
++
++/* Parallel function management */
++
++/* C_GetFunctionStatus is a legacy function; it obtains an
++ * updated status of a function running in parallel with an
++ * application. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CancelFunction is a legacy function; it cancels a function
++ * running in parallel. */
++CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Functions added in for Cryptoki Version 2.01 or later */
++
++/* C_WaitForSlotEvent waits for a slot event (token insertion,
++ * removal, etc.) to occur. */
++CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FLAGS flags, /* blocking/nonblocking flag */
++ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
++ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
++);
++#endif
+Index: openssl/crypto/engine/pkcs11t.h
+diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2
+--- /dev/null Mon Jun 13 15:55:26 2016
++++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008
+@@ -0,0 +1,1885 @@
++/* pkcs11t.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* See top of pkcs11.h for information about the macros that
++ * must be defined and the structure-packing conventions that
++ * must be set before including this file. */
++
++#ifndef _PKCS11T_H_
++#define _PKCS11T_H_ 1
++
++#define CRYPTOKI_VERSION_MAJOR 2
++#define CRYPTOKI_VERSION_MINOR 20
++#define CRYPTOKI_VERSION_AMENDMENT 3
++
++#define CK_TRUE 1
++#define CK_FALSE 0
++
++#ifndef CK_DISABLE_TRUE_FALSE
++#ifndef FALSE
++#define FALSE CK_FALSE
++#endif
++
++#ifndef TRUE
++#define TRUE CK_TRUE
++#endif
++#endif
++
++/* an unsigned 8-bit value */
++typedef unsigned char CK_BYTE;
++
++/* an unsigned 8-bit character */
++typedef CK_BYTE CK_CHAR;
++
++/* an 8-bit UTF-8 character */
++typedef CK_BYTE CK_UTF8CHAR;
++
++/* a BYTE-sized Boolean flag */
++typedef CK_BYTE CK_BBOOL;
++
++/* an unsigned value, at least 32 bits long */
++typedef unsigned long int CK_ULONG;
++
++/* a signed value, the same size as a CK_ULONG */
++/* CK_LONG is new for v2.0 */
++typedef long int CK_LONG;
++
++/* at least 32 bits; each bit is a Boolean flag */
++typedef CK_ULONG CK_FLAGS;
++
++
++/* some special values for certain CK_ULONG variables */
++#define CK_UNAVAILABLE_INFORMATION (~0UL)
++#define CK_EFFECTIVELY_INFINITE 0
++
++
++typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++typedef CK_CHAR CK_PTR CK_CHAR_PTR;
++typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
++typedef CK_ULONG CK_PTR CK_ULONG_PTR;
++typedef void CK_PTR CK_VOID_PTR;
++
++/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
++typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
++
++
++/* The following value is always invalid if used as a session */
++/* handle or object handle */
++#define CK_INVALID_HANDLE 0
++
++
++typedef struct CK_VERSION {
++ CK_BYTE major; /* integer portion of version number */
++ CK_BYTE minor; /* 1/100ths portion of version number */
++} CK_VERSION;
++
++typedef CK_VERSION CK_PTR CK_VERSION_PTR;
++
++
++typedef struct CK_INFO {
++ /* manufacturerID and libraryDecription have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags; /* must be zero */
++
++ /* libraryDescription and libraryVersion are new for v2.0 */
++ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
++ CK_VERSION libraryVersion; /* version of library */
++} CK_INFO;
++
++typedef CK_INFO CK_PTR CK_INFO_PTR;
++
++
++/* CK_NOTIFICATION enumerates the types of notifications that
++ * Cryptoki provides to an application */
++/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_NOTIFICATION;
++#define CKN_SURRENDER 0
++
++/* The following notification is new for PKCS #11 v2.20 amendment 3 */
++#define CKN_OTP_CHANGED 1
++
++
++typedef CK_ULONG CK_SLOT_ID;
++
++typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
++
++
++/* CK_SLOT_INFO provides information about a slot */
++typedef struct CK_SLOT_INFO {
++ /* slotDescription and manufacturerID have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR slotDescription[64]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags;
++
++ /* hardwareVersion and firmwareVersion are new for v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++} CK_SLOT_INFO;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
++#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
++#define CKF_HW_SLOT 0x00000004 /* hardware slot */
++
++typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
++
++
++/* CK_TOKEN_INFO provides information about a token */
++typedef struct CK_TOKEN_INFO {
++ /* label, manufacturerID, and model have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR label[32]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_UTF8CHAR model[16]; /* blank padded */
++ CK_CHAR serialNumber[16]; /* blank padded */
++ CK_FLAGS flags; /* see below */
++
++ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
++ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
++ * changed from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulMaxSessionCount; /* max open sessions */
++ CK_ULONG ulSessionCount; /* sess. now open */
++ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
++ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
++ CK_ULONG ulMaxPinLen; /* in bytes */
++ CK_ULONG ulMinPinLen; /* in bytes */
++ CK_ULONG ulTotalPublicMemory; /* in bytes */
++ CK_ULONG ulFreePublicMemory; /* in bytes */
++ CK_ULONG ulTotalPrivateMemory; /* in bytes */
++ CK_ULONG ulFreePrivateMemory; /* in bytes */
++
++ /* hardwareVersion, firmwareVersion, and time are new for
++ * v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++ CK_CHAR utcTime[16]; /* time */
++} CK_TOKEN_INFO;
++
++/* The flags parameter is defined as follows:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RNG 0x00000001 /* has random #
++ * generator */
++#define CKF_WRITE_PROTECTED 0x00000002 /* token is
++ * write-
++ * protected */
++#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
++ * login */
++#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
++ * PIN is set */
++
++/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
++ * that means that *every* time the state of cryptographic
++ * operations of a session is successfully saved, all keys
++ * needed to continue those operations are stored in the state */
++#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
++
++/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
++ * that the token has some sort of clock. The time on that
++ * clock is returned in the token info structure */
++#define CKF_CLOCK_ON_TOKEN 0x00000040
++
++/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
++ * set, that means that there is some way for the user to login
++ * without sending a PIN through the Cryptoki library itself */
++#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
++
++/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
++ * that means that a single session with the token can perform
++ * dual simultaneous cryptographic operations (digest and
++ * encrypt; decrypt and digest; sign and encrypt; and decrypt
++ * and sign) */
++#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
++
++/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
++ * token has been initialized using C_InitializeToken or an
++ * equivalent mechanism outside the scope of PKCS #11.
++ * Calling C_InitializeToken when this flag is set will cause
++ * the token to be reinitialized. */
++#define CKF_TOKEN_INITIALIZED 0x00000400
++
++/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
++ * true, the token supports secondary authentication for
++ * private key objects. This flag is deprecated in v2.11 and
++ onwards. */
++#define CKF_SECONDARY_AUTHENTICATION 0x00000800
++
++/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect user login PIN has been entered at least once
++ * since the last successful authentication. */
++#define CKF_USER_PIN_COUNT_LOW 0x00010000
++
++/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect user PIN will it to become locked. */
++#define CKF_USER_PIN_FINAL_TRY 0x00020000
++
++/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
++ * user PIN has been locked. User login to the token is not
++ * possible. */
++#define CKF_USER_PIN_LOCKED 0x00040000
++
++/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the user PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
++
++/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect SO login PIN has been entered at least once since
++ * the last successful authentication. */
++#define CKF_SO_PIN_COUNT_LOW 0x00100000
++
++/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect SO PIN will it to become locked. */
++#define CKF_SO_PIN_FINAL_TRY 0x00200000
++
++/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
++ * PIN has been locked. SO login to the token is not possible.
++ */
++#define CKF_SO_PIN_LOCKED 0x00400000
++
++/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the SO PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
++
++typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
++
++
++/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
++ * identifies a session */
++typedef CK_ULONG CK_SESSION_HANDLE;
++
++typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
++
++
++/* CK_USER_TYPE enumerates the types of Cryptoki users */
++/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_USER_TYPE;
++/* Security Officer */
++#define CKU_SO 0
++/* Normal user */
++#define CKU_USER 1
++/* Context specific (added in v2.20) */
++#define CKU_CONTEXT_SPECIFIC 2
++
++/* CK_STATE enumerates the session states */
++/* CK_STATE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_STATE;
++#define CKS_RO_PUBLIC_SESSION 0
++#define CKS_RO_USER_FUNCTIONS 1
++#define CKS_RW_PUBLIC_SESSION 2
++#define CKS_RW_USER_FUNCTIONS 3
++#define CKS_RW_SO_FUNCTIONS 4
++
++
++/* CK_SESSION_INFO provides information about a session */
++typedef struct CK_SESSION_INFO {
++ CK_SLOT_ID slotID;
++ CK_STATE state;
++ CK_FLAGS flags; /* see below */
++
++ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulDeviceError; /* device-dependent error code */
++} CK_SESSION_INFO;
++
++/* The flags are defined in the following table:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RW_SESSION 0x00000002 /* session is r/w */
++#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
++
++typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
++
++
++/* CK_OBJECT_HANDLE is a token-specific identifier for an
++ * object */
++typedef CK_ULONG CK_OBJECT_HANDLE;
++
++typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
++
++
++/* CK_OBJECT_CLASS is a value that identifies the classes (or
++ * types) of objects that Cryptoki recognizes. It is defined
++ * as follows: */
++/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_OBJECT_CLASS;
++
++/* The following classes of objects are defined: */
++/* CKO_HW_FEATURE is new for v2.10 */
++/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
++/* CKO_MECHANISM is new for v2.20 */
++#define CKO_DATA 0x00000000
++#define CKO_CERTIFICATE 0x00000001
++#define CKO_PUBLIC_KEY 0x00000002
++#define CKO_PRIVATE_KEY 0x00000003
++#define CKO_SECRET_KEY 0x00000004
++#define CKO_HW_FEATURE 0x00000005
++#define CKO_DOMAIN_PARAMETERS 0x00000006
++#define CKO_MECHANISM 0x00000007
++
++/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */
++#define CKO_OTP_KEY 0x00000008
++
++#define CKO_VENDOR_DEFINED 0x80000000
++
++typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
++
++/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
++ * value that identifies the hardware feature type of an object
++ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
++typedef CK_ULONG CK_HW_FEATURE_TYPE;
++
++/* The following hardware feature types are defined */
++/* CKH_USER_INTERFACE is new for v2.20 */
++#define CKH_MONOTONIC_COUNTER 0x00000001
++#define CKH_CLOCK 0x00000002
++#define CKH_USER_INTERFACE 0x00000003
++#define CKH_VENDOR_DEFINED 0x80000000
++
++/* CK_KEY_TYPE is a value that identifies a key type */
++/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_KEY_TYPE;
++
++/* the following key types are defined: */
++#define CKK_RSA 0x00000000
++#define CKK_DSA 0x00000001
++#define CKK_DH 0x00000002
++
++/* CKK_ECDSA and CKK_KEA are new for v2.0 */
++/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
++#define CKK_ECDSA 0x00000003
++#define CKK_EC 0x00000003
++#define CKK_X9_42_DH 0x00000004
++#define CKK_KEA 0x00000005
++
++#define CKK_GENERIC_SECRET 0x00000010
++#define CKK_RC2 0x00000011
++#define CKK_RC4 0x00000012
++#define CKK_DES 0x00000013
++#define CKK_DES2 0x00000014
++#define CKK_DES3 0x00000015
++
++/* all these key types are new for v2.0 */
++#define CKK_CAST 0x00000016
++#define CKK_CAST3 0x00000017
++/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
++#define CKK_CAST5 0x00000018
++#define CKK_CAST128 0x00000018
++#define CKK_RC5 0x00000019
++#define CKK_IDEA 0x0000001A
++#define CKK_SKIPJACK 0x0000001B
++#define CKK_BATON 0x0000001C
++#define CKK_JUNIPER 0x0000001D
++#define CKK_CDMF 0x0000001E
++#define CKK_AES 0x0000001F
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKK_BLOWFISH 0x00000020
++#define CKK_TWOFISH 0x00000021
++
++/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */
++#define CKK_SECURID 0x00000022
++#define CKK_HOTP 0x00000023
++#define CKK_ACTI 0x00000024
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_CAMELLIA 0x00000025
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_ARIA 0x00000026
++
++
++#define CKK_VENDOR_DEFINED 0x80000000
++
++
++/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
++ * type */
++/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_CERTIFICATE_TYPE;
++
++/* The following certificate types are defined: */
++/* CKC_X_509_ATTR_CERT is new for v2.10 */
++/* CKC_WTLS is new for v2.20 */
++#define CKC_X_509 0x00000000
++#define CKC_X_509_ATTR_CERT 0x00000001
++#define CKC_WTLS 0x00000002
++#define CKC_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
++ * type */
++/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_ATTRIBUTE_TYPE;
++
++/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
++ consists of an array of values. */
++#define CKF_ARRAY_ATTRIBUTE 0x40000000
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_FORMAT attribute */
++#define CK_OTP_FORMAT_DECIMAL 0
++#define CK_OTP_FORMAT_HEXADECIMAL 1
++#define CK_OTP_FORMAT_ALPHANUMERIC 2
++#define CK_OTP_FORMAT_BINARY 3
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_..._REQUIREMENT attributes */
++#define CK_OTP_PARAM_IGNORED 0
++#define CK_OTP_PARAM_OPTIONAL 1
++#define CK_OTP_PARAM_MANDATORY 2
++
++/* The following attribute types are defined: */
++#define CKA_CLASS 0x00000000
++#define CKA_TOKEN 0x00000001
++#define CKA_PRIVATE 0x00000002
++#define CKA_LABEL 0x00000003
++#define CKA_APPLICATION 0x00000010
++#define CKA_VALUE 0x00000011
++
++/* CKA_OBJECT_ID is new for v2.10 */
++#define CKA_OBJECT_ID 0x00000012
++
++#define CKA_CERTIFICATE_TYPE 0x00000080
++#define CKA_ISSUER 0x00000081
++#define CKA_SERIAL_NUMBER 0x00000082
++
++/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
++ * for v2.10 */
++#define CKA_AC_ISSUER 0x00000083
++#define CKA_OWNER 0x00000084
++#define CKA_ATTR_TYPES 0x00000085
++
++/* CKA_TRUSTED is new for v2.11 */
++#define CKA_TRUSTED 0x00000086
++
++/* CKA_CERTIFICATE_CATEGORY ...
++ * CKA_CHECK_VALUE are new for v2.20 */
++#define CKA_CERTIFICATE_CATEGORY 0x00000087
++#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
++#define CKA_URL 0x00000089
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
++#define CKA_CHECK_VALUE 0x00000090
++
++#define CKA_KEY_TYPE 0x00000100
++#define CKA_SUBJECT 0x00000101
++#define CKA_ID 0x00000102
++#define CKA_SENSITIVE 0x00000103
++#define CKA_ENCRYPT 0x00000104
++#define CKA_DECRYPT 0x00000105
++#define CKA_WRAP 0x00000106
++#define CKA_UNWRAP 0x00000107
++#define CKA_SIGN 0x00000108
++#define CKA_SIGN_RECOVER 0x00000109
++#define CKA_VERIFY 0x0000010A
++#define CKA_VERIFY_RECOVER 0x0000010B
++#define CKA_DERIVE 0x0000010C
++#define CKA_START_DATE 0x00000110
++#define CKA_END_DATE 0x00000111
++#define CKA_MODULUS 0x00000120
++#define CKA_MODULUS_BITS 0x00000121
++#define CKA_PUBLIC_EXPONENT 0x00000122
++#define CKA_PRIVATE_EXPONENT 0x00000123
++#define CKA_PRIME_1 0x00000124
++#define CKA_PRIME_2 0x00000125
++#define CKA_EXPONENT_1 0x00000126
++#define CKA_EXPONENT_2 0x00000127
++#define CKA_COEFFICIENT 0x00000128
++#define CKA_PRIME 0x00000130
++#define CKA_SUBPRIME 0x00000131
++#define CKA_BASE 0x00000132
++
++/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
++#define CKA_PRIME_BITS 0x00000133
++#define CKA_SUBPRIME_BITS 0x00000134
++#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
++/* (To retain backwards-compatibility) */
++
++#define CKA_VALUE_BITS 0x00000160
++#define CKA_VALUE_LEN 0x00000161
++
++/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
++ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
++ * and CKA_EC_POINT are new for v2.0 */
++#define CKA_EXTRACTABLE 0x00000162
++#define CKA_LOCAL 0x00000163
++#define CKA_NEVER_EXTRACTABLE 0x00000164
++#define CKA_ALWAYS_SENSITIVE 0x00000165
++
++/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
++#define CKA_KEY_GEN_MECHANISM 0x00000166
++
++#define CKA_MODIFIABLE 0x00000170
++
++/* CKA_ECDSA_PARAMS is deprecated in v2.11,
++ * CKA_EC_PARAMS is preferred. */
++#define CKA_ECDSA_PARAMS 0x00000180
++#define CKA_EC_PARAMS 0x00000180
++
++#define CKA_EC_POINT 0x00000181
++
++/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
++ * are new for v2.10. Deprecated in v2.11 and onwards. */
++#define CKA_SECONDARY_AUTH 0x00000200
++#define CKA_AUTH_PIN_FLAGS 0x00000201
++
++/* CKA_ALWAYS_AUTHENTICATE ...
++ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
++#define CKA_ALWAYS_AUTHENTICATE 0x00000202
++
++#define CKA_WRAP_WITH_TRUSTED 0x00000210
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++
++/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */
++#define CKA_OTP_FORMAT 0x00000220
++#define CKA_OTP_LENGTH 0x00000221
++#define CKA_OTP_TIME_INTERVAL 0x00000222
++#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
++#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
++#define CKA_OTP_TIME_REQUIREMENT 0x00000225
++#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
++#define CKA_OTP_PIN_REQUIREMENT 0x00000227
++#define CKA_OTP_COUNTER 0x0000022E
++#define CKA_OTP_TIME 0x0000022F
++#define CKA_OTP_USER_IDENTIFIER 0x0000022A
++#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
++#define CKA_OTP_SERVICE_LOGO 0x0000022C
++#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
++
++
++/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
++ * are new for v2.10 */
++#define CKA_HW_FEATURE_TYPE 0x00000300
++#define CKA_RESET_ON_INIT 0x00000301
++#define CKA_HAS_RESET 0x00000302
++
++/* The following attributes are new for v2.20 */
++#define CKA_PIXEL_X 0x00000400
++#define CKA_PIXEL_Y 0x00000401
++#define CKA_RESOLUTION 0x00000402
++#define CKA_CHAR_ROWS 0x00000403
++#define CKA_CHAR_COLUMNS 0x00000404
++#define CKA_COLOR 0x00000405
++#define CKA_BITS_PER_PIXEL 0x00000406
++#define CKA_CHAR_SETS 0x00000480
++#define CKA_ENCODING_METHODS 0x00000481
++#define CKA_MIME_TYPES 0x00000482
++#define CKA_MECHANISM_TYPE 0x00000500
++#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
++#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
++#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
++#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
++
++#define CKA_VENDOR_DEFINED 0x80000000
++
++/* CK_ATTRIBUTE is a structure that includes the type, length
++ * and value of an attribute */
++typedef struct CK_ATTRIBUTE {
++ CK_ATTRIBUTE_TYPE type;
++ CK_VOID_PTR pValue;
++
++ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulValueLen; /* in bytes */
++} CK_ATTRIBUTE;
++
++typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
++
++
++/* CK_DATE is a structure that defines a date */
++typedef struct CK_DATE{
++ CK_CHAR year[4]; /* the year ("1900" - "9999") */
++ CK_CHAR month[2]; /* the month ("01" - "12") */
++ CK_CHAR day[2]; /* the day ("01" - "31") */
++} CK_DATE;
++
++
++/* CK_MECHANISM_TYPE is a value that identifies a mechanism
++ * type */
++/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_MECHANISM_TYPE;
++
++/* the following mechanism types are defined: */
++#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
++#define CKM_RSA_PKCS 0x00000001
++#define CKM_RSA_9796 0x00000002
++#define CKM_RSA_X_509 0x00000003
++
++/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
++ * are new for v2.0. They are mechanisms which hash and sign */
++#define CKM_MD2_RSA_PKCS 0x00000004
++#define CKM_MD5_RSA_PKCS 0x00000005
++#define CKM_SHA1_RSA_PKCS 0x00000006
++
++/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
++ * CKM_RSA_PKCS_OAEP are new for v2.10 */
++#define CKM_RIPEMD128_RSA_PKCS 0x00000007
++#define CKM_RIPEMD160_RSA_PKCS 0x00000008
++#define CKM_RSA_PKCS_OAEP 0x00000009
++
++/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
++ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
++#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
++#define CKM_RSA_X9_31 0x0000000B
++#define CKM_SHA1_RSA_X9_31 0x0000000C
++#define CKM_RSA_PKCS_PSS 0x0000000D
++#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
++
++#define CKM_DSA_KEY_PAIR_GEN 0x00000010
++#define CKM_DSA 0x00000011
++#define CKM_DSA_SHA1 0x00000012
++#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
++#define CKM_DH_PKCS_DERIVE 0x00000021
++
++/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
++ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
++ * v2.11 */
++#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
++#define CKM_X9_42_DH_DERIVE 0x00000031
++#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
++#define CKM_X9_42_MQV_DERIVE 0x00000033
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_RSA_PKCS 0x00000040
++#define CKM_SHA384_RSA_PKCS 0x00000041
++#define CKM_SHA512_RSA_PKCS 0x00000042
++#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
++#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
++#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
++
++/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_RSA_PKCS 0x00000046
++#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
++
++#define CKM_RC2_KEY_GEN 0x00000100
++#define CKM_RC2_ECB 0x00000101
++#define CKM_RC2_CBC 0x00000102
++#define CKM_RC2_MAC 0x00000103
++
++/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
++#define CKM_RC2_MAC_GENERAL 0x00000104
++#define CKM_RC2_CBC_PAD 0x00000105
++
++#define CKM_RC4_KEY_GEN 0x00000110
++#define CKM_RC4 0x00000111
++#define CKM_DES_KEY_GEN 0x00000120
++#define CKM_DES_ECB 0x00000121
++#define CKM_DES_CBC 0x00000122
++#define CKM_DES_MAC 0x00000123
++
++/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
++#define CKM_DES_MAC_GENERAL 0x00000124
++#define CKM_DES_CBC_PAD 0x00000125
++
++#define CKM_DES2_KEY_GEN 0x00000130
++#define CKM_DES3_KEY_GEN 0x00000131
++#define CKM_DES3_ECB 0x00000132
++#define CKM_DES3_CBC 0x00000133
++#define CKM_DES3_MAC 0x00000134
++
++/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
++ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
++ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
++#define CKM_DES3_MAC_GENERAL 0x00000135
++#define CKM_DES3_CBC_PAD 0x00000136
++#define CKM_CDMF_KEY_GEN 0x00000140
++#define CKM_CDMF_ECB 0x00000141
++#define CKM_CDMF_CBC 0x00000142
++#define CKM_CDMF_MAC 0x00000143
++#define CKM_CDMF_MAC_GENERAL 0x00000144
++#define CKM_CDMF_CBC_PAD 0x00000145
++
++/* the following four DES mechanisms are new for v2.20 */
++#define CKM_DES_OFB64 0x00000150
++#define CKM_DES_OFB8 0x00000151
++#define CKM_DES_CFB64 0x00000152
++#define CKM_DES_CFB8 0x00000153
++
++#define CKM_MD2 0x00000200
++
++/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD2_HMAC 0x00000201
++#define CKM_MD2_HMAC_GENERAL 0x00000202
++
++#define CKM_MD5 0x00000210
++
++/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD5_HMAC 0x00000211
++#define CKM_MD5_HMAC_GENERAL 0x00000212
++
++#define CKM_SHA_1 0x00000220
++
++/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
++#define CKM_SHA_1_HMAC 0x00000221
++#define CKM_SHA_1_HMAC_GENERAL 0x00000222
++
++/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
++ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
++ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
++#define CKM_RIPEMD128 0x00000230
++#define CKM_RIPEMD128_HMAC 0x00000231
++#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
++#define CKM_RIPEMD160 0x00000240
++#define CKM_RIPEMD160_HMAC 0x00000241
++#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256 0x00000250
++#define CKM_SHA256_HMAC 0x00000251
++#define CKM_SHA256_HMAC_GENERAL 0x00000252
++
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224 0x00000255
++#define CKM_SHA224_HMAC 0x00000256
++#define CKM_SHA224_HMAC_GENERAL 0x00000257
++
++#define CKM_SHA384 0x00000260
++#define CKM_SHA384_HMAC 0x00000261
++#define CKM_SHA384_HMAC_GENERAL 0x00000262
++#define CKM_SHA512 0x00000270
++#define CKM_SHA512_HMAC 0x00000271
++#define CKM_SHA512_HMAC_GENERAL 0x00000272
++
++/* SecurID is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_SECURID_KEY_GEN 0x00000280
++#define CKM_SECURID 0x00000282
++
++/* HOTP is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_HOTP_KEY_GEN 0x00000290
++#define CKM_HOTP 0x00000291
++
++/* ACTI is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_ACTI 0x000002A0
++#define CKM_ACTI_KEY_GEN 0x000002A1
++
++/* All of the following mechanisms are new for v2.0 */
++/* Note that CAST128 and CAST5 are the same algorithm */
++#define CKM_CAST_KEY_GEN 0x00000300
++#define CKM_CAST_ECB 0x00000301
++#define CKM_CAST_CBC 0x00000302
++#define CKM_CAST_MAC 0x00000303
++#define CKM_CAST_MAC_GENERAL 0x00000304
++#define CKM_CAST_CBC_PAD 0x00000305
++#define CKM_CAST3_KEY_GEN 0x00000310
++#define CKM_CAST3_ECB 0x00000311
++#define CKM_CAST3_CBC 0x00000312
++#define CKM_CAST3_MAC 0x00000313
++#define CKM_CAST3_MAC_GENERAL 0x00000314
++#define CKM_CAST3_CBC_PAD 0x00000315
++#define CKM_CAST5_KEY_GEN 0x00000320
++#define CKM_CAST128_KEY_GEN 0x00000320
++#define CKM_CAST5_ECB 0x00000321
++#define CKM_CAST128_ECB 0x00000321
++#define CKM_CAST5_CBC 0x00000322
++#define CKM_CAST128_CBC 0x00000322
++#define CKM_CAST5_MAC 0x00000323
++#define CKM_CAST128_MAC 0x00000323
++#define CKM_CAST5_MAC_GENERAL 0x00000324
++#define CKM_CAST128_MAC_GENERAL 0x00000324
++#define CKM_CAST5_CBC_PAD 0x00000325
++#define CKM_CAST128_CBC_PAD 0x00000325
++#define CKM_RC5_KEY_GEN 0x00000330
++#define CKM_RC5_ECB 0x00000331
++#define CKM_RC5_CBC 0x00000332
++#define CKM_RC5_MAC 0x00000333
++#define CKM_RC5_MAC_GENERAL 0x00000334
++#define CKM_RC5_CBC_PAD 0x00000335
++#define CKM_IDEA_KEY_GEN 0x00000340
++#define CKM_IDEA_ECB 0x00000341
++#define CKM_IDEA_CBC 0x00000342
++#define CKM_IDEA_MAC 0x00000343
++#define CKM_IDEA_MAC_GENERAL 0x00000344
++#define CKM_IDEA_CBC_PAD 0x00000345
++#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
++#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
++#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
++#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
++#define CKM_XOR_BASE_AND_DATA 0x00000364
++#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
++#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
++#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
++#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
++
++/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
++ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
++ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
++#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
++#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
++#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
++#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
++#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
++
++/* CKM_TLS_PRF is new for v2.20 */
++#define CKM_TLS_PRF 0x00000378
++
++#define CKM_SSL3_MD5_MAC 0x00000380
++#define CKM_SSL3_SHA1_MAC 0x00000381
++#define CKM_MD5_KEY_DERIVATION 0x00000390
++#define CKM_MD2_KEY_DERIVATION 0x00000391
++#define CKM_SHA1_KEY_DERIVATION 0x00000392
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_KEY_DERIVATION 0x00000393
++#define CKM_SHA384_KEY_DERIVATION 0x00000394
++#define CKM_SHA512_KEY_DERIVATION 0x00000395
++
++/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_KEY_DERIVATION 0x00000396
++
++#define CKM_PBE_MD2_DES_CBC 0x000003A0
++#define CKM_PBE_MD5_DES_CBC 0x000003A1
++#define CKM_PBE_MD5_CAST_CBC 0x000003A2
++#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
++#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
++#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
++#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
++#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
++#define CKM_PBE_SHA1_RC4_128 0x000003A6
++#define CKM_PBE_SHA1_RC4_40 0x000003A7
++#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
++#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
++#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
++#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
++
++/* CKM_PKCS5_PBKD2 is new for v2.10 */
++#define CKM_PKCS5_PBKD2 0x000003B0
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
++
++/* WTLS mechanisms are new for v2.20 */
++#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
++#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
++#define CKM_WTLS_PRF 0x000003D3
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
++
++#define CKM_KEY_WRAP_LYNKS 0x00000400
++#define CKM_KEY_WRAP_SET_OAEP 0x00000401
++
++/* CKM_CMS_SIG is new for v2.20 */
++#define CKM_CMS_SIG 0x00000500
++
++/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */
++#define CKM_KIP_DERIVE 0x00000510
++#define CKM_KIP_WRAP 0x00000511
++#define CKM_KIP_MAC 0x00000512
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_CAMELLIA_KEY_GEN 0x00000550
++#define CKM_CAMELLIA_ECB 0x00000551
++#define CKM_CAMELLIA_CBC 0x00000552
++#define CKM_CAMELLIA_MAC 0x00000553
++#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
++#define CKM_CAMELLIA_CBC_PAD 0x00000555
++#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
++#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
++#define CKM_CAMELLIA_CTR 0x00000558
++
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_ARIA_KEY_GEN 0x00000560
++#define CKM_ARIA_ECB 0x00000561
++#define CKM_ARIA_CBC 0x00000562
++#define CKM_ARIA_MAC 0x00000563
++#define CKM_ARIA_MAC_GENERAL 0x00000564
++#define CKM_ARIA_CBC_PAD 0x00000565
++#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
++#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
++
++/* Fortezza mechanisms */
++#define CKM_SKIPJACK_KEY_GEN 0x00001000
++#define CKM_SKIPJACK_ECB64 0x00001001
++#define CKM_SKIPJACK_CBC64 0x00001002
++#define CKM_SKIPJACK_OFB64 0x00001003
++#define CKM_SKIPJACK_CFB64 0x00001004
++#define CKM_SKIPJACK_CFB32 0x00001005
++#define CKM_SKIPJACK_CFB16 0x00001006
++#define CKM_SKIPJACK_CFB8 0x00001007
++#define CKM_SKIPJACK_WRAP 0x00001008
++#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
++#define CKM_SKIPJACK_RELAYX 0x0000100a
++#define CKM_KEA_KEY_PAIR_GEN 0x00001010
++#define CKM_KEA_KEY_DERIVE 0x00001011
++#define CKM_FORTEZZA_TIMESTAMP 0x00001020
++#define CKM_BATON_KEY_GEN 0x00001030
++#define CKM_BATON_ECB128 0x00001031
++#define CKM_BATON_ECB96 0x00001032
++#define CKM_BATON_CBC128 0x00001033
++#define CKM_BATON_COUNTER 0x00001034
++#define CKM_BATON_SHUFFLE 0x00001035
++#define CKM_BATON_WRAP 0x00001036
++
++/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
++ * CKM_EC_KEY_PAIR_GEN is preferred */
++#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
++#define CKM_EC_KEY_PAIR_GEN 0x00001040
++
++#define CKM_ECDSA 0x00001041
++#define CKM_ECDSA_SHA1 0x00001042
++
++/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
++ * are new for v2.11 */
++#define CKM_ECDH1_DERIVE 0x00001050
++#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
++#define CKM_ECMQV_DERIVE 0x00001052
++
++#define CKM_JUNIPER_KEY_GEN 0x00001060
++#define CKM_JUNIPER_ECB128 0x00001061
++#define CKM_JUNIPER_CBC128 0x00001062
++#define CKM_JUNIPER_COUNTER 0x00001063
++#define CKM_JUNIPER_SHUFFLE 0x00001064
++#define CKM_JUNIPER_WRAP 0x00001065
++#define CKM_FASTHASH 0x00001070
++
++/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
++ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
++ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
++ * new for v2.11 */
++#define CKM_AES_KEY_GEN 0x00001080
++#define CKM_AES_ECB 0x00001081
++#define CKM_AES_CBC 0x00001082
++#define CKM_AES_MAC 0x00001083
++#define CKM_AES_MAC_GENERAL 0x00001084
++#define CKM_AES_CBC_PAD 0x00001085
++
++/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_AES_CTR 0x00001086
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKM_BLOWFISH_KEY_GEN 0x00001090
++#define CKM_BLOWFISH_CBC 0x00001091
++#define CKM_TWOFISH_KEY_GEN 0x00001092
++#define CKM_TWOFISH_CBC 0x00001093
++
++
++/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
++#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
++#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
++#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
++#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
++#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
++#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
++
++#define CKM_DSA_PARAMETER_GEN 0x00002000
++#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
++#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
++
++#define CKM_VENDOR_DEFINED 0x80000000
++
++typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
++
++
++/* CK_MECHANISM is a structure that specifies a particular
++ * mechanism */
++typedef struct CK_MECHANISM {
++ CK_MECHANISM_TYPE mechanism;
++ CK_VOID_PTR pParameter;
++
++ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulParameterLen; /* in bytes */
++} CK_MECHANISM;
++
++typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
++
++
++/* CK_MECHANISM_INFO provides information about a particular
++ * mechanism */
++typedef struct CK_MECHANISM_INFO {
++ CK_ULONG ulMinKeySize;
++ CK_ULONG ulMaxKeySize;
++ CK_FLAGS flags;
++} CK_MECHANISM_INFO;
++
++/* The flags are defined as follows:
++ * Bit Flag Mask Meaning */
++#define CKF_HW 0x00000001 /* performed by HW */
++
++/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
++ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
++ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
++ * and CKF_DERIVE are new for v2.0. They specify whether or not
++ * a mechanism can be used for a particular task */
++#define CKF_ENCRYPT 0x00000100
++#define CKF_DECRYPT 0x00000200
++#define CKF_DIGEST 0x00000400
++#define CKF_SIGN 0x00000800
++#define CKF_SIGN_RECOVER 0x00001000
++#define CKF_VERIFY 0x00002000
++#define CKF_VERIFY_RECOVER 0x00004000
++#define CKF_GENERATE 0x00008000
++#define CKF_GENERATE_KEY_PAIR 0x00010000
++#define CKF_WRAP 0x00020000
++#define CKF_UNWRAP 0x00040000
++#define CKF_DERIVE 0x00080000
++
++/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
++ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
++ * describe a token's EC capabilities not available in mechanism
++ * information. */
++#define CKF_EC_F_P 0x00100000
++#define CKF_EC_F_2M 0x00200000
++#define CKF_EC_ECPARAMETERS 0x00400000
++#define CKF_EC_NAMEDCURVE 0x00800000
++#define CKF_EC_UNCOMPRESS 0x01000000
++#define CKF_EC_COMPRESS 0x02000000
++
++#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
++
++typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
++
++
++/* CK_RV is a value that identifies the return value of a
++ * Cryptoki function */
++/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_RV;
++
++#define CKR_OK 0x00000000
++#define CKR_CANCEL 0x00000001
++#define CKR_HOST_MEMORY 0x00000002
++#define CKR_SLOT_ID_INVALID 0x00000003
++
++/* CKR_FLAGS_INVALID was removed for v2.0 */
++
++/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
++#define CKR_GENERAL_ERROR 0x00000005
++#define CKR_FUNCTION_FAILED 0x00000006
++
++/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
++ * and CKR_CANT_LOCK are new for v2.01 */
++#define CKR_ARGUMENTS_BAD 0x00000007
++#define CKR_NO_EVENT 0x00000008
++#define CKR_NEED_TO_CREATE_THREADS 0x00000009
++#define CKR_CANT_LOCK 0x0000000A
++
++#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
++#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
++#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
++#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
++#define CKR_DATA_INVALID 0x00000020
++#define CKR_DATA_LEN_RANGE 0x00000021
++#define CKR_DEVICE_ERROR 0x00000030
++#define CKR_DEVICE_MEMORY 0x00000031
++#define CKR_DEVICE_REMOVED 0x00000032
++#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
++#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
++#define CKR_FUNCTION_CANCELED 0x00000050
++#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
++
++/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
++#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
++
++#define CKR_KEY_HANDLE_INVALID 0x00000060
++
++/* CKR_KEY_SENSITIVE was removed for v2.0 */
++
++#define CKR_KEY_SIZE_RANGE 0x00000062
++#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
++
++/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
++ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
++ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
++ * v2.0 */
++#define CKR_KEY_NOT_NEEDED 0x00000064
++#define CKR_KEY_CHANGED 0x00000065
++#define CKR_KEY_NEEDED 0x00000066
++#define CKR_KEY_INDIGESTIBLE 0x00000067
++#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
++#define CKR_KEY_NOT_WRAPPABLE 0x00000069
++#define CKR_KEY_UNEXTRACTABLE 0x0000006A
++
++#define CKR_MECHANISM_INVALID 0x00000070
++#define CKR_MECHANISM_PARAM_INVALID 0x00000071
++
++/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
++ * were removed for v2.0 */
++#define CKR_OBJECT_HANDLE_INVALID 0x00000082
++#define CKR_OPERATION_ACTIVE 0x00000090
++#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
++#define CKR_PIN_INCORRECT 0x000000A0
++#define CKR_PIN_INVALID 0x000000A1
++#define CKR_PIN_LEN_RANGE 0x000000A2
++
++/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
++#define CKR_PIN_EXPIRED 0x000000A3
++#define CKR_PIN_LOCKED 0x000000A4
++
++#define CKR_SESSION_CLOSED 0x000000B0
++#define CKR_SESSION_COUNT 0x000000B1
++#define CKR_SESSION_HANDLE_INVALID 0x000000B3
++#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
++#define CKR_SESSION_READ_ONLY 0x000000B5
++#define CKR_SESSION_EXISTS 0x000000B6
++
++/* CKR_SESSION_READ_ONLY_EXISTS and
++ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
++#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
++#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
++
++#define CKR_SIGNATURE_INVALID 0x000000C0
++#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
++#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
++#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
++#define CKR_TOKEN_NOT_PRESENT 0x000000E0
++#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
++#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
++#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
++#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
++#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
++#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
++#define CKR_USER_NOT_LOGGED_IN 0x00000101
++#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
++#define CKR_USER_TYPE_INVALID 0x00000103
++
++/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
++ * are new to v2.01 */
++#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
++#define CKR_USER_TOO_MANY_TYPES 0x00000105
++
++#define CKR_WRAPPED_KEY_INVALID 0x00000110
++#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
++#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
++#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
++#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
++#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
++
++/* These are new to v2.0 */
++#define CKR_RANDOM_NO_RNG 0x00000121
++
++/* These are new to v2.11 */
++#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
++
++/* These are new to v2.0 */
++#define CKR_BUFFER_TOO_SMALL 0x00000150
++#define CKR_SAVED_STATE_INVALID 0x00000160
++#define CKR_INFORMATION_SENSITIVE 0x00000170
++#define CKR_STATE_UNSAVEABLE 0x00000180
++
++/* These are new to v2.01 */
++#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
++#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
++#define CKR_MUTEX_BAD 0x000001A0
++#define CKR_MUTEX_NOT_LOCKED 0x000001A1
++
++/* The following return values are new for PKCS #11 v2.20 amendment 3 */
++#define CKR_NEW_PIN_MODE 0x000001B0
++#define CKR_NEXT_OTP 0x000001B1
++
++/* This is new to v2.20 */
++#define CKR_FUNCTION_REJECTED 0x00000200
++
++#define CKR_VENDOR_DEFINED 0x80000000
++
++
++/* CK_NOTIFY is an application callback that processes events */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication /* passed to C_OpenSession */
++);
++
++
++/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
++ * version and pointers of appropriate types to all the
++ * Cryptoki functions */
++/* CK_FUNCTION_LIST is new for v2.0 */
++typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
++
++typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
++
++typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
++
++
++/* CK_CREATEMUTEX is an application callback for creating a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
++ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
++);
++
++
++/* CK_DESTROYMUTEX is an application callback for destroying a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_LOCKMUTEX is an application callback for locking a mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_UNLOCKMUTEX is an application callback for unlocking a
++ * mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_C_INITIALIZE_ARGS provides the optional arguments to
++ * C_Initialize */
++typedef struct CK_C_INITIALIZE_ARGS {
++ CK_CREATEMUTEX CreateMutex;
++ CK_DESTROYMUTEX DestroyMutex;
++ CK_LOCKMUTEX LockMutex;
++ CK_UNLOCKMUTEX UnlockMutex;
++ CK_FLAGS flags;
++ CK_VOID_PTR pReserved;
++} CK_C_INITIALIZE_ARGS;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
++#define CKF_OS_LOCKING_OK 0x00000002
++
++typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
++
++
++/* additional flags for parameters to functions */
++
++/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
++#define CKF_DONT_BLOCK 1
++
++/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
++ * Generation Function (MGF) applied to a message block when
++ * formatting a message block for the PKCS #1 OAEP encryption
++ * scheme. */
++typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
++
++typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
++
++/* The following MGFs are defined */
++/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
++ * are new for v2.20 */
++#define CKG_MGF1_SHA1 0x00000001
++#define CKG_MGF1_SHA256 0x00000002
++#define CKG_MGF1_SHA384 0x00000003
++#define CKG_MGF1_SHA512 0x00000004
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKG_MGF1_SHA224 0x00000005
++
++/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
++ * of the encoding parameter when formatting a message block
++ * for the PKCS #1 OAEP encryption scheme. */
++typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
++
++typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
++
++/* The following encoding parameter sources are defined */
++#define CKZ_DATA_SPECIFIED 0x00000001
++
++/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
++ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_OAEP mechanism. */
++typedef struct CK_RSA_PKCS_OAEP_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
++ CK_VOID_PTR pSourceData;
++ CK_ULONG ulSourceDataLen;
++} CK_RSA_PKCS_OAEP_PARAMS;
++
++typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
++
++/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
++ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_PSS mechanism(s). */
++typedef struct CK_RSA_PKCS_PSS_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_ULONG sLen;
++} CK_RSA_PKCS_PSS_PARAMS;
++
++typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
++
++/* CK_EC_KDF_TYPE is new for v2.11. */
++typedef CK_ULONG CK_EC_KDF_TYPE;
++
++/* The following EC Key Derivation Functions are defined */
++#define CKD_NULL 0x00000001
++#define CKD_SHA1_KDF 0x00000002
++
++/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
++ * where each party contributes one key pair.
++ */
++typedef struct CK_ECDH1_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_ECDH1_DERIVE_PARAMS;
++
++typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
++
++
++/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
++typedef struct CK_ECDH2_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_ECDH2_DERIVE_PARAMS;
++
++typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_ECMQV_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_ECMQV_DERIVE_PARAMS;
++
++typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
++
++/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
++ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
++typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
++typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
++
++/* The following X9.42 DH key derivation functions are defined
++ (besides CKD_NULL already defined : */
++#define CKD_SHA1_KDF_ASN1 0x00000003
++#define CKD_SHA1_KDF_CONCATENATE 0x00000004
++
++/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
++ * contributes one key pair */
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_X9_42_DH1_DERIVE_PARAMS;
++
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
++
++/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
++ * mechanisms, where each party contributes two key pairs */
++typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_X9_42_DH2_DERIVE_PARAMS;
++
++typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_X9_42_MQV_DERIVE_PARAMS;
++
++typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
++
++/* CK_KEA_DERIVE_PARAMS provides the parameters to the
++ * CKM_KEA_DERIVE mechanism */
++/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
++typedef struct CK_KEA_DERIVE_PARAMS {
++ CK_BBOOL isSender;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pRandomB;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_KEA_DERIVE_PARAMS;
++
++typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
++
++
++/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
++ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
++ * holds the effective keysize */
++typedef CK_ULONG CK_RC2_PARAMS;
++
++typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
++
++
++/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
++ * mechanism */
++typedef struct CK_RC2_CBC_PARAMS {
++ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++
++ CK_BYTE iv[8]; /* IV for CBC mode */
++} CK_RC2_CBC_PARAMS;
++
++typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
++
++
++/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC2_MAC_GENERAL mechanism */
++/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC2_MAC_GENERAL_PARAMS {
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC2_MAC_GENERAL_PARAMS;
++
++typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC2_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
++ * CKM_RC5_MAC mechanisms */
++/* CK_RC5_PARAMS is new for v2.0 */
++typedef struct CK_RC5_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++} CK_RC5_PARAMS;
++
++typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
++
++
++/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
++ * mechanism */
++/* CK_RC5_CBC_PARAMS is new for v2.0 */
++typedef struct CK_RC5_CBC_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_BYTE_PTR pIv; /* pointer to IV */
++ CK_ULONG ulIvLen; /* length of IV in bytes */
++} CK_RC5_CBC_PARAMS;
++
++typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
++
++
++/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC5_MAC_GENERAL mechanism */
++/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC5_MAC_GENERAL_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC5_MAC_GENERAL_PARAMS;
++
++typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC5_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
++ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
++ * the MAC */
++/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
++
++typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
++
++/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
++typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[8];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pPassword;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPAndGLen;
++ CK_ULONG ulQLen;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pPrimeP;
++ CK_BYTE_PTR pBaseG;
++ CK_BYTE_PTR pSubprimeQ;
++} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
++
++typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
++ CK_SKIPJACK_PRIVATE_WRAP_PTR;
++
++
++/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_RELAYX mechanism */
++/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_RELAYX_PARAMS {
++ CK_ULONG ulOldWrappedXLen;
++ CK_BYTE_PTR pOldWrappedX;
++ CK_ULONG ulOldPasswordLen;
++ CK_BYTE_PTR pOldPassword;
++ CK_ULONG ulOldPublicDataLen;
++ CK_BYTE_PTR pOldPublicData;
++ CK_ULONG ulOldRandomLen;
++ CK_BYTE_PTR pOldRandomA;
++ CK_ULONG ulNewPasswordLen;
++ CK_BYTE_PTR pNewPassword;
++ CK_ULONG ulNewPublicDataLen;
++ CK_BYTE_PTR pNewPublicData;
++ CK_ULONG ulNewRandomLen;
++ CK_BYTE_PTR pNewRandomA;
++} CK_SKIPJACK_RELAYX_PARAMS;
++
++typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
++ CK_SKIPJACK_RELAYX_PARAMS_PTR;
++
++
++typedef struct CK_PBE_PARAMS {
++ CK_BYTE_PTR pInitVector;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pSalt;
++ CK_ULONG ulSaltLen;
++ CK_ULONG ulIteration;
++} CK_PBE_PARAMS;
++
++typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
++
++
++/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
++ * CKM_KEY_WRAP_SET_OAEP mechanism */
++/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
++typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
++ CK_BYTE bBC; /* block contents byte */
++ CK_BYTE_PTR pX; /* extra data */
++ CK_ULONG ulXLen; /* length of extra data in bytes */
++} CK_KEY_WRAP_SET_OAEP_PARAMS;
++
++typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
++ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_SSL3_RANDOM_DATA;
++
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_VERSION_PTR pVersion;
++} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hClientMacSecret;
++ CK_OBJECT_HANDLE hServerMacSecret;
++ CK_OBJECT_HANDLE hClientKey;
++ CK_OBJECT_HANDLE hServerKey;
++ CK_BYTE_PTR pIVClient;
++ CK_BYTE_PTR pIVServer;
++} CK_SSL3_KEY_MAT_OUT;
++
++typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_PARAMS {
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_BBOOL bIsExport;
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_SSL3_KEY_MAT_PARAMS;
++
++typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
++
++/* CK_TLS_PRF_PARAMS is new for version 2.20 */
++typedef struct CK_TLS_PRF_PARAMS {
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_TLS_PRF_PARAMS;
++
++typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
++
++/* WTLS is new for version 2.20 */
++typedef struct CK_WTLS_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_WTLS_RANDOM_DATA;
++
++typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
++
++typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_BYTE_PTR pVersion;
++} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
++
++typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++typedef struct CK_WTLS_PRF_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_WTLS_PRF_PARAMS;
++
++typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hMacSecret;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pIV;
++} CK_WTLS_KEY_MAT_OUT;
++
++typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_ULONG ulSequenceNumber;
++ CK_BBOOL bIsExport;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_WTLS_KEY_MAT_PARAMS;
++
++typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
++
++/* CMS is new for version 2.20 */
++typedef struct CK_CMS_SIG_PARAMS {
++ CK_OBJECT_HANDLE certificateHandle;
++ CK_MECHANISM_PTR pSigningMechanism;
++ CK_MECHANISM_PTR pDigestMechanism;
++ CK_UTF8CHAR_PTR pContentType;
++ CK_BYTE_PTR pRequestedAttributes;
++ CK_ULONG ulRequestedAttributesLen;
++ CK_BYTE_PTR pRequiredAttributes;
++ CK_ULONG ulRequiredAttributesLen;
++} CK_CMS_SIG_PARAMS;
++
++typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
++
++typedef struct CK_KEY_DERIVATION_STRING_DATA {
++ CK_BYTE_PTR pData;
++ CK_ULONG ulLen;
++} CK_KEY_DERIVATION_STRING_DATA;
++
++typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
++ CK_KEY_DERIVATION_STRING_DATA_PTR;
++
++
++/* The CK_EXTRACT_PARAMS is used for the
++ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
++ * of the base key should be used as the first bit of the
++ * derived key */
++/* CK_EXTRACT_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_EXTRACT_PARAMS;
++
++typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
++
++/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
++ * indicate the Pseudo-Random Function (PRF) used to generate
++ * key bits using PKCS #5 PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
++
++typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
++
++/* The following PRFs are defined in PKCS #5 v2.0. */
++#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
++
++
++/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
++ * source of the salt value when deriving a key using PKCS #5
++ * PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
++
++typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
++
++/* The following salt value sources are defined in PKCS #5 v2.0. */
++#define CKZ_SALT_SPECIFIED 0x00000001
++
++/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
++ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
++ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
++typedef struct CK_PKCS5_PBKD2_PARAMS {
++ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ CK_VOID_PTR pSaltSourceData;
++ CK_ULONG ulSaltSourceDataLen;
++ CK_ULONG iterations;
++ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ CK_VOID_PTR pPrfData;
++ CK_ULONG ulPrfDataLen;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG_PTR ulPasswordLen;
++} CK_PKCS5_PBKD2_PARAMS;
++
++typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
++
++/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */
++
++typedef CK_ULONG CK_OTP_PARAM_TYPE;
++typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */
++
++typedef struct CK_OTP_PARAM {
++ CK_OTP_PARAM_TYPE type;
++ CK_VOID_PTR pValue;
++ CK_ULONG ulValueLen;
++} CK_OTP_PARAM;
++
++typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
++
++typedef struct CK_OTP_PARAMS {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_PARAMS;
++
++typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
++
++typedef struct CK_OTP_SIGNATURE_INFO {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_SIGNATURE_INFO;
++
++typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CK_OTP_VALUE 0
++#define CK_OTP_PIN 1
++#define CK_OTP_CHALLENGE 2
++#define CK_OTP_TIME 3
++#define CK_OTP_COUNTER 4
++#define CK_OTP_FLAGS 5
++#define CK_OTP_OUTPUT_LENGTH 6
++#define CK_OTP_OUTPUT_FORMAT 7
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CKF_NEXT_OTP 0x00000001
++#define CKF_EXCLUDE_TIME 0x00000002
++#define CKF_EXCLUDE_COUNTER 0x00000004
++#define CKF_EXCLUDE_CHALLENGE 0x00000008
++#define CKF_EXCLUDE_PIN 0x00000010
++#define CKF_USER_FRIENDLY_OTP 0x00000020
++
++/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */
++typedef struct CK_KIP_PARAMS {
++ CK_MECHANISM_PTR pMechanism;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++} CK_KIP_PARAMS;
++
++typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
++
++/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_AES_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_AES_CTR_PARAMS;
++
++typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_CAMELLIA_CTR_PARAMS;
++
++typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++#endif
+Index: openssl/util/libeay.num
+diff -u openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.2.1.2.1.2.1 openssl/util/libeay.num:1.13.2.3
+--- openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.2.1.2.1.2.1 Mon Jun 13 15:42:32 2016
++++ openssl/util/libeay.num Mon Jun 13 15:52:51 2016
+@@ -4415,4 +4415,5 @@
+ X509_VERIFY_PARAM_add1_host 4771 EXIST::FUNCTION:
+ EC_GROUP_get_mont_data 4772 EXIST::FUNCTION:EC
+ i2d_re_X509_tbs 4773 EXIST::FUNCTION:
+-EVP_PKEY_asn1_set_item 4774 EXIST::FUNCTION:
++ENGINE_load_pk11ca 4774 EXIST::FUNCTION:HW_PKCS11CA,ENGINE
++ENGINE_load_pk11so 4774 EXIST::FUNCTION:HW_PKCS11SO,ENGINE
+Index: openssl/util/mk1mf.pl
+diff -u openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.2.1.2.1.2.1 openssl/util/mk1mf.pl:1.12.2.3
+--- openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.2.1.2.1.2.1 Mon Jun 13 15:42:33 2016
++++ openssl/util/mk1mf.pl Mon Jun 13 15:52:52 2016
+@@ -122,6 +122,8 @@
+ no-ecdh - No ECDH
+ no-engine - No engine
+ no-hw - No hw
++ no-hw-pkcs11ca - No hw PKCS#11 CA flavor
++ no-hw-pkcs11so - No hw PKCS#11 SO flavor
+ nasm - Use NASM for x86 asm
+ nw-nasm - Use NASM x86 asm for NetWare
+ nw-mwasm - Use Metrowerks x86 asm for NetWare
+@@ -287,6 +289,8 @@
+ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost;
+ $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine;
+ $cflags.=" -DOPENSSL_NO_HW" if $no_hw;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca;
++$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so;
+ $cflags.=" -DOPENSSL_FIPS" if $fips;
+ $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake;
+ $cflags.=" -DOPENSSL_NO_EC2M" if $no_ec2m;
+@@ -361,6 +365,9 @@
+ $dir=$val;
+ }
+
++ if ($key eq "PK11_LIB_LOCATION")
++ { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";}
++
+ if ($key eq "KRB5_INCLUDES")
+ { $cflags .= " $val";}
+
+@@ -1219,6 +1226,8 @@
+ "no-gost" => \$no_gost,
+ "no-engine" => \$no_engine,
+ "no-hw" => \$no_hw,
++ "no-hw-pkcs11ca" => \$no_hw_pkcs11ca,
++ "no-hw-pkcs11so" => \$no_hw_pkcs11so,
+ "no-rsax" => 0,
+ "just-ssl" =>
+ [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast,
+Index: openssl/util/mkdef.pl
+diff -u openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.2.1.4.1 openssl/util/mkdef.pl:1.11.2.2
+--- openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.2.1.4.1 Mon Jun 13 15:42:34 2016
++++ openssl/util/mkdef.pl Mon Jun 13 15:52:52 2016
+@@ -96,7 +96,7 @@
+ # External "algorithms"
+ "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM",
+ # Engines
+- "STATIC_ENGINE", "ENGINE", "HW", "GMP",
++ "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO",
+ # RFC3779
+ "RFC3779",
+ # TLS
+@@ -143,6 +143,7 @@
+ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
+ my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
+ my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw;
++my $no_pkcs11ca; my $no_pkcs11so;
+ my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
+ my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
+ my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc;
+@@ -251,6 +252,8 @@
+ elsif (/^no-sctp$/) { $no_sctp=1; }
+ elsif (/^no-srtp$/) { $no_srtp=1; }
+ elsif (/^no-unit-test$/){ $no_unit_test=1; }
++ elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; }
++ elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; }
+ }
+
+
+@@ -1206,6 +1209,8 @@
+ if ($keyword eq "KRB5" && $no_krb5) { return 0; }
+ if ($keyword eq "ENGINE" && $no_engine) { return 0; }
+ if ($keyword eq "HW" && $no_hw) { return 0; }
++ if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; }
++ if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; }
+ if ($keyword eq "FP_API" && $no_fp_api) { return 0; }
+ if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; }
+ if ($keyword eq "GMP" && $no_gmp) { return 0; }
+Index: openssl/util/pl/VC-32.pl
+diff -u openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.8.1.2.1.2.1 openssl/util/pl/VC-32.pl:1.10.2.3
+--- openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.8.1.2.1.2.1 Mon Jun 13 15:42:35 2016
++++ openssl/util/pl/VC-32.pl Mon Jun 13 15:52:53 2016
+@@ -47,7 +47,7 @@
+ $base_cflags= " $mf_cflag";
+ my $f = $shlib || $fips ?' /MD':' /MT';
+ $opt_cflags=$f.' /Ox';
+- $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG';
++ $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG';
+ $lflags="/nologo /subsystem:console /opt:ref";
+
+ *::perlasm_compile_target = sub {
diff --git a/bin/pkcs11/pkcs11-destroy.8 b/bin/pkcs11/pkcs11-destroy.8
new file mode 100644
index 0000000..441a567
--- /dev/null
+++ b/bin/pkcs11/pkcs11-destroy.8
@@ -0,0 +1,97 @@
+.\" Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: pkcs11-destroy
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-15
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "PKCS11\-DESTROY" "8" "2014\-01\-15" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+pkcs11-destroy \- destroy PKCS#11 objects
+.SH "SYNOPSIS"
+.HP \w'\fBpkcs11\-destroy\fR\ 'u
+\fBpkcs11\-destroy\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {\-i\ \fIID\fR | \-l\ \fIlabel\fR} [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-w\ \fR\fB\fIseconds\fR\fR]
+.SH "DESCRIPTION"
+.PP
+\fBpkcs11\-destroy\fR
+destroys keys stored in a PKCS#11 device, identified by their
+\fBID\fR
+or
+\fBlabel\fR\&.
+.PP
+Matching keys are displayed before being destroyed\&. By default, there is a five second delay to allow the user to interrupt the process before the destruction takes place\&.
+.SH "ARGUMENTS"
+.PP
+\-m \fImodule\fR
+.RS 4
+Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&.
+.RE
+.PP
+\-s \fIslot\fR
+.RS 4
+Open the session with the given PKCS#11 slot\&. The default is slot 0\&.
+.RE
+.PP
+\-i \fIID\fR
+.RS 4
+Destroy keys with the given object ID\&.
+.RE
+.PP
+\-l \fIlabel\fR
+.RS 4
+Destroy keys with the given label\&.
+.RE
+.PP
+\-p \fIPIN\fR
+.RS 4
+Specify the PIN for the device\&. If no PIN is provided on the command line,
+\fBpkcs11\-destroy\fR
+will prompt for it\&.
+.RE
+.PP
+\-w \fIseconds\fR
+.RS 4
+Specify how long to pause before carrying out key destruction\&. The default is five seconds\&. If set to
+0, destruction will be immediate\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBpkcs11-keygen\fR(8),
+\fBpkcs11-list\fR(8),
+\fBpkcs11-tokens\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/pkcs11/pkcs11-destroy.c b/bin/pkcs11/pkcs11-destroy.c
new file mode 100644
index 0000000..ae9f7d1
--- /dev/null
+++ b/bin/pkcs11/pkcs11-destroy.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2009, 2015 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 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.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label]
+ * [-p $pin] [ -w $wait ]
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifdef WIN32
+#define sleep(x) Sleep(x)
+#endif
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE attr_id[2];
+ CK_OBJECT_HANDLE akey[50];
+ pk11_context_t pctx;
+ char *lib_name = NULL;
+ char *label = NULL;
+ char *pin = NULL;
+ int error = 0;
+ unsigned int id = 0, i = 0, wait = 5;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &attr_id, sizeof(attr_id)}
+ };
+ unsigned int j, len;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:w:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'i':
+ id = atoi(isc_commandline_argument);
+ id &= 0xffff;
+ break;
+ case 'l':
+ label = isc_commandline_argument;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'w':
+ wait = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg || (id && (label != NULL))) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tpkcs11-destroy [-m module] [-s slot] "
+ "[-i id | -l label] [-p pin] [-w waittime]\n");
+ exit(1);
+ }
+
+ if (id) {
+ attr_id[0] = (id >> 8) & 0xff;
+ attr_id[1] = id & 0xff;
+ } else if (label) {
+ search_template[0].type = CKA_LABEL;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, OP_ANY, false, true,
+ true, (const char *) pin, slot);
+ if (result == PK11_R_NORANDOMSERVICE ||
+ result == PK11_R_NODIGESTSERVICE ||
+ result == PK11_R_NOAESSERVICE) {
+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
+ fprintf(stderr, "This HSM will not work with BIND 9 "
+ "using native PKCS#11.\n");
+ } else if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Unrecoverable error initializing "
+ "PKCS#11: %s\n", isc_result_totext(result));
+ exit(1);
+ }
+
+ memset(pin, 0, strlen(pin));
+
+ hSession = pctx.session;
+
+ rv = pkcs_C_FindObjectsInit(hSession, search_template,
+ ((id != 0) || (label != NULL)) ? 1 : 0);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
+ if (ulObjectCount == 0) {
+ printf("No matching key objects found.\n");
+ goto exit_search;
+ } else
+ printf("Key object%s found:\n", ulObjectCount > 1 ? "s" : "");
+
+ for (i = 0; i < ulObjectCount; i++) {
+ CK_OBJECT_CLASS oclass = 0;
+ CK_BYTE labelbuf[64 + 1];
+ CK_BYTE idbuf[64];
+ CK_ATTRIBUTE attr_template[] = {
+ {CKA_CLASS, &oclass, sizeof(oclass)},
+ {CKA_LABEL, labelbuf, sizeof(labelbuf) - 1},
+ {CKA_ID, idbuf, sizeof(idbuf)}
+ };
+
+ memset(labelbuf, 0, sizeof(labelbuf));
+ memset(idbuf, 0, sizeof(idbuf));
+
+ rv = pkcs_C_GetAttributeValue(hSession, akey[i],
+ attr_template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GetAttributeValue[%u]: rv = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ goto exit_search;
+ }
+ len = attr_template[2].ulValueLen;
+ printf(" object[%u]: class %lu, label '%s', id[%lu] ",
+ i, oclass, labelbuf, attr_template[2].ulValueLen);
+ if (len > 4)
+ len = 4;
+ if (len > 0)
+ printf("0x");
+ for (j = 0; j < len; j++)
+ printf("%02x", idbuf[j]);
+ if (attr_template[2].ulValueLen > len)
+ printf("...\n");
+ else
+ printf("\n");
+ }
+
+ if (wait != 0) {
+ printf("WARNING: This action is irreversible! "
+ "Destroying key objects in %u seconds\n ", wait);
+ for (i = 0; i < wait; i++) {
+ printf(".");
+ fflush(stdout);
+ sleep(1);
+ }
+ printf("\n");
+ }
+
+ for (i = 0; i < ulObjectCount; i++) {
+ rv = pkcs_C_DestroyObject(hSession, akey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DestroyObject[%u] failed: rv = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ }
+ }
+
+ if (error == 0)
+ printf("Destruction complete.\n");
+
+ exit_search:
+ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/pkcs11/pkcs11-destroy.docbook b/bin/pkcs11/pkcs11-destroy.docbook
new file mode 100644
index 0000000..18ff3a7
--- /dev/null
+++ b/bin/pkcs11/pkcs11-destroy.docbook
@@ -0,0 +1,153 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.pkcs11-destroy">
+ <info>
+ <date>2014-01-15</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>pkcs11-destroy</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>pkcs11-destroy</application></refname>
+ <refpurpose>destroy PKCS#11 objects</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>pkcs11-destroy</command>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">module</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">slot</replaceable></option></arg>
+ <group choice="req" rep="norepeat">
+ <arg choice="plain" rep="norepeat">-i <replaceable class="parameter">ID</replaceable></arg>
+ <arg choice="plain" rep="norepeat">-l <replaceable class="parameter">label</replaceable></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">PIN</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-w <replaceable class="parameter">seconds</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>pkcs11-destroy</command> destroys keys stored in a
+ PKCS#11 device, identified by their <option>ID</option> or
+ <option>label</option>.
+ </para>
+ <para>
+ Matching keys are displayed before being destroyed. By default,
+ there is a five second delay to allow the user to interrupt the
+ process before the destruction takes place.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>-m <replaceable class="parameter">module</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">slot</replaceable></term>
+ <listitem>
+ <para>
+ Open the session with the given PKCS#11 slot. The default is
+ slot 0.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">ID</replaceable></term>
+ <listitem>
+ <para>
+ Destroy keys with the given object ID.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">label</replaceable></term>
+ <listitem>
+ <para>
+ Destroy keys with the given label.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">PIN</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PIN for the device. If no PIN is provided on the
+ command line, <command>pkcs11-destroy</command> will prompt for it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-w <replaceable class="parameter">seconds</replaceable></term>
+ <listitem>
+ <para>
+ Specify how long to pause before carrying out key destruction.
+ The default is five seconds. If set to <literal>0</literal>,
+ destruction will be immediate.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>pkcs11-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-list</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-tokens</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/pkcs11/pkcs11-destroy.html b/bin/pkcs11/pkcs11-destroy.html
new file mode 100644
index 0000000..aca390a
--- /dev/null
+++ b/bin/pkcs11/pkcs11-destroy.html
@@ -0,0 +1,128 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>pkcs11-destroy</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.pkcs11-destroy"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">pkcs11-destroy</span>
+ &#8212; destroy PKCS#11 objects
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">pkcs11-destroy</code>
+ [<code class="option">-m <em class="replaceable"><code>module</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>]
+ {
+ -i <em class="replaceable"><code>ID</code></em>
+ | -l <em class="replaceable"><code>label</code></em>
+ }
+ [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>]
+ [<code class="option">-w <em class="replaceable"><code>seconds</code></em></code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>pkcs11-destroy</strong></span> destroys keys stored in a
+ PKCS#11 device, identified by their <code class="option">ID</code> or
+ <code class="option">label</code>.
+ </p>
+ <p>
+ Matching keys are displayed before being destroyed. By default,
+ there is a five second delay to allow the user to interrupt the
+ process before the destruction takes place.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>slot</code></em></span></dt>
+<dd>
+ <p>
+ Open the session with the given PKCS#11 slot. The default is
+ slot 0.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>ID</code></em></span></dt>
+<dd>
+ <p>
+ Destroy keys with the given object ID.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
+<dd>
+ <p>
+ Destroy keys with the given label.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>PIN</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PIN for the device. If no PIN is provided on the
+ command line, <span class="command"><strong>pkcs11-destroy</strong></span> will prompt for it.
+ </p>
+ </dd>
+<dt><span class="term">-w <em class="replaceable"><code>seconds</code></em></span></dt>
+<dd>
+ <p>
+ Specify how long to pause before carrying out key destruction.
+ The default is five seconds. If set to <code class="literal">0</code>,
+ destruction will be immediate.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-list</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-tokens</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/pkcs11/pkcs11-keygen.8 b/bin/pkcs11/pkcs11-keygen.8
new file mode 100644
index 0000000..c1355d4
--- /dev/null
+++ b/bin/pkcs11/pkcs11-keygen.8
@@ -0,0 +1,120 @@
+.\" Copyright (C) 2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: pkcs11-keygen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-15
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "PKCS11\-KEYGEN" "8" "2014\-01\-15" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+pkcs11-keygen \- generate keys on a PKCS#11 device
+.SH "SYNOPSIS"
+.HP \w'\fBpkcs11\-keygen\fR\ 'u
+\fBpkcs11\-keygen\fR {\-a\ \fIalgorithm\fR} [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-e\fR] [\fB\-i\ \fR\fB\fIid\fR\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-P\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-q\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {label}
+.SH "DESCRIPTION"
+.PP
+\fBpkcs11\-keygen\fR
+causes a PKCS#11 device to generate a new key pair with the given
+\fBlabel\fR
+(which must be unique) and with
+\fBkeysize\fR
+bits of prime\&.
+.SH "ARGUMENTS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Specify the key algorithm class: Supported classes are RSA, DSA, DH, ECC and ECX\&. In addition to these strings, the
+\fBalgorithm\fR
+can be specified as a DNSSEC signing algorithm that will be used with this key; for example, NSEC3RSASHA1 maps to RSA, ECDSAP256SHA256 maps to ECC, and ED25519 to ECX\&. The default class is "RSA"\&.
+.RE
+.PP
+\-b \fIkeysize\fR
+.RS 4
+Create the key pair with
+\fBkeysize\fR
+bits of prime\&. For ECC keys, the only valid values are 256 and 384, and the default is 256\&. For ECX kyes, the only valid values are 256 and 456, and the default is 256\&.
+.RE
+.PP
+\-e
+.RS 4
+For RSA keys only, use a large exponent\&.
+.RE
+.PP
+\-i \fIid\fR
+.RS 4
+Create key objects with id\&. The id is either an unsigned short 2 byte or an unsigned long 4 byte number\&.
+.RE
+.PP
+\-m \fImodule\fR
+.RS 4
+Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&.
+.RE
+.PP
+\-P
+.RS 4
+Set the new private key to be non\-sensitive and extractable\&. The allows the private key data to be read from the PKCS#11 device\&. The default is for private keys to be sensitive and non\-extractable\&.
+.RE
+.PP
+\-p \fIPIN\fR
+.RS 4
+Specify the PIN for the device\&. If no PIN is provided on the command line,
+\fBpkcs11\-keygen\fR
+will prompt for it\&.
+.RE
+.PP
+\-q
+.RS 4
+Quiet mode: suppress unnecessary output\&.
+.RE
+.PP
+\-S
+.RS 4
+For Diffie\-Hellman (DH) keys only, use a special prime of 768, 1024 or 1536 bit size and base (aka generator) 2\&. If not specified, bit size will default to 1024\&.
+.RE
+.PP
+\-s \fIslot\fR
+.RS 4
+Open the session with the given PKCS#11 slot\&. The default is slot 0\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBpkcs11-destroy\fR(8),
+\fBpkcs11-list\fR(8),
+\fBpkcs11-tokens\fR(8),
+\fBdnssec-keyfromlabel\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/pkcs11/pkcs11-keygen.c b/bin/pkcs11/pkcs11-keygen.c
new file mode 100644
index 0000000..560b4e9
--- /dev/null
+++ b/bin/pkcs11/pkcs11-keygen.c
@@ -0,0 +1,757 @@
+/*
+ * Copyright (C) 2009, 2012, 2015 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 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.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* pkcs11-keygen - PKCS#11 key generator
+ *
+ * Create a key in the keystore of an HSM
+ *
+ * The calculation of key tag is left to the script
+ * that converts the key into a DNSKEY RR and inserts
+ * it into a zone file.
+ *
+ * usage:
+ * pkcs11-keygen [-P] [-m module] [-s slot] [-e] [-b keysize]
+ * [-i id] [-p pin] -l label
+ *
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+#define WANT_DH_PRIMES
+#define WANT_ECC_CURVES
+#include <pk11/constants.h>
+#include <pkcs11/eddsa.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+/* Define static key template values */
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+/* Key class: RSA, ECC, ECX, DSA, DH, or unknown */
+typedef enum {
+ key_unknown,
+ key_rsa,
+ key_dsa,
+ key_dh,
+ key_ecc,
+ key_ecx
+} key_class_t;
+
+/*
+ * Private key template: usable for most key classes without
+ * modificaton; override CKA_SIGN with CKA_DERIVE for DH
+ */
+#define PRIVATE_LABEL 0
+#define PRIVATE_SIGN 1
+#define PRIVATE_DERIVE 1
+#define PRIVATE_TOKEN 2
+#define PRIVATE_PRIVATE 3
+#define PRIVATE_SENSITIVE 4
+#define PRIVATE_EXTRACTABLE 5
+#define PRIVATE_ID 6
+#define PRIVATE_ATTRS 7
+static CK_ATTRIBUTE private_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_SIGN, &truevalue, sizeof(truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+ {CKA_PRIVATE, &truevalue, sizeof(truevalue)},
+ {CKA_SENSITIVE, &truevalue, sizeof(truevalue)},
+ {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)},
+ {CKA_ID, NULL_PTR, 0}
+};
+
+/*
+ * Public key template for RSA keys
+ */
+#define RSA_LABEL 0
+#define RSA_VERIFY 1
+#define RSA_TOKEN 2
+#define RSA_PRIVATE 3
+#define RSA_MODULUS_BITS 4
+#define RSA_PUBLIC_EXPONENT 5
+#define RSA_ID 6
+#define RSA_ATTRS 7
+static CK_ATTRIBUTE rsa_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
+ {CKA_MODULUS_BITS, NULL_PTR, 0},
+ {CKA_PUBLIC_EXPONENT, NULL_PTR, 0},
+ {CKA_ID, NULL_PTR, 0}
+};
+
+/*
+ * Public key template for ECC/ECX keys
+ */
+#define ECC_LABEL 0
+#define ECC_VERIFY 1
+#define ECC_TOKEN 2
+#define ECC_PRIVATE 3
+#define ECC_PARAMS 4
+#define ECC_ID 5
+#define ECC_ATTRS 6
+static CK_ATTRIBUTE ecc_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
+ {CKA_EC_PARAMS, NULL_PTR, 0},
+ {CKA_ID, NULL_PTR, 0}
+};
+
+/*
+ * Public key template for DSA keys
+ */
+#define DSA_LABEL 0
+#define DSA_VERIFY 1
+#define DSA_TOKEN 2
+#define DSA_PRIVATE 3
+#define DSA_PRIME 4
+#define DSA_SUBPRIME 5
+#define DSA_BASE 6
+#define DSA_ID 7
+#define DSA_ATTRS 8
+static CK_ATTRIBUTE dsa_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
+ {CKA_PRIME, NULL_PTR, 0},
+ {CKA_SUBPRIME, NULL_PTR, 0},
+ {CKA_BASE, NULL_PTR, 0},
+ {CKA_ID, NULL_PTR, 0}
+};
+#define DSA_PARAM_PRIME 0
+#define DSA_PARAM_SUBPRIME 1
+#define DSA_PARAM_BASE 2
+#define DSA_PARAM_ATTRS 3
+static CK_ATTRIBUTE dsa_param_template[] = {
+ {CKA_PRIME, NULL_PTR, 0},
+ {CKA_SUBPRIME, NULL_PTR, 0},
+ {CKA_BASE, NULL_PTR, 0},
+};
+#define DSA_DOMAIN_PRIMEBITS 0
+#define DSA_DOMAIN_PRIVATE 1
+#define DSA_DOMAIN_ATTRS 2
+static CK_ATTRIBUTE dsa_domain_template[] = {
+ {CKA_PRIME_BITS, NULL_PTR, 0},
+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
+};
+
+/*
+ * Public key template for DH keys
+ */
+#define DH_LABEL 0
+#define DH_VERIFY 1
+#define DH_TOKEN 2
+#define DH_PRIVATE 3
+#define DH_PRIME 4
+#define DH_BASE 5
+#define DH_ID 6
+#define DH_ATTRS 7
+static CK_ATTRIBUTE dh_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
+ {CKA_PRIME, NULL_PTR, 0},
+ {CKA_BASE, NULL_PTR, 0},
+ {CKA_ID, NULL_PTR, 0}
+};
+#define DH_PARAM_PRIME 0
+#define DH_PARAM_BASE 1
+#define DH_PARAM_ATTRS 2
+static CK_ATTRIBUTE dh_param_template[] = {
+ {CKA_PRIME, NULL_PTR, 0},
+ {CKA_BASE, NULL_PTR, 0},
+};
+#define DH_DOMAIN_PRIMEBITS 0
+#define DH_DOMAIN_ATTRS 1
+static CK_ATTRIBUTE dh_domain_template[] = {
+ {CKA_PRIME_BITS, NULL_PTR, 0},
+};
+
+/*
+ * Convert from text to key class. Accepts the names of DNSSEC
+ * signing algorithms, so e.g., ECDSAP256SHA256 maps to ECC and
+ * NSEC3RSASHA1 maps to RSA.
+ */
+static key_class_t
+keyclass_fromtext(const char *name) {
+ if (name == NULL)
+ return (key_unknown);
+
+ if (strncasecmp(name, "rsa", 3) == 0 ||
+ strncasecmp(name, "nsec3rsa", 8) == 0)
+ return (key_rsa);
+ else if (strncasecmp(name, "dsa", 3) == 0 ||
+ strncasecmp(name, "nsec3dsa", 8) == 0)
+ return (key_dsa);
+ else if (strcasecmp(name, "dh") == 0)
+ return (key_dh);
+ else if (strncasecmp(name, "ecc", 3) == 0 ||
+ strncasecmp(name, "ecdsa", 5) == 0)
+ return (key_ecc);
+ else if (strncasecmp(name, "ecx", 3) == 0 ||
+ strncasecmp(name, "ed", 2) == 0)
+ return (key_ecx);
+ else
+ return (key_unknown);
+}
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "Usage:\n"
+ "\tpkcs11-keygen -a algorithm -b keysize -l label\n"
+ "\t [-P] [-m module] "
+ "[-s slot] [-e] [-S] [-i id] [-p PIN]\n");
+ exit(2);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_MECHANISM mech, dpmech;
+ CK_SESSION_HANDLE hSession;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ CK_ULONG bits = 0;
+ CK_CHAR *label = NULL;
+ CK_OBJECT_HANDLE privatekey, publickey, domainparams;
+ CK_BYTE exponent[5];
+ CK_ULONG expsize = 0;
+ pk11_context_t pctx;
+ int error = 0;
+ int c, errflg = 0;
+ int hide = 1, special = 0, quiet = 0;
+ int idlen = 0, id_offset = 0;
+ unsigned int i;
+ unsigned long id = 0;
+ CK_BYTE idbuf[4];
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_LABEL, NULL_PTR, 0}
+ };
+ CK_ATTRIBUTE *public_template = NULL;
+ CK_ATTRIBUTE *domain_template = NULL;
+ CK_ATTRIBUTE *param_template = NULL;
+ CK_ULONG public_attrcnt = 0, private_attrcnt = PRIVATE_ATTRS;
+ CK_ULONG domain_attrcnt = 0, param_attrcnt = 0;
+ key_class_t keyclass = key_rsa;
+ pk11_optype_t op_type = OP_ANY;
+
+#define OPTIONS ":a:b:ei:l:m:Pp:qSs:"
+ while ((c = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
+ switch (c) {
+ case 'a':
+ keyclass = keyclass_fromtext(isc_commandline_argument);
+ break;
+ case 'P':
+ hide = 0;
+ break;
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'e':
+ expsize = 5;
+ break;
+ case 'b':
+ bits = atoi(isc_commandline_argument);
+ break;
+ case 'l':
+ /* -l option is retained for backward compatibility * */
+ label = (CK_CHAR *)isc_commandline_argument;
+ break;
+ case 'i':
+ id = strtoul(isc_commandline_argument, NULL, 0);
+ idlen = 4;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'S':
+ special = 1;
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (label == NULL && isc_commandline_index < argc)
+ label = (CK_CHAR *)argv[isc_commandline_index];
+
+ if (errflg || (label == NULL))
+ usage();
+
+ if (expsize != 0 && keyclass != key_rsa) {
+ fprintf(stderr, "The -e option is only compatible "
+ "with RSA key generation\n");
+ exit(2);
+ }
+
+ if (special != 0 && keyclass != key_dh) {
+ fprintf(stderr, "The -S option is only compatible "
+ "with Diffie-Hellman key generation\n");
+ exit(2);
+ }
+
+ switch (keyclass) {
+ case key_rsa:
+ op_type = OP_RSA;
+ if (expsize == 0)
+ expsize = 3;
+ if (bits == 0)
+ usage();
+
+ mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ public_template = rsa_template;
+ public_attrcnt = RSA_ATTRS;
+ id_offset = RSA_ID;
+
+ /* Set public exponent to F4 or F5 */
+ exponent[0] = 0x01;
+ exponent[1] = 0x00;
+ if (expsize == 3)
+ exponent[2] = 0x01;
+ else {
+ exponent[2] = 0x00;
+ exponent[3] = 0x00;
+ exponent[4] = 0x01;
+ }
+
+ public_template[RSA_MODULUS_BITS].pValue = &bits;
+ public_template[RSA_MODULUS_BITS].ulValueLen = sizeof(bits);
+ public_template[RSA_PUBLIC_EXPONENT].pValue = &exponent;
+ public_template[RSA_PUBLIC_EXPONENT].ulValueLen = expsize;
+ break;
+ case key_ecc:
+ op_type = OP_EC;
+ if (bits == 0)
+ bits = 256;
+ else if (bits != 256 && bits != 384) {
+ fprintf(stderr, "ECC keys only support bit sizes of "
+ "256 and 384\n");
+ exit(2);
+ }
+
+ mech.mechanism = CKM_EC_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ public_template = ecc_template;
+ public_attrcnt = ECC_ATTRS;
+ id_offset = ECC_ID;
+
+ if (bits == 256) {
+ public_template[4].pValue = pk11_ecc_prime256v1;
+ public_template[4].ulValueLen =
+ sizeof(pk11_ecc_prime256v1);
+ } else {
+ public_template[4].pValue = pk11_ecc_secp384r1;
+ public_template[4].ulValueLen =
+ sizeof(pk11_ecc_secp384r1);
+ }
+
+ break;
+ case key_ecx:
+#ifndef CKM_EDDSA_KEY_PAIR_GEN
+ fprintf(stderr, "CKM_EDDSA_KEY_PAIR_GEN is not defined\n");
+ usage();
+#endif
+ op_type = OP_EC;
+ if (bits == 0)
+ bits = 256;
+ else if (bits != 256 && bits != 456) {
+ fprintf(stderr, "ECX keys only support bit sizes of "
+ "256 and 456\n");
+ exit(2);
+ }
+
+ mech.mechanism = CKM_EDDSA_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ public_template = ecc_template;
+ public_attrcnt = ECC_ATTRS;
+ id_offset = ECC_ID;
+
+ if (bits == 256) {
+ public_template[4].pValue = pk11_ecc_ed25519;
+ public_template[4].ulValueLen =
+ sizeof(pk11_ecc_ed25519);
+ } else {
+ public_template[4].pValue = pk11_ecc_ed448;
+ public_template[4].ulValueLen =
+ sizeof(pk11_ecc_ed448);
+ }
+
+ break;
+ case key_dsa:
+ op_type = OP_DSA;
+ if (bits == 0)
+ usage();
+
+ dpmech.mechanism = CKM_DSA_PARAMETER_GEN;
+ dpmech.pParameter = NULL;
+ dpmech.ulParameterLen = 0;
+ mech.mechanism = CKM_DSA_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ public_template = dsa_template;
+ public_attrcnt = DSA_ATTRS;
+ id_offset = DSA_ID;
+
+ domain_template = dsa_domain_template;
+ domain_attrcnt = DSA_DOMAIN_ATTRS;
+ param_template = dsa_param_template;
+ param_attrcnt = DSA_PARAM_ATTRS;
+
+ domain_template[DSA_DOMAIN_PRIMEBITS].pValue = &bits;
+ domain_template[DSA_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits);
+ break;
+ case key_dh:
+ op_type = OP_DH;
+ if (special && bits == 0)
+ bits = 1024;
+ else if (special &&
+ bits != 768 && bits != 1024 && bits != 1536)
+ {
+ fprintf(stderr, "When using the special prime (-S) "
+ "option, only key sizes of\n"
+ "768, 1024 or 1536 are supported.\n");
+ exit(2);
+ } else if (bits == 0)
+ usage();
+
+ dpmech.mechanism = CKM_DH_PKCS_PARAMETER_GEN;
+ dpmech.pParameter = NULL;
+ dpmech.ulParameterLen = 0;
+ mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ /* Override CKA_SIGN attribute */
+ private_template[PRIVATE_DERIVE].type = CKA_DERIVE;
+
+ public_template = dh_template;
+ public_attrcnt = DH_ATTRS;
+ id_offset = DH_ID;
+
+ domain_template = dh_domain_template;
+ domain_attrcnt = DH_DOMAIN_ATTRS;
+ param_template = dh_param_template;
+ param_attrcnt = DH_PARAM_ATTRS;
+
+ domain_template[DH_DOMAIN_PRIMEBITS].pValue = &bits;
+ domain_template[DH_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits);
+ break;
+ case key_unknown:
+ usage();
+ }
+
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen((char *)label);
+ public_template[0].pValue = label;
+ public_template[0].ulValueLen = strlen((char *)label);
+ private_template[0].pValue = label;
+ private_template[0].ulValueLen = strlen((char *)label);
+
+ if (idlen == 0) {
+ public_attrcnt--;
+ private_attrcnt--;
+ } else {
+ if (id <= 0xffff) {
+ idlen = 2;
+ idbuf[0] = (CK_BYTE)(id >> 8);
+ idbuf[1] = (CK_BYTE)id;
+ } else {
+ idbuf[0] = (CK_BYTE)(id >> 24);
+ idbuf[1] = (CK_BYTE)(id >> 16);
+ idbuf[2] = (CK_BYTE)(id >> 8);
+ idbuf[3] = (CK_BYTE)id;
+ }
+
+ public_template[id_offset].pValue = idbuf;
+ public_template[id_offset].ulValueLen = idlen;
+ private_template[PRIVATE_ID].pValue = idbuf;
+ private_template[PRIVATE_ID].ulValueLen = idlen;
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, true,
+ true, (const char *) pin, slot);
+ if (result == PK11_R_NORANDOMSERVICE ||
+ result == PK11_R_NODIGESTSERVICE ||
+ result == PK11_R_NOAESSERVICE) {
+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
+ fprintf(stderr, "This HSM will not work with BIND 9 "
+ "using native PKCS#11.\n");
+ } else if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Unrecoverable error initializing "
+ "PKCS#11: %s\n", isc_result_totext(result));
+ exit(1);
+ }
+
+ memset(pin, 0, strlen(pin));
+
+ hSession = pctx.session;
+
+ /* check if a key with the same id already exists */
+ rv = pkcs_C_FindObjectsInit(hSession, search_template, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ rv = pkcs_C_FindObjects(hSession, &privatekey, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+ if (ulObjectCount != 0) {
+ fprintf(stderr, "Key already exists.\n");
+ error = 1;
+ goto exit_search;
+ }
+
+ /* Set attributes if the key is not to be hidden */
+ if (!hide) {
+ private_template[4].pValue = &falsevalue;
+ private_template[5].pValue = &truevalue;
+ }
+
+ if (keyclass == key_rsa || keyclass == key_ecc || keyclass == key_ecx)
+ goto generate_keys;
+
+ /*
+ * Special setup for Diffie-Hellman keys
+ */
+ if (special != 0) {
+ public_template[DH_BASE].pValue = pk11_dh_bn2;
+ public_template[DH_BASE].ulValueLen = sizeof(pk11_dh_bn2);
+ if (bits == 768) {
+ public_template[DH_PRIME].pValue = pk11_dh_bn768;
+ public_template[DH_PRIME].ulValueLen =
+ sizeof(pk11_dh_bn768);
+ } else if (bits == 1024) {
+ public_template[DH_PRIME].pValue = pk11_dh_bn1024;
+ public_template[DH_PRIME].ulValueLen =
+ sizeof(pk11_dh_bn1024);
+ } else {
+ public_template[DH_PRIME].pValue = pk11_dh_bn1536;
+ public_template[DH_PRIME].ulValueLen =
+ sizeof(pk11_dh_bn1536);
+ }
+ param_attrcnt = 0;
+ goto generate_keys;
+ }
+
+ /* Generate Domain parameters */
+ rv = pkcs_C_GenerateKey(hSession, &dpmech, domain_template,
+ domain_attrcnt, &domainparams);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GenerateKey: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
+ /* Get Domain parameters */
+ rv = pkcs_C_GetAttributeValue(hSession, domainparams,
+ param_template, param_attrcnt);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GetAttributeValue0: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_domain;
+ }
+
+ /* Allocate space for parameter attributes */
+ for (i = 0; i < param_attrcnt; i++) {
+ param_template[i].pValue = NULL;
+ }
+
+ for (i = 0; i < param_attrcnt; i++) {
+ param_template[i].pValue = malloc(param_template[i].ulValueLen);
+ if (param_template[i].pValue == NULL) {
+ fprintf(stderr, "malloc failed\n");
+ error = 1;
+ goto exit_params;
+ }
+ }
+
+ rv = pkcs_C_GetAttributeValue(hSession, domainparams,
+ dsa_param_template, DSA_PARAM_ATTRS);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GetAttributeValue1: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_params;
+ }
+
+ switch (keyclass) {
+ case key_dsa:
+ public_template[DSA_PRIME].pValue =
+ param_template[DSA_PARAM_PRIME].pValue;
+ public_template[DSA_PRIME].ulValueLen =
+ param_template[DSA_PARAM_PRIME].ulValueLen;
+ public_template[DSA_SUBPRIME].pValue =
+ param_template[DSA_PARAM_SUBPRIME].pValue;
+ public_template[DSA_SUBPRIME].ulValueLen =
+ param_template[DSA_PARAM_SUBPRIME].ulValueLen;
+ public_template[DSA_BASE].pValue =
+ param_template[DSA_PARAM_BASE].pValue;
+ public_template[DSA_BASE].ulValueLen =
+ param_template[DSA_PARAM_BASE].ulValueLen;
+ break;
+ case key_dh:
+ public_template[DH_PRIME].pValue =
+ param_template[DH_PARAM_PRIME].pValue;
+ public_template[DH_PRIME].ulValueLen =
+ param_template[DH_PARAM_PRIME].ulValueLen;
+ public_template[DH_BASE].pValue =
+ param_template[DH_PARAM_BASE].pValue;
+ public_template[DH_BASE].ulValueLen =
+ param_template[DH_PARAM_BASE].ulValueLen;
+ default:
+ break;
+ }
+
+ generate_keys:
+ /* Generate Key pair for signing/verifying */
+ rv = pkcs_C_GenerateKeyPair(hSession, &mech,
+ public_template, public_attrcnt,
+ private_template, private_attrcnt,
+ &publickey, &privatekey);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateKeyPair: Error = 0x%.8lX\n", rv);
+ error = 1;
+ } else if (!quiet)
+ printf("Key pair generation complete.\n");
+
+ exit_params:
+ /* Free parameter attributes */
+ if (keyclass == key_dsa || keyclass == key_dh) {
+ for (i = 0; i < param_attrcnt; i++) {
+ if (param_template[i].pValue != NULL) {
+ free(param_template[i].pValue);
+ }
+ }
+ }
+
+ exit_domain:
+ /* Destroy domain parameters */
+ if (keyclass == key_dsa || (keyclass == key_dh && !special)) {
+ rv = pkcs_C_DestroyObject(hSession, domainparams);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DestroyObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+ }
+
+ exit_search:
+ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/pkcs11/pkcs11-keygen.docbook b/bin/pkcs11/pkcs11-keygen.docbook
new file mode 100644
index 0000000..0307e55
--- /dev/null
+++ b/bin/pkcs11/pkcs11-keygen.docbook
@@ -0,0 +1,205 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.pkcs11-keygen">
+ <info>
+ <date>2014-01-15</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>pkcs11-keygen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>pkcs11-keygen</application></refname>
+ <refpurpose>generate keys on a PKCS#11 device</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>pkcs11-keygen</command>
+ <arg choice="req" rep="norepeat">-a <replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">keysize</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-e</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">id</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">module</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">PIN</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-S</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">slot</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">label</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>pkcs11-keygen</command> causes a PKCS#11 device to generate
+ a new key pair with the given <option>label</option> (which must be
+ unique) and with <option>keysize</option> bits of prime.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Specify the key algorithm class: Supported classes are RSA,
+ DSA, DH, ECC and ECX. In addition to these strings, the
+ <option>algorithm</option> can be specified as a DNSSEC
+ signing algorithm that will be used with this key; for
+ example, NSEC3RSASHA1 maps to RSA, ECDSAP256SHA256 maps
+ to ECC, and ED25519 to ECX. The default class is "RSA".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+ Create the key pair with <option>keysize</option> bits of
+ prime. For ECC keys, the only valid values are 256 and 384,
+ and the default is 256. For ECX kyes, the only valid values
+ are 256 and 456, and the default is 256.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e</term>
+ <listitem>
+ <para>
+ For RSA keys only, use a large exponent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">id</replaceable></term>
+ <listitem>
+ <para>
+ Create key objects with id. The id is either
+ an unsigned short 2 byte or an unsigned long 4 byte number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">module</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P</term>
+ <listitem>
+ <para>
+ Set the new private key to be non-sensitive and extractable.
+ The allows the private key data to be read from the PKCS#11
+ device. The default is for private keys to be sensitive and
+ non-extractable.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">PIN</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PIN for the device. If no PIN is provided on
+ the command line, <command>pkcs11-keygen</command> will
+ prompt for it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ Quiet mode: suppress unnecessary output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S</term>
+ <listitem>
+ <para>
+ For Diffie-Hellman (DH) keys only, use a special prime of
+ 768, 1024 or 1536 bit size and base (aka generator) 2.
+ If not specified, bit size will default to 1024.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">slot</replaceable></term>
+ <listitem>
+ <para>
+ Open the session with the given PKCS#11 slot. The default is
+ slot 0.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>pkcs11-destroy</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-list</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-tokens</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keyfromlabel</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/pkcs11/pkcs11-keygen.html b/bin/pkcs11/pkcs11-keygen.html
new file mode 100644
index 0000000..6eaefb1
--- /dev/null
+++ b/bin/pkcs11/pkcs11-keygen.html
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>pkcs11-keygen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.pkcs11-keygen"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">pkcs11-keygen</span>
+ &#8212; generate keys on a PKCS#11 device
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">pkcs11-keygen</code>
+ {-a <em class="replaceable"><code>algorithm</code></em>}
+ [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>]
+ [<code class="option">-e</code>]
+ [<code class="option">-i <em class="replaceable"><code>id</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>module</code></em></code>]
+ [<code class="option">-P</code>]
+ [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-S</code>]
+ [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>]
+ {label}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>pkcs11-keygen</strong></span> causes a PKCS#11 device to generate
+ a new key pair with the given <code class="option">label</code> (which must be
+ unique) and with <code class="option">keysize</code> bits of prime.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+ <p>
+ Specify the key algorithm class: Supported classes are RSA,
+ DSA, DH, ECC and ECX. In addition to these strings, the
+ <code class="option">algorithm</code> can be specified as a DNSSEC
+ signing algorithm that will be used with this key; for
+ example, NSEC3RSASHA1 maps to RSA, ECDSAP256SHA256 maps
+ to ECC, and ED25519 to ECX. The default class is "RSA".
+ </p>
+ </dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd>
+ <p>
+ Create the key pair with <code class="option">keysize</code> bits of
+ prime. For ECC keys, the only valid values are 256 and 384,
+ and the default is 256. For ECX kyes, the only valid values
+ are 256 and 456, and the default is 256.
+ </p>
+ </dd>
+<dt><span class="term">-e</span></dt>
+<dd>
+ <p>
+ For RSA keys only, use a large exponent.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>id</code></em></span></dt>
+<dd>
+ <p>
+ Create key objects with id. The id is either
+ an unsigned short 2 byte or an unsigned long 4 byte number.
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </p>
+ </dd>
+<dt><span class="term">-P</span></dt>
+<dd>
+ <p>
+ Set the new private key to be non-sensitive and extractable.
+ The allows the private key data to be read from the PKCS#11
+ device. The default is for private keys to be sensitive and
+ non-extractable.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>PIN</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PIN for the device. If no PIN is provided on
+ the command line, <span class="command"><strong>pkcs11-keygen</strong></span> will
+ prompt for it.
+ </p>
+ </dd>
+<dt><span class="term">-q</span></dt>
+<dd>
+ <p>
+ Quiet mode: suppress unnecessary output.
+ </p>
+ </dd>
+<dt><span class="term">-S</span></dt>
+<dd>
+ <p>
+ For Diffie-Hellman (DH) keys only, use a special prime of
+ 768, 1024 or 1536 bit size and base (aka generator) 2.
+ If not specified, bit size will default to 1024.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>slot</code></em></span></dt>
+<dd>
+ <p>
+ Open the session with the given PKCS#11 slot. The default is
+ slot 0.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-destroy</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-list</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-tokens</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keyfromlabel</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/pkcs11/pkcs11-list.8 b/bin/pkcs11/pkcs11-list.8
new file mode 100644
index 0000000..06c887d
--- /dev/null
+++ b/bin/pkcs11/pkcs11-list.8
@@ -0,0 +1,98 @@
+.\" Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: pkcs11-list
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-10-05
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "PKCS11\-LIST" "8" "2009\-10\-05" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+pkcs11-list \- list PKCS#11 objects
+.SH "SYNOPSIS"
+.HP \w'\fBpkcs11\-list\fR\ 'u
+\fBpkcs11\-list\fR [\fB\-P\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] [\-i\ \fIID\fR] [\-l\ \fIlabel\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR]
+.SH "DESCRIPTION"
+.PP
+\fBpkcs11\-list\fR
+lists the PKCS#11 objects with
+\fBID\fR
+or
+\fBlabel\fR
+or by default all objects\&. The object class, label, and ID are displayed for all keys\&. For private or secret keys, the extractability attribute is also displayed, as either
+true,
+false, or
+never\&.
+.SH "ARGUMENTS"
+.PP
+\-P
+.RS 4
+List only the public objects\&. (Note that on some PKCS#11 devices, all objects are private\&.)
+.RE
+.PP
+\-m \fImodule\fR
+.RS 4
+Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&.
+.RE
+.PP
+\-s \fIslot\fR
+.RS 4
+Open the session with the given PKCS#11 slot\&. The default is slot 0\&.
+.RE
+.PP
+\-i \fIID\fR
+.RS 4
+List only key objects with the given object ID\&.
+.RE
+.PP
+\-l \fIlabel\fR
+.RS 4
+List only key objects with the given label\&.
+.RE
+.PP
+\-p \fIPIN\fR
+.RS 4
+Specify the PIN for the device\&. If no PIN is provided on the command line,
+\fBpkcs11\-list\fR
+will prompt for it\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBpkcs11-destroy\fR(8),
+\fBpkcs11-keygen\fR(8),
+\fBpkcs11-tokens\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/pkcs11/pkcs11-list.c b/bin/pkcs11/pkcs11-list.c
new file mode 100644
index 0000000..8912521
--- /dev/null
+++ b/bin/pkcs11/pkcs11-list.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* pkcs11-list [-P] [-m module] [-s slot] [-i $id | -l $label] [-p $pin] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE attr_id[2];
+ CK_OBJECT_HANDLE akey[50];
+ pk11_context_t pctx;
+ char *lib_name = NULL;
+ char *label = NULL;
+ char *pin = NULL;
+ bool error = false, logon = true, all = false;
+ unsigned int i = 0, id = 0;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &attr_id, sizeof(attr_id)}
+ };
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:P")) != -1) {
+ switch (c) {
+ case 'P':
+ logon = false;
+ break;
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'i':
+ id = atoi(isc_commandline_argument);
+ id &= 0xffff;
+ break;
+ case 'l':
+ label = isc_commandline_argument;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tpkcs11-list [-P] [-m module] [-s slot] "
+ "[-i id | -l label] [-p pin]\n");
+ exit(1);
+ }
+
+ if (!id && (label == NULL))
+ all = true;
+
+ if (slot)
+ printf("slot %lu\n", slot);
+
+ if (id) {
+ printf("id %u\n", id);
+ attr_id[0] = (id >> 8) & 0xff;
+ attr_id[1] = id & 0xff;
+ } else if (label != NULL) {
+ printf("label %s\n", label);
+ search_template[0].type = CKA_LABEL;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (logon && pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, OP_ANY, false, false,
+ logon, pin, slot);
+ if (result == PK11_R_NORANDOMSERVICE ||
+ result == PK11_R_NODIGESTSERVICE ||
+ result == PK11_R_NOAESSERVICE) {
+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
+ fprintf(stderr, "This HSM will not work with BIND 9 "
+ "using native PKCS#11.\n");
+ } else if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Unrecoverable error initializing "
+ "PKCS#11: %s\n", isc_result_totext(result));
+ fprintf(stderr, "Unrecoverable error initializing "
+ "PKCS#11: %s\n", isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen(pin));
+
+ hSession = pctx.session;
+
+ rv = pkcs_C_FindObjectsInit(hSession, search_template, all ? 0 : 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ ulObjectCount = 1;
+ while (ulObjectCount) {
+ rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjects: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_search;
+ }
+ for (i = 0; i < ulObjectCount; i++) {
+ unsigned int j, len;
+
+ CK_OBJECT_CLASS oclass = 0;
+ CK_BYTE labelbuf[64 + 1];
+ CK_BYTE idbuf[64];
+ CK_BBOOL extract = TRUE;
+ CK_BBOOL never = FALSE;
+ CK_ATTRIBUTE template[] = {
+ {CKA_CLASS, &oclass, sizeof(oclass)},
+ {CKA_LABEL, labelbuf, sizeof(labelbuf) - 1},
+ {CKA_ID, idbuf, sizeof(idbuf)}
+ };
+ CK_ATTRIBUTE priv_template[] = {
+ {CKA_EXTRACTABLE, &extract, sizeof(extract)},
+ {CKA_NEVER_EXTRACTABLE, &never, sizeof(never)}
+ };
+
+ memset(labelbuf, 0, sizeof(labelbuf));
+ memset(idbuf, 0, sizeof(idbuf));
+
+ rv = pkcs_C_GetAttributeValue(hSession, akey[i],
+ template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GetAttributeValue[%u]: "
+ "rv = 0x%.8lX\n",
+ i, rv);
+ if (rv == CKR_BUFFER_TOO_SMALL)
+ fprintf(stderr,
+ "%u too small: %lu %lu %lu\n",
+ i,
+ template[0].ulValueLen,
+ template[1].ulValueLen,
+ template[2].ulValueLen);
+ error = 1;
+ continue;
+ }
+
+ len = template[2].ulValueLen;
+ printf("object[%u]: handle %lu class %lu "
+ "label[%lu] '%s' id[%lu] ",
+ i, akey[i], oclass,
+ template[1].ulValueLen,
+ labelbuf,
+ template[2].ulValueLen);
+ if (len == 2) {
+ id = (idbuf[0] << 8) & 0xff00;
+ id |= idbuf[1] & 0xff;
+ printf("%u", id);
+ } else {
+ if (len > 8)
+ len = 8;
+ if (len > 0)
+ printf("0x");
+ for (j = 0; j < len; j++)
+ printf("%02x", idbuf[j]);
+ if (template[2].ulValueLen > len)
+ printf("...");
+ }
+ if ((oclass == CKO_PRIVATE_KEY ||
+ oclass == CKO_SECRET_KEY) &&
+ pkcs_C_GetAttributeValue(hSession, akey[i],
+ priv_template, 2) == CKR_OK) {
+ printf(" E:%s",
+ extract ? "true" :
+ (never ? "never" : "false"));
+ }
+ printf("\n");
+ }
+ }
+
+ exit_search:
+ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/pkcs11/pkcs11-list.docbook b/bin/pkcs11/pkcs11-list.docbook
new file mode 100644
index 0000000..b929a15
--- /dev/null
+++ b/bin/pkcs11/pkcs11-list.docbook
@@ -0,0 +1,149 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.pkcs11-list">
+ <info>
+ <date>2009-10-05</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>pkcs11-list</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>pkcs11-list</application></refname>
+ <refpurpose>list PKCS#11 objects</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>pkcs11-list</command>
+ <arg choice="opt" rep="norepeat"><option>-P</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">module</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">slot</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat">-i <replaceable class="parameter">ID</replaceable></arg>
+ <arg choice="opt" rep="norepeat">-l <replaceable class="parameter">label</replaceable></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">PIN</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>pkcs11-list</command>
+ lists the PKCS#11 objects with <option>ID</option> or
+ <option>label</option> or by default all objects.
+ The object class, label, and ID are displayed for all
+ keys. For private or secret keys, the extractability
+ attribute is also displayed, as either <literal>true</literal>,
+ <literal>false</literal>, or <literal>never</literal>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P</term>
+ <listitem>
+ <para>
+ List only the public objects. (Note that on some PKCS#11
+ devices, all objects are private.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">module</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">slot</replaceable></term>
+ <listitem>
+ <para>
+ Open the session with the given PKCS#11 slot. The default is
+ slot 0.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">ID</replaceable></term>
+ <listitem>
+ <para>
+ List only key objects with the given object ID.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">label</replaceable></term>
+ <listitem>
+ <para>
+ List only key objects with the given label.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">PIN</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PIN for the device. If no PIN is provided on the
+ command line, <command>pkcs11-list</command> will prompt for it.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>pkcs11-destroy</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-tokens</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/pkcs11/pkcs11-list.html b/bin/pkcs11/pkcs11-list.html
new file mode 100644
index 0000000..fedfb6f
--- /dev/null
+++ b/bin/pkcs11/pkcs11-list.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>pkcs11-list</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.pkcs11-list"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">pkcs11-list</span>
+ &#8212; list PKCS#11 objects
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">pkcs11-list</code>
+ [<code class="option">-P</code>]
+ [<code class="option">-m <em class="replaceable"><code>module</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>]
+ [-i <em class="replaceable"><code>ID</code></em>]
+ [-l <em class="replaceable"><code>label</code></em>]
+ [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>pkcs11-list</strong></span>
+ lists the PKCS#11 objects with <code class="option">ID</code> or
+ <code class="option">label</code> or by default all objects.
+ The object class, label, and ID are displayed for all
+ keys. For private or secret keys, the extractability
+ attribute is also displayed, as either <code class="literal">true</code>,
+ <code class="literal">false</code>, or <code class="literal">never</code>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-P</span></dt>
+<dd>
+ <p>
+ List only the public objects. (Note that on some PKCS#11
+ devices, all objects are private.)
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>slot</code></em></span></dt>
+<dd>
+ <p>
+ Open the session with the given PKCS#11 slot. The default is
+ slot 0.
+ </p>
+ </dd>
+<dt><span class="term">-i <em class="replaceable"><code>ID</code></em></span></dt>
+<dd>
+ <p>
+ List only key objects with the given object ID.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
+<dd>
+ <p>
+ List only key objects with the given label.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>PIN</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PIN for the device. If no PIN is provided on the
+ command line, <span class="command"><strong>pkcs11-list</strong></span> will prompt for it.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-destroy</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-tokens</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/pkcs11/pkcs11-tokens.8 b/bin/pkcs11/pkcs11-tokens.8
new file mode 100644
index 0000000..d204d65
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.8
@@ -0,0 +1,69 @@
+.\" Copyright (C) 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: pkcs11-tokens
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-15
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "PKCS11\-TOKENS" "8" "2014\-01\-15" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+pkcs11-tokens \- list PKCS#11 available tokens
+.SH "SYNOPSIS"
+.HP \w'\fBpkcs11\-tokens\fR\ 'u
+\fBpkcs11\-tokens\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-v\fR]
+.SH "DESCRIPTION"
+.PP
+\fBpkcs11\-tokens\fR
+lists the PKCS#11 available tokens with defaults from the slot/token scan performed at application initialization\&.
+.SH "ARGUMENTS"
+.PP
+\-m \fImodule\fR
+.RS 4
+Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&.
+.RE
+.PP
+\-v
+.RS 4
+Make the PKCS#11 libisc initialization verbose\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBpkcs11-destroy\fR(8),
+\fBpkcs11-keygen\fR(8),
+\fBpkcs11-list\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/pkcs11/pkcs11-tokens.c b/bin/pkcs11/pkcs11-tokens.c
new file mode 100644
index 0000000..564710a
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/* pkcs11-tokens [-m module] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ char *lib_name = NULL;
+ int c, errflg = 0;
+ isc_mem_t *mctx = NULL;
+ pk11_context_t pctx;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:v")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 'v':
+ pk11_verbose_init = true;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tpkcs11-tokens [-v] [-m module]\n");
+ exit(1);
+ }
+
+ if (isc_mem_create(0, 0, &mctx) != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_mem_create() failed\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ result = pk11_get_session(&pctx, OP_ANY, true, false,
+ false, NULL, 0);
+ if (result == PK11_R_NORANDOMSERVICE ||
+ result == PK11_R_NODIGESTSERVICE ||
+ result == PK11_R_NOAESSERVICE) {
+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
+ fprintf(stderr, "This HSM will not work with BIND 9 "
+ "using native PKCS#11.\n\n");
+ } else if ((result != ISC_R_SUCCESS) && (result != ISC_R_NOTFOUND)) {
+ fprintf(stderr, "Unrecoverable error initializing "
+ "PKCS#11: %s\n", isc_result_totext(result));
+ exit(1);
+ }
+
+ pk11_dump_tokens();
+
+ if (pctx.handle != NULL)
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ isc_mem_destroy(&mctx);
+
+ exit(0);
+}
diff --git a/bin/pkcs11/pkcs11-tokens.docbook b/bin/pkcs11/pkcs11-tokens.docbook
new file mode 100644
index 0000000..4c3ebaa
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.docbook
@@ -0,0 +1,101 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.pkcs11-tokens">
+ <info>
+ <date>2014-01-15</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>pkcs11-tokens</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>pkcs11-tokens</application></refname>
+ <refpurpose>list PKCS#11 available tokens</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>pkcs11-tokens</command>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">module</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>pkcs11-tokens</command>
+ lists the PKCS#11 available tokens with defaults from the slot/token
+ scan performed at application initialization.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>-m <replaceable class="parameter">module</replaceable></term>
+ <listitem>
+ <para>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Make the PKCS#11 libisc initialization verbose.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>pkcs11-destroy</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pkcs11-list</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/pkcs11/pkcs11-tokens.html b/bin/pkcs11/pkcs11-tokens.html
new file mode 100644
index 0000000..7a76539
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>pkcs11-tokens</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.pkcs11-tokens"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">pkcs11-tokens</span>
+ &#8212; list PKCS#11 available tokens
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">pkcs11-tokens</code>
+ [<code class="option">-m <em class="replaceable"><code>module</code></em></code>]
+ [<code class="option">-v</code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>pkcs11-tokens</strong></span>
+ lists the PKCS#11 available tokens with defaults from the slot/token
+ scan performed at application initialization.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
+<dd>
+ <p>
+ Specify the PKCS#11 provider module. This must be the full
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Make the PKCS#11 libisc initialization verbose.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-destroy</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">pkcs11-list</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/pkcs11/win32/pk11destroy.dsp.in b/bin/pkcs11/win32/pk11destroy.dsp.in
new file mode 100644
index 0000000..6c217d9
--- /dev/null
+++ b/bin/pkcs11/win32/pk11destroy.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="pk11destroy" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=pk11destroy - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pk11destroy.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11destroy.mak" CFG="pk11destroy - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11destroy - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11destroy - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-destroy.exe"
+
+!ELSEIF "$(CFG)" == "pk11destroy - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-destroy.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pk11destroy - @PLATFORM@ Release"
+# Name "pk11destroy - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\pkcs11-destroy.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/pkcs11/win32/pk11destroy.dsw b/bin/pkcs11/win32/pk11destroy.dsw
new file mode 100644
index 0000000..cd46783
--- /dev/null
+++ b/bin/pkcs11/win32/pk11destroy.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "pk11destroy"=".\pk11destroy.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/pkcs11/win32/pk11destroy.mak.in b/bin/pkcs11/win32/pk11destroy.mak.in
new file mode 100644
index 0000000..1fc79d1
--- /dev/null
+++ b/bin/pkcs11/win32/pk11destroy.mak.in
@@ -0,0 +1,296 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on pk11destroy.dsp
+!IF "$(CFG)" == ""
+CFG=pk11destroy - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to pk11destroy - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "pk11destroy - @PLATFORM@ Release" && "$(CFG)" != "pk11destroy - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11destroy.mak" CFG="pk11destroy - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11destroy - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11destroy - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\pkcs11-destroy.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-destroy.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\pkcs11-destroy.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11destroy.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11destroy.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-destroy.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-destroy.exe"
+LINK32_OBJS= "$(INTDIR)\pkcs11-destroy.obj"
+
+"..\..\..\Build\Release\pkcs11-destroy.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "pk11destroy - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\pkcs11-destroy.exe" "$(OUTDIR)\pk11destroy.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-destroy.obj"
+ -@erase "$(INTDIR)\pkcs11-destroy.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\pkcs11-destroy.pdb"
+ -@erase "$(OUTDIR)\pk11destroy.bsc"
+ -@erase "..\..\..\Build\Debug\pkcs11-destroy.exe"
+ -@erase "..\..\..\Build\Debug\pkcs11-destroy.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11destroy.bsc"
+BSC32_SBRS= "$(INTDIR)\pkcs11-destroy.sbr"
+
+"$(OUTDIR)\pk11destroy.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-destroy.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-destroy.exe" /pdbtype:sept
+LINK32_OBJS= "$(INTDIR)\pkcs11-destroy.obj"
+
+"..\..\..\Build\Debug\pkcs11-destroy.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("pk11destroy.dep")
+!INCLUDE "pk11destroy.dep"
+!ELSE
+!MESSAGE Warning: cannot find "pk11destroy.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release" || "$(CFG)" == "pk11destroy - @PLATFORM@ Debug"
+SOURCE="..\pkcs11-destroy.c"
+
+!IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pkcs11-destroy.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "pk11destroy - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pkcs11-destroy.obj" "$(INTDIR)\pkcs11-destroy.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/pkcs11/win32/pk11destroy.vcxproj.filters.in b/bin/pkcs11/win32/pk11destroy.vcxproj.filters.in
new file mode 100644
index 0000000..bdcc431
--- /dev/null
+++ b/bin/pkcs11/win32/pk11destroy.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-destroy.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11destroy.vcxproj.in b/bin/pkcs11/win32/pk11destroy.vcxproj.in
new file mode 100644
index 0000000..5f44159
--- /dev/null
+++ b/bin/pkcs11/win32/pk11destroy.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5B3137E5-7E1F-49AA-8810-A09AA417D326}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>pk11destroy</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-destroy</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-destroy</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-destroy.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/pkcs11/win32/pk11destroy.vcxproj.user b/bin/pkcs11/win32/pk11destroy.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/pkcs11/win32/pk11destroy.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11keygen.dsp.in b/bin/pkcs11/win32/pk11keygen.dsp.in
new file mode 100644
index 0000000..98d52e2
--- /dev/null
+++ b/bin/pkcs11/win32/pk11keygen.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="pk11keygen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=pk11keygen - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pk11keygen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11keygen.mak" CFG="pk11keygen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-keygen.exe"
+
+!ELSEIF "$(CFG)" == "pk11keygen - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-keygen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pk11keygen - @PLATFORM@ Release"
+# Name "pk11keygen - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\pkcs11-keygen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/pkcs11/win32/pk11keygen.dsw b/bin/pkcs11/win32/pk11keygen.dsw
new file mode 100644
index 0000000..5c52ce0
--- /dev/null
+++ b/bin/pkcs11/win32/pk11keygen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "pk11keygen"=".\pk11keygen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/pkcs11/win32/pk11keygen.mak.in b/bin/pkcs11/win32/pk11keygen.mak.in
new file mode 100644
index 0000000..d00f677
--- /dev/null
+++ b/bin/pkcs11/win32/pk11keygen.mak.in
@@ -0,0 +1,296 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on pk11keygen.dsp
+!IF "$(CFG)" == ""
+CFG=pk11keygen - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to pk11keygen - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "pk11keygen - @PLATFORM@ Release" && "$(CFG)" != "pk11keygen - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11keygen.mak" CFG="pk11keygen - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\pkcs11-keygen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-keygen.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\pkcs11-keygen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11keygen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11keygen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-keygen.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-keygen.exe"
+LINK32_OBJS= "$(INTDIR)\pkcs11-keygen.obj"
+
+"..\..\..\Build\Release\pkcs11-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "pk11keygen - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\pkcs11-keygen.exe" "$(OUTDIR)\pk11keygen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-keygen.obj"
+ -@erase "$(INTDIR)\pkcs11-keygen.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\pkcs11-keygen.pdb"
+ -@erase "$(OUTDIR)\pk11keygen.bsc"
+ -@erase "..\..\..\Build\Debug\pkcs11-keygen.exe"
+ -@erase "..\..\..\Build\Debug\pkcs11-keygen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11keygen.bsc"
+BSC32_SBRS= "$(INTDIR)\pkcs11-keygen.sbr"
+
+"$(OUTDIR)\pk11keygen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-keygen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-keygen.exe" /pdbtype:sept
+LINK32_OBJS= "$(INTDIR)\pkcs11-keygen.obj"
+
+"..\..\..\Build\Debug\pkcs11-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("pk11keygen.dep")
+!INCLUDE "pk11keygen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "pk11keygen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release" || "$(CFG)" == "pk11keygen - @PLATFORM@ Debug"
+SOURCE="..\pkcs11-keygen.c"
+
+!IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pkcs11-keygen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "pk11keygen - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pkcs11-keygen.obj" "$(INTDIR)\pkcs11-keygen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/pkcs11/win32/pk11keygen.vcxproj.filters.in b/bin/pkcs11/win32/pk11keygen.vcxproj.filters.in
new file mode 100644
index 0000000..412ff86
--- /dev/null
+++ b/bin/pkcs11/win32/pk11keygen.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-keygen.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11keygen.vcxproj.in b/bin/pkcs11/win32/pk11keygen.vcxproj.in
new file mode 100644
index 0000000..2395615
--- /dev/null
+++ b/bin/pkcs11/win32/pk11keygen.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5042D371-0402-4FA3-A52A-769708694422}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>pk11keygen</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-keygen</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-keygen</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-keygen.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/pkcs11/win32/pk11keygen.vcxproj.user b/bin/pkcs11/win32/pk11keygen.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/pkcs11/win32/pk11keygen.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11list.dsp.in b/bin/pkcs11/win32/pk11list.dsp.in
new file mode 100644
index 0000000..35e6c9c
--- /dev/null
+++ b/bin/pkcs11/win32/pk11list.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="pk11list" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=pk11list - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pk11list.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11list.mak" CFG="pk11list - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11list - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11list - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pk11list - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-list.exe"
+
+!ELSEIF "$(CFG)" == "pk11list - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-list.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pk11list - @PLATFORM@ Release"
+# Name "pk11list - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\pkcs11-list.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/pkcs11/win32/pk11list.dsw b/bin/pkcs11/win32/pk11list.dsw
new file mode 100644
index 0000000..352a03c
--- /dev/null
+++ b/bin/pkcs11/win32/pk11list.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "pk11list"=".\pk11list.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/pkcs11/win32/pk11list.mak.in b/bin/pkcs11/win32/pk11list.mak.in
new file mode 100644
index 0000000..3cd2537
--- /dev/null
+++ b/bin/pkcs11/win32/pk11list.mak.in
@@ -0,0 +1,296 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on pk11list.dsp
+!IF "$(CFG)" == ""
+CFG=pk11list - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to pk11list - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "pk11list - @PLATFORM@ Release" && "$(CFG)" != "pk11list - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11list.mak" CFG="pk11list - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11list - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11list - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "pk11list - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "pk11list - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\pkcs11-list.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-list.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\pkcs11-list.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11list.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11list.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-list.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-list.exe"
+LINK32_OBJS= "$(INTDIR)\pkcs11-list.obj"
+
+"..\..\..\Build\Release\pkcs11-list.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "pk11list - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\pkcs11-list.exe" "$(OUTDIR)\pk11list.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-list.obj"
+ -@erase "$(INTDIR)\pkcs11-list.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\pkcs11-list.pdb"
+ -@erase "$(OUTDIR)\pk11list.bsc"
+ -@erase "..\..\..\Build\Debug\pkcs11-list.exe"
+ -@erase "..\..\..\Build\Debug\pkcs11-list.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11list.bsc"
+BSC32_SBRS= "$(INTDIR)\pkcs11-list.sbr"
+
+"$(OUTDIR)\pk11list.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-list.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-list.exe" /pdbtype:sept
+LINK32_OBJS= "$(INTDIR)\pkcs11-list.obj"
+
+"..\..\..\Build\Debug\pkcs11-list.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("pk11list.dep")
+!INCLUDE "pk11list.dep"
+!ELSE
+!MESSAGE Warning: cannot find "pk11list.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "pk11list - @PLATFORM@ Release" || "$(CFG)" == "pk11list - @PLATFORM@ Debug"
+SOURCE="..\pkcs11-list.c"
+
+!IF "$(CFG)" == "pk11list - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pkcs11-list.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "pk11list - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pkcs11-list.obj" "$(INTDIR)\pkcs11-list.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/pkcs11/win32/pk11list.vcxproj.filters.in b/bin/pkcs11/win32/pk11list.vcxproj.filters.in
new file mode 100644
index 0000000..6944afd
--- /dev/null
+++ b/bin/pkcs11/win32/pk11list.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-list.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11list.vcxproj.in b/bin/pkcs11/win32/pk11list.vcxproj.in
new file mode 100644
index 0000000..e4d460d
--- /dev/null
+++ b/bin/pkcs11/win32/pk11list.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C663B088-F7BC-4C8C-8D06-A76636EED651}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>pk11list</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-list</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-list</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-list.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/pkcs11/win32/pk11list.vcxproj.user b/bin/pkcs11/win32/pk11list.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/pkcs11/win32/pk11list.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11tokens.dsp.in b/bin/pkcs11/win32/pk11tokens.dsp.in
new file mode 100644
index 0000000..013df20
--- /dev/null
+++ b/bin/pkcs11/win32/pk11tokens.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="pk11tokens" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=pk11tokens - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pk11tokens.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11tokens.mak" CFG="pk11tokens - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11tokens - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11tokens - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-tokens.exe"
+
+!ELSEIF "$(CFG)" == "pk11tokens - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-tokens.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pk11tokens - @PLATFORM@ Release"
+# Name "pk11tokens - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\pkcs11-tokens.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/pkcs11/win32/pk11tokens.dsw b/bin/pkcs11/win32/pk11tokens.dsw
new file mode 100644
index 0000000..571b588
--- /dev/null
+++ b/bin/pkcs11/win32/pk11tokens.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "pk11tokens"=".\pk11tokens.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/pkcs11/win32/pk11tokens.mak.in b/bin/pkcs11/win32/pk11tokens.mak.in
new file mode 100644
index 0000000..b7dec13
--- /dev/null
+++ b/bin/pkcs11/win32/pk11tokens.mak.in
@@ -0,0 +1,296 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on pk11tokens.dsp
+!IF "$(CFG)" == ""
+CFG=pk11tokens - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to pk11tokens - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "pk11tokens - @PLATFORM@ Release" && "$(CFG)" != "pk11tokens - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pk11tokens.mak" CFG="pk11tokens - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pk11tokens - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pk11tokens - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\pkcs11-tokens.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-tokens.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\pkcs11-tokens.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11tokens.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11tokens.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-tokens.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-tokens.exe"
+LINK32_OBJS= "$(INTDIR)\pkcs11-tokens.obj"
+
+"..\..\..\Build\Release\pkcs11-tokens.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "pk11tokens - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\pkcs11-tokens.exe" "$(OUTDIR)\pk11tokens.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\pkcs11-tokens.obj"
+ -@erase "$(INTDIR)\pkcs11-tokens.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\pkcs11-tokens.pdb"
+ -@erase "$(OUTDIR)\pk11tokens.bsc"
+ -@erase "..\..\..\Build\Debug\pkcs11-tokens.exe"
+ -@erase "..\..\..\Build\Debug\pkcs11-tokens.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11tokens.bsc"
+BSC32_SBRS= "$(INTDIR)\pkcs11-tokens.sbr"
+
+"$(OUTDIR)\pk11tokens.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-tokens.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-tokens.exe" /pdbtype:sept
+LINK32_OBJS= "$(INTDIR)\pkcs11-tokens.obj"
+
+"..\..\..\Build\Debug\pkcs11-tokens.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("pk11tokens.dep")
+!INCLUDE "pk11tokens.dep"
+!ELSE
+!MESSAGE Warning: cannot find "pk11tokens.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release" || "$(CFG)" == "pk11tokens - @PLATFORM@ Debug"
+SOURCE="..\pkcs11-tokens.c"
+
+!IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pkcs11-tokens.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "pk11tokens - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pkcs11-tokens.obj" "$(INTDIR)\pkcs11-tokens.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/pkcs11/win32/pk11tokens.vcxproj.filters.in b/bin/pkcs11/win32/pk11tokens.vcxproj.filters.in
new file mode 100644
index 0000000..7c3b8ed
--- /dev/null
+++ b/bin/pkcs11/win32/pk11tokens.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-tokens.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/pkcs11/win32/pk11tokens.vcxproj.in b/bin/pkcs11/win32/pk11tokens.vcxproj.in
new file mode 100644
index 0000000..554e551
--- /dev/null
+++ b/bin/pkcs11/win32/pk11tokens.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{403FD4B1-A4F9-4159-9013-5860E3A4417D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>pk11tokens</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-tokens</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>pkcs11-tokens</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pkcs11-tokens.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/pkcs11/win32/pk11tokens.vcxproj.user b/bin/pkcs11/win32/pk11tokens.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/pkcs11/win32/pk11tokens.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/python/Makefile.in b/bin/python/Makefile.in
new file mode 100644
index 0000000..aa678d4
--- /dev/null
+++ b/bin/python/Makefile.in
@@ -0,0 +1,80 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+PYTHON = @PYTHON@
+
+SUBDIRS = isc
+
+TARGETS = dnssec-checkds dnssec-coverage dnssec-keymgr
+PYSRCS = dnssec-checkds.py dnssec-coverage.py dnssec-keymgr.py
+
+MANPAGES = dnssec-checkds.8 dnssec-coverage.8 dnssec-keymgr.8
+HTMLPAGES = dnssec-checkds.html dnssec-coverage.html dnssec-keymgr.html
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+dnssec-checkds: dnssec-checkds.py
+ cp -f dnssec-checkds.py dnssec-checkds
+ chmod +x dnssec-checkds
+
+dnssec-coverage: dnssec-coverage.py
+ cp -f dnssec-coverage.py dnssec-coverage
+ chmod +x dnssec-coverage
+
+dnssec-keymgr: dnssec-keymgr.py
+ cp -f dnssec-keymgr.py dnssec-keymgr
+ chmod +x dnssec-keymgr
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: ${TARGETS} installdirs
+ ${INSTALL_SCRIPT} dnssec-checkds ${DESTDIR}${sbindir}
+ ${INSTALL_SCRIPT} dnssec-coverage ${DESTDIR}${sbindir}
+ ${INSTALL_SCRIPT} dnssec-keymgr ${DESTDIR}${sbindir}
+ ${INSTALL_DATA} ${srcdir}/dnssec-checkds.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/dnssec-coverage.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/dnssec-keymgr.8 ${DESTDIR}${mandir}/man8
+ if test -n "${PYTHON}" ; then \
+ if test -n "${DESTDIR}" ; then \
+ ${PYTHON} ${srcdir}/setup.py install --root=${DESTDIR} --prefix=${prefix} @PYTHON_INSTALL_LIB@ ; \
+ else \
+ ${PYTHON} ${srcdir}/setup.py install --prefix=${prefix} @PYTHON_INSTALL_LIB@ ; \
+ fi ; \
+ rm -rf build ; \
+ fi
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man8/dnssec-keymgr.8
+ rm -f ${DESTDIR}${mandir}/man8/dnssec-coverage.8
+ rm -f ${DESTDIR}${mandir}/man8/dnssec-checkds.8
+ rm -f ${DESTDIR}${sbindir}/dnssec-keymgr
+ rm -f ${DESTDIR}${sbindir}/dnssec-coverage
+ rm -f ${DESTDIR}${sbindir}/dnssec-checkds
+ # only manually uninstall for the python package itself
+
+clean distclean::
+ rm -f ${TARGETS}
+ rm -rf build
+
+distclean::
+ rm -f dnssec-checkds.py dnssec-coverage.py dnssec-keymgr.py
diff --git a/bin/python/dnssec-checkds.8 b/bin/python/dnssec-checkds.8
new file mode 100644
index 0000000..801970c
--- /dev/null
+++ b/bin/python/dnssec-checkds.8
@@ -0,0 +1,87 @@
+.\" Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-checkds
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2013-01-01
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-CHECKDS" "8" "2013\-01\-01" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-checkds \- DNSSEC delegation consistency checking tool
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-checkds\fR\ 'u
+\fBdnssec\-checkds\fR [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-d\ \fR\fB\fIdig\ path\fR\fR] [\fB\-D\ \fR\fB\fIdsfromkey\ path\fR\fR] {zone}
+.HP \w'\fBdnssec\-dsfromkey\fR\ 'u
+\fBdnssec\-dsfromkey\fR [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-d\ \fR\fB\fIdig\ path\fR\fR] [\fB\-D\ \fR\fB\fIdsfromkey\ path\fR\fR] {zone}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-checkds\fR
+verifies the correctness of Delegation Signer (DS) or DNSSEC Lookaside Validation (DLV) resource records for keys in a specified zone\&.
+.SH "OPTIONS"
+.PP
+\-f \fIfile\fR
+.RS 4
+If a
+\fBfile\fR
+is specified, then the zone is read from that file to find the DNSKEY records\&. If not, then the DNSKEY records for the zone are looked up in the DNS\&.
+.RE
+.PP
+\-l \fIdomain\fR
+.RS 4
+Check for a DLV record in the specified lookaside domain, instead of checking for a DS record in the zone\*(Aqs parent\&.
+.RE
+.PP
+\-d \fIdig path\fR
+.RS 4
+Specifies a path to a
+\fBdig\fR
+binary\&. Used for testing\&.
+.RE
+.PP
+\-D \fIdsfromkey path\fR
+.RS 4
+Specifies a path to a
+\fBdnssec\-dsfromkey\fR
+binary\&. Used for testing\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec-dsfromkey\fR(8),
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signzone\fR(8),
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/python/dnssec-checkds.docbook b/bin/python/dnssec-checkds.docbook
new file mode 100644
index 0000000..8c5f5b5
--- /dev/null
+++ b/bin/python/dnssec-checkds.docbook
@@ -0,0 +1,136 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-checkds">
+ <info>
+ <date>2013-01-01</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-checkds</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-checkds</application></refname>
+ <refpurpose>DNSSEC delegation consistency checking tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2012</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-checkds</command>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">dig path</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">dsfromkey path</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">zone</arg>
+ </cmdsynopsis>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-dsfromkey</command>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">dig path</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">dsfromkey path</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">zone</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-checkds</command>
+ verifies the correctness of Delegation Signer (DS) or DNSSEC
+ Lookaside Validation (DLV) resource records for keys in a specified
+ zone.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-f <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ If a <option>file</option> is specified, then the zone is
+ read from that file to find the DNSKEY records. If not,
+ then the DNSKEY records for the zone are looked up in the DNS.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Check for a DLV record in the specified lookaside domain,
+ instead of checking for a DS record in the zone's parent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">dig path</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a path to a <command>dig</command> binary. Used
+ for testing.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">dsfromkey path</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a path to a <command>dnssec-dsfromkey</command> binary.
+ Used for testing.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dnssec-dsfromkey</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/python/dnssec-checkds.html b/bin/python/dnssec-checkds.html
new file mode 100644
index 0000000..26c8ebe
--- /dev/null
+++ b/bin/python/dnssec-checkds.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-checkds</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-checkds"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-checkds</span>
+ &#8212; DNSSEC delegation consistency checking tool
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-checkds</code>
+ [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>file</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>dig path</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>dsfromkey path</code></em></code>]
+ {zone}
+ </p></div>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-dsfromkey</code>
+ [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>file</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>dig path</code></em></code>]
+ [<code class="option">-D <em class="replaceable"><code>dsfromkey path</code></em></code>]
+ {zone}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-checkds</strong></span>
+ verifies the correctness of Delegation Signer (DS) or DNSSEC
+ Lookaside Validation (DLV) resource records for keys in a specified
+ zone.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt>
+<dd>
+ <p>
+ If a <code class="option">file</code> is specified, then the zone is
+ read from that file to find the DNSKEY records. If not,
+ then the DNSKEY records for the zone are looked up in the DNS.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p>
+ Check for a DLV record in the specified lookaside domain,
+ instead of checking for a DS record in the zone's parent.
+ </p>
+ </dd>
+<dt><span class="term">-d <em class="replaceable"><code>dig path</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a path to a <span class="command"><strong>dig</strong></span> binary. Used
+ for testing.
+ </p>
+ </dd>
+<dt><span class="term">-D <em class="replaceable"><code>dsfromkey path</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a path to a <span class="command"><strong>dnssec-dsfromkey</strong></span> binary.
+ Used for testing.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dnssec-dsfromkey</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>,
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/python/dnssec-checkds.py.in b/bin/python/dnssec-checkds.py.in
new file mode 100644
index 0000000..ed5ac37
--- /dev/null
+++ b/bin/python/dnssec-checkds.py.in
@@ -0,0 +1,27 @@
+#!@PYTHON@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import os
+import sys
+
+sys.path.insert(0, os.path.dirname(sys.argv[0]))
+if os.name != 'nt':
+ if '@PYTHON_INSTALL_DIR@': # value of --with-python-install-dir
+ sys.path.insert(1, '@PYTHON_INSTALL_DIR@')
+ else:
+ sys.path.insert(1, os.path.join('@prefix@', 'lib',
+ 'python' + sys.version[:3], 'site-packages'))
+
+import isc.checkds
+
+if __name__ == "__main__":
+ isc.checkds.main()
diff --git a/bin/python/dnssec-coverage.8 b/bin/python/dnssec-coverage.8
new file mode 100644
index 0000000..2ffab1b
--- /dev/null
+++ b/bin/python/dnssec-coverage.8
@@ -0,0 +1,156 @@
+.\" Copyright (C) 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-coverage
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-11
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-COVERAGE" "8" "2014\-01\-11" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-coverage \- checks future DNSKEY coverage for a zone
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-coverage\fR\ 'u
+\fBdnssec\-coverage\fR [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-l\ \fR\fB\fIlength\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-d\ \fR\fB\fIDNSKEY\ TTL\fR\fR] [\fB\-m\ \fR\fB\fImax\ TTL\fR\fR] [\fB\-r\ \fR\fB\fIinterval\fR\fR] [\fB\-c\ \fR\fB\fIcompilezone\ path\fR\fR] [\fB\-k\fR] [\fB\-z\fR] [zone...]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-coverage\fR
+verifies that the DNSSEC keys for a given zone or a set of zones have timing metadata set properly to ensure no future lapses in DNSSEC coverage\&.
+.PP
+If
+\fBzone\fR
+is specified, then keys found in the key repository matching that zone are scanned, and an ordered list is generated of the events scheduled for that key (i\&.e\&., publication, activation, inactivation, deletion)\&. The list of events is walked in order of occurrence\&. Warnings are generated if any event is scheduled which could cause the zone to enter a state in which validation failures might occur: for example, if the number of published or active keys for a given algorithm drops to zero, or if a key is deleted from the zone too soon after a new key is rolled, and cached data signed by the prior key has not had time to expire from resolver caches\&.
+.PP
+If
+\fBzone\fR
+is not specified, then all keys in the key repository will be scanned, and all zones for which there are keys will be analyzed\&. (Note: This method of reporting is only accurate if all the zones that have keys in a given repository share the same TTL parameters\&.)
+.SH "OPTIONS"
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which keys can be found\&. Defaults to the current working directory\&.
+.RE
+.PP
+\-f \fIfile\fR
+.RS 4
+If a
+\fBfile\fR
+is specified, then the zone is read from that file; the largest TTL and the DNSKEY TTL are determined directly from the zone data, and the
+\fB\-m\fR
+and
+\fB\-d\fR
+options do not need to be specified on the command line\&.
+.RE
+.PP
+\-l \fIduration\fR
+.RS 4
+The length of time to check for DNSSEC coverage\&. Key events scheduled further into the future than
+\fBduration\fR
+will be ignored, and assumed to be correct\&.
+.sp
+The value of
+\fBduration\fR
+can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&.
+.RE
+.PP
+\-m \fImaximum TTL\fR
+.RS 4
+Sets the value to be used as the maximum TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure\&. When a zone\-signing key is deactivated, there must be enough time for the record in the zone with the longest TTL to have expired from resolver caches before that key can be purged from the DNSKEY RRset\&. If that condition does not apply, a warning will be generated\&.
+.sp
+The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&.
+.sp
+This option is not necessary if the
+\fB\-f\fR
+has been used to specify a zone file\&. If
+\fB\-f\fR
+has been specified, this option may still be used; it will override the value found in the file\&.
+.sp
+If this option is not used and the maximum TTL cannot be retrieved from a zone file, a warning is generated and a default value of 1 week is used\&.
+.RE
+.PP
+\-d \fIDNSKEY TTL\fR
+.RS 4
+Sets the value to be used as the DNSKEY TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure\&. When a key is rolled (that is, replaced with a new key), there must be enough time for the old DNSKEY RRset to have expired from resolver caches before the new key is activated and begins generating signatures\&. If that condition does not apply, a warning will be generated\&.
+.sp
+The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&.
+.sp
+This option is not necessary if
+\fB\-f\fR
+has been used to specify a zone file from which the TTL of the DNSKEY RRset can be read, or if a default key TTL was set using ith the
+\fB\-L\fR
+to
+\fBdnssec\-keygen\fR\&. If either of those is true, this option may still be used; it will override the values found in the zone file or the key file\&.
+.sp
+If this option is not used and the key TTL cannot be retrieved from the zone file or the key file, then a warning is generated and a default value of 1 day is used\&.
+.RE
+.PP
+\-r \fIresign interval\fR
+.RS 4
+Sets the value to be used as the resign interval for the zone or zones being analyzed when determining whether there is a possibility of validation failure\&. This value defaults to 22\&.5 days, which is also the default in
+\fBnamed\fR\&. However, if it has been changed by the
+\fBsig\-validity\-interval\fR
+option in
+named\&.conf, then it should also be changed here\&.
+.sp
+The length of the interval can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&.
+.RE
+.PP
+\-k
+.RS 4
+Only check KSK coverage; ignore ZSK events\&. Cannot be used with
+\fB\-z\fR\&.
+.RE
+.PP
+\-z
+.RS 4
+Only check ZSK coverage; ignore KSK events\&. Cannot be used with
+\fB\-k\fR\&.
+.RE
+.PP
+\-c \fIcompilezone path\fR
+.RS 4
+Specifies a path to a
+\fBnamed\-compilezone\fR
+binary\&. Used for testing\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec-checkds\fR(8),
+\fBdnssec-dsfromkey\fR(8),
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signzone\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/python/dnssec-coverage.docbook b/bin/python/dnssec-coverage.docbook
new file mode 100644
index 0000000..92a0c71
--- /dev/null
+++ b/bin/python/dnssec-coverage.docbook
@@ -0,0 +1,271 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-coverage">
+ <info>
+ <date>2014-01-11</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-coverage</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-coverage</application></refname>
+ <refpurpose>checks future DNSKEY coverage for a zone</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-coverage</command>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">length</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">DNSKEY TTL</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">max TTL</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">compilezone path</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-z</option></arg>
+ <arg choice="opt" rep="repeat">zone</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dnssec-coverage</command>
+ verifies that the DNSSEC keys for a given zone or a set of zones
+ have timing metadata set properly to ensure no future lapses in DNSSEC
+ coverage.
+ </para>
+ <para>
+ If <option>zone</option> is specified, then keys found in
+ the key repository matching that zone are scanned, and an ordered
+ list is generated of the events scheduled for that key (i.e.,
+ publication, activation, inactivation, deletion). The list of
+ events is walked in order of occurrence. Warnings are generated
+ if any event is scheduled which could cause the zone to enter a
+ state in which validation failures might occur: for example, if
+ the number of published or active keys for a given algorithm drops
+ to zero, or if a key is deleted from the zone too soon after a new
+ key is rolled, and cached data signed by the prior key has not had
+ time to expire from resolver caches.
+ </para>
+ <para>
+ If <option>zone</option> is not specified, then all keys in the
+ key repository will be scanned, and all zones for which there are
+ keys will be analyzed. (Note: This method of reporting is only
+ accurate if all the zones that have keys in a given repository
+ share the same TTL parameters.)
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which keys can be found. Defaults to the
+ current working directory.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ If a <option>file</option> is specified, then the zone is
+ read from that file; the largest TTL and the DNSKEY TTL are
+ determined directly from the zone data, and the
+ <option>-m</option> and <option>-d</option> options do
+ not need to be specified on the command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">duration</replaceable></term>
+ <listitem>
+ <para>
+ The length of time to check for DNSSEC coverage. Key events
+ scheduled further into the future than <option>duration</option>
+ will be ignored, and assumed to be correct.
+ </para>
+ <para>
+ The value of <option>duration</option> can be set in seconds,
+ or in larger units of time by adding a suffix: 'mi' for minutes,
+ 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months,
+ 'y' for years.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">maximum TTL</replaceable></term>
+ <listitem>
+ <para>
+ Sets the value to be used as the maximum TTL for the zone or
+ zones being analyzed when determining whether there is a
+ possibility of validation failure. When a zone-signing key is
+ deactivated, there must be enough time for the record in the
+ zone with the longest TTL to have expired from resolver caches
+ before that key can be purged from the DNSKEY RRset. If that
+ condition does not apply, a warning will be generated.
+ </para>
+ <para>
+ The length of the TTL can be set in seconds, or in larger units
+ of time by adding a suffix: 'mi' for minutes, 'h' for hours,
+ 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
+ </para>
+ <para>
+ This option is not necessary if the <option>-f</option> has
+ been used to specify a zone file. If <option>-f</option> has
+ been specified, this option may still be used; it will override
+ the value found in the file.
+ </para>
+ <para>
+ If this option is not used and the maximum TTL cannot be retrieved
+ from a zone file, a warning is generated and a default value of
+ 1 week is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">DNSKEY TTL</replaceable></term>
+ <listitem>
+ <para>
+ Sets the value to be used as the DNSKEY TTL for the zone or
+ zones being analyzed when determining whether there is a
+ possibility of validation failure. When a key is rolled (that
+ is, replaced with a new key), there must be enough time for the
+ old DNSKEY RRset to have expired from resolver caches before
+ the new key is activated and begins generating signatures. If
+ that condition does not apply, a warning will be generated.
+ </para>
+ <para>
+ The length of the TTL can be set in seconds, or in larger units
+ of time by adding a suffix: 'mi' for minutes, 'h' for hours,
+ 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
+ </para>
+ <para>
+ This option is not necessary if <option>-f</option> has
+ been used to specify a zone file from which the TTL
+ of the DNSKEY RRset can be read, or if a default key TTL was
+ set using ith the <option>-L</option> to
+ <command>dnssec-keygen</command>. If either of those is true,
+ this option may still be used; it will override the values
+ found in the zone file or the key file.
+ </para>
+ <para>
+ If this option is not used and the key TTL cannot be retrieved
+ from the zone file or the key file, then a warning is generated
+ and a default value of 1 day is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">resign interval</replaceable></term>
+ <listitem>
+ <para>
+ Sets the value to be used as the resign interval for the zone
+ or zones being analyzed when determining whether there is a
+ possibility of validation failure. This value defaults to
+ 22.5 days, which is also the default in
+ <command>named</command>. However, if it has been changed
+ by the <option>sig-validity-interval</option> option in
+ <filename>named.conf</filename>, then it should also be
+ changed here.
+ </para>
+ <para>
+ The length of the interval can be set in seconds, or in larger
+ units of time by adding a suffix: 'mi' for minutes, 'h' for hours,
+ 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Only check KSK coverage; ignore ZSK events. Cannot be
+ used with <option>-z</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Only check ZSK coverage; ignore KSK events. Cannot be
+ used with <option>-k</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">compilezone path</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a path to a <command>named-compilezone</command> binary.
+ Used for testing.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>dnssec-checkds</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-dsfromkey</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/python/dnssec-coverage.html b/bin/python/dnssec-coverage.html
new file mode 100644
index 0000000..7b4b5c4
--- /dev/null
+++ b/bin/python/dnssec-coverage.html
@@ -0,0 +1,236 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-coverage</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-coverage"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-coverage</span>
+ &#8212; checks future DNSKEY coverage for a zone
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-coverage</code>
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-l <em class="replaceable"><code>length</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>file</code></em></code>]
+ [<code class="option">-d <em class="replaceable"><code>DNSKEY TTL</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>max TTL</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>interval</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>compilezone path</code></em></code>]
+ [<code class="option">-k</code>]
+ [<code class="option">-z</code>]
+ [zone...]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dnssec-coverage</strong></span>
+ verifies that the DNSSEC keys for a given zone or a set of zones
+ have timing metadata set properly to ensure no future lapses in DNSSEC
+ coverage.
+ </p>
+ <p>
+ If <code class="option">zone</code> is specified, then keys found in
+ the key repository matching that zone are scanned, and an ordered
+ list is generated of the events scheduled for that key (i.e.,
+ publication, activation, inactivation, deletion). The list of
+ events is walked in order of occurrence. Warnings are generated
+ if any event is scheduled which could cause the zone to enter a
+ state in which validation failures might occur: for example, if
+ the number of published or active keys for a given algorithm drops
+ to zero, or if a key is deleted from the zone too soon after a new
+ key is rolled, and cached data signed by the prior key has not had
+ time to expire from resolver caches.
+ </p>
+ <p>
+ If <code class="option">zone</code> is not specified, then all keys in the
+ key repository will be scanned, and all zones for which there are
+ keys will be analyzed. (Note: This method of reporting is only
+ accurate if all the zones that have keys in a given repository
+ share the same TTL parameters.)
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which keys can be found. Defaults to the
+ current working directory.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt>
+<dd>
+ <p>
+ If a <code class="option">file</code> is specified, then the zone is
+ read from that file; the largest TTL and the DNSKEY TTL are
+ determined directly from the zone data, and the
+ <code class="option">-m</code> and <code class="option">-d</code> options do
+ not need to be specified on the command line.
+ </p>
+ </dd>
+<dt><span class="term">-l <em class="replaceable"><code>duration</code></em></span></dt>
+<dd>
+ <p>
+ The length of time to check for DNSSEC coverage. Key events
+ scheduled further into the future than <code class="option">duration</code>
+ will be ignored, and assumed to be correct.
+ </p>
+ <p>
+ The value of <code class="option">duration</code> can be set in seconds,
+ or in larger units of time by adding a suffix: 'mi' for minutes,
+ 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months,
+ 'y' for years.
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>maximum TTL</code></em></span></dt>
+<dd>
+ <p>
+ Sets the value to be used as the maximum TTL for the zone or
+ zones being analyzed when determining whether there is a
+ possibility of validation failure. When a zone-signing key is
+ deactivated, there must be enough time for the record in the
+ zone with the longest TTL to have expired from resolver caches
+ before that key can be purged from the DNSKEY RRset. If that
+ condition does not apply, a warning will be generated.
+ </p>
+ <p>
+ The length of the TTL can be set in seconds, or in larger units
+ of time by adding a suffix: 'mi' for minutes, 'h' for hours,
+ 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
+ </p>
+ <p>
+ This option is not necessary if the <code class="option">-f</code> has
+ been used to specify a zone file. If <code class="option">-f</code> has
+ been specified, this option may still be used; it will override
+ the value found in the file.
+ </p>
+ <p>
+ If this option is not used and the maximum TTL cannot be retrieved
+ from a zone file, a warning is generated and a default value of
+ 1 week is used.
+ </p>
+ </dd>
+<dt><span class="term">-d <em class="replaceable"><code>DNSKEY TTL</code></em></span></dt>
+<dd>
+ <p>
+ Sets the value to be used as the DNSKEY TTL for the zone or
+ zones being analyzed when determining whether there is a
+ possibility of validation failure. When a key is rolled (that
+ is, replaced with a new key), there must be enough time for the
+ old DNSKEY RRset to have expired from resolver caches before
+ the new key is activated and begins generating signatures. If
+ that condition does not apply, a warning will be generated.
+ </p>
+ <p>
+ The length of the TTL can be set in seconds, or in larger units
+ of time by adding a suffix: 'mi' for minutes, 'h' for hours,
+ 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
+ </p>
+ <p>
+ This option is not necessary if <code class="option">-f</code> has
+ been used to specify a zone file from which the TTL
+ of the DNSKEY RRset can be read, or if a default key TTL was
+ set using ith the <code class="option">-L</code> to
+ <span class="command"><strong>dnssec-keygen</strong></span>. If either of those is true,
+ this option may still be used; it will override the values
+ found in the zone file or the key file.
+ </p>
+ <p>
+ If this option is not used and the key TTL cannot be retrieved
+ from the zone file or the key file, then a warning is generated
+ and a default value of 1 day is used.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>resign interval</code></em></span></dt>
+<dd>
+ <p>
+ Sets the value to be used as the resign interval for the zone
+ or zones being analyzed when determining whether there is a
+ possibility of validation failure. This value defaults to
+ 22.5 days, which is also the default in
+ <span class="command"><strong>named</strong></span>. However, if it has been changed
+ by the <code class="option">sig-validity-interval</code> option in
+ <code class="filename">named.conf</code>, then it should also be
+ changed here.
+ </p>
+ <p>
+ The length of the interval can be set in seconds, or in larger
+ units of time by adding a suffix: 'mi' for minutes, 'h' for hours,
+ 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
+ </p>
+ </dd>
+<dt><span class="term">-k</span></dt>
+<dd>
+ <p>
+ Only check KSK coverage; ignore ZSK events. Cannot be
+ used with <code class="option">-z</code>.
+ </p>
+ </dd>
+<dt><span class="term">-z</span></dt>
+<dd>
+ <p>
+ Only check ZSK coverage; ignore KSK events. Cannot be
+ used with <code class="option">-k</code>.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>compilezone path</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a path to a <span class="command"><strong>named-compilezone</strong></span> binary.
+ Used for testing.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-checkds</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-dsfromkey</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-signzone</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/python/dnssec-coverage.py.in b/bin/python/dnssec-coverage.py.in
new file mode 100644
index 0000000..8518dc3
--- /dev/null
+++ b/bin/python/dnssec-coverage.py.in
@@ -0,0 +1,27 @@
+#!@PYTHON@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import os
+import sys
+
+sys.path.insert(0, os.path.dirname(sys.argv[0]))
+if os.name != 'nt':
+ if '@PYTHON_INSTALL_DIR@': # value of --with-python-install-dir
+ sys.path.insert(1, '@PYTHON_INSTALL_DIR@')
+ else:
+ sys.path.insert(1, os.path.join('@prefix@', 'lib',
+ 'python' + sys.version[:3], 'site-packages'))
+
+import isc.coverage
+
+if __name__ == "__main__":
+ isc.coverage.main()
diff --git a/bin/python/dnssec-keymgr.8 b/bin/python/dnssec-keymgr.8
new file mode 100644
index 0000000..a538fda
--- /dev/null
+++ b/bin/python/dnssec-keymgr.8
@@ -0,0 +1,301 @@
+.\" Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnssec-keymgr
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2016-06-03
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSSEC\-KEYMGR" "8" "2016\-06\-03" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnssec-keymgr \- Ensures correct DNSKEY coverage for a zone based on a defined policy
+.SH "SYNOPSIS"
+.HP \w'\fBdnssec\-keymgr\fR\ 'u
+\fBdnssec\-keymgr\fR [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-c\ \fR\fB\fIfile\fR\fR] [\fB\-f\fR] [\fB\-k\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-z\fR] [\fB\-g\ \fR\fB\fIpath\fR\fR] [\fB\-r\ \fR\fB\fIpath\fR\fR] [\fB\-s\ \fR\fB\fIpath\fR\fR] [zone...]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-keymgr\fR
+is a high level Python wrapper to facilitate the key rollover process for zones handled by BIND\&. It uses the BIND commands for manipulating DNSSEC key metadata:
+\fBdnssec\-keygen\fR
+and
+\fBdnssec\-settime\fR\&.
+.PP
+DNSSEC policy can be read from a configuration file (default
+/etc/dnssec\-policy\&.conf), from which the key parameters, publication and rollover schedule, and desired coverage duration for any given zone can be determined\&. This file may be used to define individual DNSSEC policies on a per\-zone basis, or to set a default policy used for all zones\&.
+.PP
+When
+\fBdnssec\-keymgr\fR
+runs, it examines the DNSSEC keys for one or more zones, comparing their timing metadata against the policies for those zones\&. If key settings do not conform to the DNSSEC policy (for example, because the policy has been changed), they are automatically corrected\&.
+.PP
+A zone policy can specify a duration for which we want to ensure the key correctness (\fBcoverage\fR)\&. It can also specify a rollover period (\fBroll\-period\fR)\&. If policy indicates that a key should roll over before the coverage period ends, then a successor key will automatically be created and added to the end of the key series\&.
+.PP
+If zones are specified on the command line,
+\fBdnssec\-keymgr\fR
+will examine only those zones\&. If a specified zone does not already have keys in place, then keys will be generated for it according to policy\&.
+.PP
+If zones are
+\fInot\fR
+specified on the command line, then
+\fBdnssec\-keymgr\fR
+will search the key directory (either the current working directory or the directory set by the
+\fB\-K\fR
+option), and check the keys for all the zones represented in the directory\&.
+.PP
+It is expected that this tool will be run automatically and unattended (for example, by
+\fBcron\fR)\&.
+.SH "OPTIONS"
+.PP
+\-c \fIfile\fR
+.RS 4
+If
+\fB\-c\fR
+is specified, then the DNSSEC policy is read from
+\fBfile\fR\&. (If not specified, then the policy is read from
+/etc/dnssec\-policy\&.conf; if that file doesn\*(Aqt exist, a built\-in global default policy is used\&.)
+.RE
+.PP
+\-f
+.RS 4
+Force: allow updating of key events even if they are already in the past\&. This is not recommended for use with zones in which keys have already been published\&. However, if a set of keys has been generated all of which have publication and activation dates in the past, but the keys have not been published in a zone as yet, then this option can be used to clean them up and turn them into a proper series of keys with appropriate rollover intervals\&.
+.RE
+.PP
+\-g \fIkeygen\-path\fR
+.RS 4
+Specifies a path to a
+\fBdnssec\-keygen\fR
+binary\&. Used for testing\&. See also the
+\fB\-s\fR
+option\&.
+.RE
+.PP
+\-h
+.RS 4
+Print the
+\fBdnssec\-keymgr\fR
+help summary and exit\&.
+.RE
+.PP
+\-K \fIdirectory\fR
+.RS 4
+Sets the directory in which keys can be found\&. Defaults to the current working directory\&.
+.RE
+.PP
+\-k
+.RS 4
+Only apply policies to KSK keys\&. See also the
+\fB\-z\fR
+option\&.
+.RE
+.PP
+\-q
+.RS 4
+Quiet: suppress printing of
+\fBdnssec\-keygen\fR
+and
+\fBdnssec\-settime\fR\&.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies a path to a file containing random data\&. This is passed to the
+\fBdnssec\-keygen\fR
+binary using its
+\fB\-r\fR
+option\&.
+.RE
+.PP
+\-s \fIsettime\-path\fR
+.RS 4
+Specifies a path to a
+\fBdnssec\-settime\fR
+binary\&. Used for testing\&. See also the
+\fB\-g\fR
+option\&.
+.RE
+.PP
+\-v
+.RS 4
+Print the
+\fBdnssec\-keymgr\fR
+version and exit\&.
+.RE
+.PP
+\-z
+.RS 4
+Only apply policies to ZSK keys\&. See also the
+\fB\-k\fR
+option\&.
+.RE
+.SH "POLICY CONFIGURATION"
+.PP
+The
+dnssec\-policy\&.conf
+file can specify three kinds of policies:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fIPolicy classes\fR
+(\fBpolicy \fR\fB\fIname\fR\fR\fB { \&.\&.\&. };\fR) can be inherited by zone policies or other policy classes; these can be used to create sets of different security profiles\&. For example, a policy class
+\fBnormal\fR
+might specify 1024\-bit key sizes, but a class
+\fBextra\fR
+might specify 2048 bits instead;
+\fBextra\fR
+would be used for zones that had unusually high security needs\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Algorithm policies: (\fBalgorithm\-policy \fR\fB\fIalgorithm\fR\fR\fB { \&.\&.\&. };\fR
+) override default per\-algorithm settings\&. For example, by default, RSASHA256 keys use 2048\-bit key sizes for both KSK and ZSK\&. This can be modified using
+\fBalgorithm\-policy\fR, and the new key sizes would then be used for any key of type RSASHA256\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Zone policies: (\fBzone \fR\fB\fIname\fR\fR\fB { \&.\&.\&. };\fR
+) set policy for a single zone by name\&. A zone policy can inherit a policy class by including a
+\fBpolicy\fR
+option\&. Zone names beginning with digits (i\&.e\&., 0\-9) must be quoted\&.
+.RE
+.PP
+Options that can be specified in policies:
+.PP
+\fBalgorithm\fR
+.RS 4
+The key algorithm\&. If no policy is defined, the default is RSASHA256\&.
+.RE
+.PP
+\fBcoverage\fR
+.RS 4
+The length of time to ensure that keys will be correct; no action will be taken to create new keys to be activated after this time\&. This can be represented as a number of seconds, or as a duration using human\-readable units (examples: "1y" or "6 months")\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. If no policy is configured, the default is six months\&.
+.RE
+.PP
+\fBdirectory\fR
+.RS 4
+Specifies the directory in which keys should be stored\&.
+.RE
+.PP
+\fBkey\-size\fR
+.RS 4
+Specifies the number of bits to use in creating keys\&. Takes two arguments: keytype (eihter "zsk" or "ksk") and size\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. If no policy is configured, the default is 1024 bits for DSA keys and 2048 for RSA\&.
+.RE
+.PP
+\fBkeyttl\fR
+.RS 4
+The key TTL\&. If no policy is defined, the default is one hour\&.
+.RE
+.PP
+\fBpost\-publish\fR
+.RS 4
+How long after inactivation a key should be deleted from the zone\&. Note: If
+\fBroll\-period\fR
+is not set, this value is ignored\&. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. The default is one month\&.
+.RE
+.PP
+\fBpre\-publish\fR
+.RS 4
+How long before activation a key should be published\&. Note: If
+\fBroll\-period\fR
+is not set, this value is ignored\&. Takes two arguments: keytype (either "zsk" or "ksk") and a duration\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. The default is one month\&.
+.RE
+.PP
+\fBroll\-period\fR
+.RS 4
+How frequently keys should be rolled over\&. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. If no policy is configured, the default is one year for ZSK\*(Aqs\&. KSK\*(Aqs do not roll over by default\&.
+.RE
+.PP
+\fBstandby\fR
+.RS 4
+Not yet implemented\&.
+.RE
+.SH "REMAINING WORK"
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Enable scheduling of KSK rollovers using the
+\fB\-P sync\fR
+and
+\fB\-D sync\fR
+options to
+\fBdnssec\-keygen\fR
+and
+\fBdnssec\-settime\fR\&. Check the parent zone (as in
+\fBdnssec\-checkds\fR) to determine when it\*(Aqs safe for the key to roll\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Allow configuration of standby keys and use of the REVOKE bit, for keys that use RFC 5011 semantics\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec-coverage\fR(8),
+\fBdnssec-keygen\fR(8),
+\fBdnssec-settime\fR(8),
+\fBdnssec-checkds\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2016-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/python/dnssec-keymgr.docbook b/bin/python/dnssec-keymgr.docbook
new file mode 100644
index 0000000..c94ca06
--- /dev/null
+++ b/bin/python/dnssec-keymgr.docbook
@@ -0,0 +1,417 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-keymgr">
+ <info>
+ <date>2016-06-03</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keymgr</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keymgr</application></refname>
+ <refpurpose>Ensures correct DNSKEY coverage for a zone based on a defined policy</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnssec-keymgr</command>
+ <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-z</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-g <replaceable class="parameter">path</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r <replaceable class="parameter">path</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">path</replaceable></option></arg>
+ <arg choice="opt" rep="repeat">zone</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+ <para>
+ <command>dnssec-keymgr</command> is a high level Python wrapper
+ to facilitate the key rollover process for zones handled by
+ BIND. It uses the BIND commands for manipulating DNSSEC key
+ metadata: <command>dnssec-keygen</command> and
+ <command>dnssec-settime</command>.
+ </para>
+ <para>
+ DNSSEC policy can be read from a configuration file (default
+ <filename>/etc/dnssec-policy.conf</filename>), from which the key
+ parameters, publication and rollover schedule, and desired
+ coverage duration for any given zone can be determined. This
+ file may be used to define individual DNSSEC policies on a
+ per-zone basis, or to set a default policy used for all zones.
+ </para>
+ <para>
+ When <command>dnssec-keymgr</command> runs, it examines the DNSSEC
+ keys for one or more zones, comparing their timing metadata against
+ the policies for those zones. If key settings do not conform to the
+ DNSSEC policy (for example, because the policy has been changed),
+ they are automatically corrected.
+ </para>
+ <para>
+ A zone policy can specify a duration for which we want to
+ ensure the key correctness (<option>coverage</option>). It can
+ also specify a rollover period (<option>roll-period</option>).
+ If policy indicates that a key should roll over before the
+ coverage period ends, then a successor key will automatically be
+ created and added to the end of the key series.
+ </para>
+ <para>
+ If zones are specified on the command line,
+ <command>dnssec-keymgr</command> will examine only those zones.
+ If a specified zone does not already have keys in place, then
+ keys will be generated for it according to policy.
+ </para>
+ <para>
+ If zones are <emphasis>not</emphasis> specified on the command
+ line, then <command>dnssec-keymgr</command> will search the
+ key directory (either the current working directory or the directory
+ set by the <option>-K</option> option), and check the keys for
+ all the zones represented in the directory.
+ </para>
+ <para>
+ It is expected that this tool will be run automatically and
+ unattended (for example, by <command>cron</command>).
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+ <variablelist>
+ <varlistentry>
+ <term>-c <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ If <option>-c</option> is specified, then the DNSSEC
+ policy is read from <option>file</option>. (If not
+ specified, then the policy is read from
+ <filename>/etc/dnssec-policy.conf</filename>; if that file
+ doesn't exist, a built-in global default policy is used.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Force: allow updating of key events even if they are
+ already in the past. This is not recommended for use with
+ zones in which keys have already been published. However,
+ if a set of keys has been generated all of which have
+ publication and activation dates in the past, but the
+ keys have not been published in a zone as yet, then this
+ option can be used to clean them up and turn them into a
+ proper series of keys with appropriate rollover intervals.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g <replaceable class="parameter">keygen-path</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a path to a <command>dnssec-keygen</command> binary.
+ Used for testing.
+ See also the <option>-s</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Print the <command>dnssec-keymgr</command> help summary
+ and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which keys can be found. Defaults to the
+ current working directory.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Only apply policies to KSK keys.
+ See also the <option>-z</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ Quiet: suppress printing of <command>dnssec-keygen</command>
+ and <command>dnssec-settime</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a path to a file containing random data.
+ This is passed to the <command>dnssec-keygen</command> binary
+ using its <option>-r</option> option.
+<!-- TODO: what to do about "-r keyboard"? -->
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">settime-path</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a path to a <command>dnssec-settime</command> binary.
+ Used for testing.
+ See also the <option>-g</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the <command>dnssec-keymgr</command> version and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Only apply policies to ZSK keys.
+ See also the <option>-k</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>POLICY CONFIGURATION</title></info>
+ <para>
+ The <filename>dnssec-policy.conf</filename> file can specify three kinds
+ of policies:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Policy classes</emphasis>
+ (<option>policy <replaceable>name</replaceable> { ... };</option>)
+ can be inherited by zone policies or other policy classes; these
+ can be used to create sets of different security profiles. For
+ example, a policy class <userinput>normal</userinput> might specify
+ 1024-bit key sizes, but a class <userinput>extra</userinput> might
+ specify 2048 bits instead; <userinput>extra</userinput> would be
+ used for zones that had unusually high security needs.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Algorithm policies:
+ (<option>algorithm-policy <replaceable>algorithm</replaceable> { ... };</option> )
+ override default per-algorithm settings. For example, by default,
+ RSASHA256 keys use 2048-bit key sizes for both KSK and ZSK. This
+ can be modified using <command>algorithm-policy</command>, and the
+ new key sizes would then be used for any key of type RSASHA256.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Zone policies:
+ (<option>zone <replaceable>name</replaceable> { ... };</option> )
+ set policy for a single zone by name. A zone policy can inherit
+ a policy class by including a <option>policy</option> option.
+ Zone names beginning with digits (i.e., 0-9) must be quoted.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Options that can be specified in policies:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><command>algorithm</command></term>
+ <listitem>
+ <para>
+ The key algorithm. If no policy is defined, the default is
+ RSASHA256.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>coverage</command></term>
+ <listitem>
+ <para>
+ The length of time to ensure that keys will be correct; no action
+ will be taken to create new keys to be activated after this time.
+ This can be represented as a number of seconds, or as a duration using
+ human-readable units (examples: "1y" or "6 months").
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies.
+ If no policy is configured, the default is six months.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>directory</command></term>
+ <listitem>
+ <para>
+ Specifies the directory in which keys should be stored.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>key-size</command></term>
+ <listitem>
+ <para>
+ Specifies the number of bits to use in creating keys.
+ Takes two arguments: keytype (eihter "zsk" or "ksk") and size.
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies. If no policy is
+ configured, the default is 1024 bits for DSA keys and 2048 for
+ RSA.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>keyttl</command></term>
+ <listitem>
+ <para>
+ The key TTL. If no policy is defined, the default is one hour.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>post-publish</command></term>
+ <listitem>
+ <para>
+ How long after inactivation a key should be deleted from the zone.
+ Note: If <option>roll-period</option> is not set, this value is
+ ignored. Takes two arguments: keytype (eihter "zsk" or "ksk") and a
+ duration. A default value for this option can be set in algorithm
+ policies as well as in policy classes or zone policies. The default
+ is one month.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>pre-publish</command></term>
+ <listitem>
+ <para>
+ How long before activation a key should be published. Note: If
+ <option>roll-period</option> is not set, this value is ignored.
+ Takes two arguments: keytype (either "zsk" or "ksk") and a duration.
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies. The default is
+ one month.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>roll-period</command></term>
+ <listitem>
+ <para>
+ How frequently keys should be rolled over.
+ Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration.
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies. If no policy is
+ configured, the default is one year for ZSK's. KSK's do not
+ roll over by default.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>standby</command></term>
+ <listitem>
+ <para>
+ Not yet implemented.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>REMAINING WORK</title></info>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Enable scheduling of KSK rollovers using the <option>-P sync</option>
+ and <option>-D sync</option> options to
+ <command>dnssec-keygen</command> and
+ <command>dnssec-settime</command>. Check the parent zone
+ (as in <command>dnssec-checkds</command>) to determine when it's
+ safe for the key to roll.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Allow configuration of standby keys and use of the REVOKE bit,
+ for keys that use RFC 5011 semantics.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+ <para>
+ <citerefentry>
+ <refentrytitle>dnssec-coverage</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-settime</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-checkds</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/python/dnssec-keymgr.html b/bin/python/dnssec-keymgr.html
new file mode 100644
index 0000000..7ec46d5
--- /dev/null
+++ b/bin/python/dnssec-keymgr.html
@@ -0,0 +1,364 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keymgr</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnssec-keymgr"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnssec-keymgr</span>
+ &#8212; Ensures correct DNSKEY coverage for a zone based on a defined policy
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnssec-keymgr</code>
+ [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>file</code></em></code>]
+ [<code class="option">-f</code>]
+ [<code class="option">-k</code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-z</code>]
+ [<code class="option">-g <em class="replaceable"><code>path</code></em></code>]
+ [<code class="option">-r <em class="replaceable"><code>path</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>path</code></em></code>]
+ [zone...]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+ <p>
+ <span class="command"><strong>dnssec-keymgr</strong></span> is a high level Python wrapper
+ to facilitate the key rollover process for zones handled by
+ BIND. It uses the BIND commands for manipulating DNSSEC key
+ metadata: <span class="command"><strong>dnssec-keygen</strong></span> and
+ <span class="command"><strong>dnssec-settime</strong></span>.
+ </p>
+ <p>
+ DNSSEC policy can be read from a configuration file (default
+ <code class="filename">/etc/dnssec-policy.conf</code>), from which the key
+ parameters, publication and rollover schedule, and desired
+ coverage duration for any given zone can be determined. This
+ file may be used to define individual DNSSEC policies on a
+ per-zone basis, or to set a default policy used for all zones.
+ </p>
+ <p>
+ When <span class="command"><strong>dnssec-keymgr</strong></span> runs, it examines the DNSSEC
+ keys for one or more zones, comparing their timing metadata against
+ the policies for those zones. If key settings do not conform to the
+ DNSSEC policy (for example, because the policy has been changed),
+ they are automatically corrected.
+ </p>
+ <p>
+ A zone policy can specify a duration for which we want to
+ ensure the key correctness (<code class="option">coverage</code>). It can
+ also specify a rollover period (<code class="option">roll-period</code>).
+ If policy indicates that a key should roll over before the
+ coverage period ends, then a successor key will automatically be
+ created and added to the end of the key series.
+ </p>
+ <p>
+ If zones are specified on the command line,
+ <span class="command"><strong>dnssec-keymgr</strong></span> will examine only those zones.
+ If a specified zone does not already have keys in place, then
+ keys will be generated for it according to policy.
+ </p>
+ <p>
+ If zones are <span class="emphasis"><em>not</em></span> specified on the command
+ line, then <span class="command"><strong>dnssec-keymgr</strong></span> will search the
+ key directory (either the current working directory or the directory
+ set by the <code class="option">-K</code> option), and check the keys for
+ all the zones represented in the directory.
+ </p>
+ <p>
+ It is expected that this tool will be run automatically and
+ unattended (for example, by <span class="command"><strong>cron</strong></span>).
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-c <em class="replaceable"><code>file</code></em></span></dt>
+<dd>
+ <p>
+ If <code class="option">-c</code> is specified, then the DNSSEC
+ policy is read from <code class="option">file</code>. (If not
+ specified, then the policy is read from
+ <code class="filename">/etc/dnssec-policy.conf</code>; if that file
+ doesn't exist, a built-in global default policy is used.)
+ </p>
+ </dd>
+<dt><span class="term">-f</span></dt>
+<dd>
+ <p>
+ Force: allow updating of key events even if they are
+ already in the past. This is not recommended for use with
+ zones in which keys have already been published. However,
+ if a set of keys has been generated all of which have
+ publication and activation dates in the past, but the
+ keys have not been published in a zone as yet, then this
+ option can be used to clean them up and turn them into a
+ proper series of keys with appropriate rollover intervals.
+ </p>
+ </dd>
+<dt><span class="term">-g <em class="replaceable"><code>keygen-path</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a path to a <span class="command"><strong>dnssec-keygen</strong></span> binary.
+ Used for testing.
+ See also the <code class="option">-s</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-h</span></dt>
+<dd>
+ <p>
+ Print the <span class="command"><strong>dnssec-keymgr</strong></span> help summary
+ and exit.
+ </p>
+ </dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+ <p>
+ Sets the directory in which keys can be found. Defaults to the
+ current working directory.
+ </p>
+ </dd>
+<dt><span class="term">-k</span></dt>
+<dd>
+ <p>
+ Only apply policies to KSK keys.
+ See also the <code class="option">-z</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-q</span></dt>
+<dd>
+ <p>
+ Quiet: suppress printing of <span class="command"><strong>dnssec-keygen</strong></span>
+ and <span class="command"><strong>dnssec-settime</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a path to a file containing random data.
+ This is passed to the <span class="command"><strong>dnssec-keygen</strong></span> binary
+ using its <code class="option">-r</code> option.
+
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>settime-path</code></em></span></dt>
+<dd>
+ <p>
+ Specifies a path to a <span class="command"><strong>dnssec-settime</strong></span> binary.
+ Used for testing.
+ See also the <code class="option">-g</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Print the <span class="command"><strong>dnssec-keymgr</strong></span> version and exit.
+ </p>
+ </dd>
+<dt><span class="term">-z</span></dt>
+<dd>
+ <p>
+ Only apply policies to ZSK keys.
+ See also the <code class="option">-k</code> option.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>POLICY CONFIGURATION</h2>
+ <p>
+ The <code class="filename">dnssec-policy.conf</code> file can specify three kinds
+ of policies:
+ </p>
+ <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ <p>
+ <span class="emphasis"><em>Policy classes</em></span>
+ (<code class="option">policy <em class="replaceable"><code>name</code></em> { ... };</code>)
+ can be inherited by zone policies or other policy classes; these
+ can be used to create sets of different security profiles. For
+ example, a policy class <strong class="userinput"><code>normal</code></strong> might specify
+ 1024-bit key sizes, but a class <strong class="userinput"><code>extra</code></strong> might
+ specify 2048 bits instead; <strong class="userinput"><code>extra</code></strong> would be
+ used for zones that had unusually high security needs.
+ </p>
+ </li>
+<li class="listitem">
+ <p>
+ Algorithm policies:
+ (<code class="option">algorithm-policy <em class="replaceable"><code>algorithm</code></em> { ... };</code> )
+ override default per-algorithm settings. For example, by default,
+ RSASHA256 keys use 2048-bit key sizes for both KSK and ZSK. This
+ can be modified using <span class="command"><strong>algorithm-policy</strong></span>, and the
+ new key sizes would then be used for any key of type RSASHA256.
+ </p>
+ </li>
+<li class="listitem">
+ <p>
+ Zone policies:
+ (<code class="option">zone <em class="replaceable"><code>name</code></em> { ... };</code> )
+ set policy for a single zone by name. A zone policy can inherit
+ a policy class by including a <code class="option">policy</code> option.
+ Zone names beginning with digits (i.e., 0-9) must be quoted.
+ </p>
+ </li>
+</ul></div>
+ <p>
+ Options that can be specified in policies:
+ </p>
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><span class="command"><strong>algorithm</strong></span></span></dt>
+<dd>
+ <p>
+ The key algorithm. If no policy is defined, the default is
+ RSASHA256.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>coverage</strong></span></span></dt>
+<dd>
+ <p>
+ The length of time to ensure that keys will be correct; no action
+ will be taken to create new keys to be activated after this time.
+ This can be represented as a number of seconds, or as a duration using
+ human-readable units (examples: "1y" or "6 months").
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies.
+ If no policy is configured, the default is six months.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>directory</strong></span></span></dt>
+<dd>
+ <p>
+ Specifies the directory in which keys should be stored.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>key-size</strong></span></span></dt>
+<dd>
+ <p>
+ Specifies the number of bits to use in creating keys.
+ Takes two arguments: keytype (eihter "zsk" or "ksk") and size.
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies. If no policy is
+ configured, the default is 1024 bits for DSA keys and 2048 for
+ RSA.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>keyttl</strong></span></span></dt>
+<dd>
+ <p>
+ The key TTL. If no policy is defined, the default is one hour.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>post-publish</strong></span></span></dt>
+<dd>
+ <p>
+ How long after inactivation a key should be deleted from the zone.
+ Note: If <code class="option">roll-period</code> is not set, this value is
+ ignored. Takes two arguments: keytype (eihter "zsk" or "ksk") and a
+ duration. A default value for this option can be set in algorithm
+ policies as well as in policy classes or zone policies. The default
+ is one month.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>pre-publish</strong></span></span></dt>
+<dd>
+ <p>
+ How long before activation a key should be published. Note: If
+ <code class="option">roll-period</code> is not set, this value is ignored.
+ Takes two arguments: keytype (either "zsk" or "ksk") and a duration.
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies. The default is
+ one month.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>roll-period</strong></span></span></dt>
+<dd>
+ <p>
+ How frequently keys should be rolled over.
+ Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration.
+ A default value for this option can be set in algorithm policies
+ as well as in policy classes or zone policies. If no policy is
+ configured, the default is one year for ZSK's. KSK's do not
+ roll over by default.
+ </p>
+ </dd>
+<dt><span class="term"><span class="command"><strong>standby</strong></span></span></dt>
+<dd>
+ <p>
+ Not yet implemented.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>REMAINING WORK</h2>
+ <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ <p>
+ Enable scheduling of KSK rollovers using the <code class="option">-P sync</code>
+ and <code class="option">-D sync</code> options to
+ <span class="command"><strong>dnssec-keygen</strong></span> and
+ <span class="command"><strong>dnssec-settime</strong></span>. Check the parent zone
+ (as in <span class="command"><strong>dnssec-checkds</strong></span>) to determine when it's
+ safe for the key to roll.
+ </p>
+ </li>
+<li class="listitem">
+ <p>
+ Allow configuration of standby keys and use of the REVOKE bit,
+ for keys that use RFC 5011 semantics.
+ </p>
+ </li>
+</ul></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-coverage</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-settime</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-checkds</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/python/dnssec-keymgr.py.in b/bin/python/dnssec-keymgr.py.in
new file mode 100644
index 0000000..c8453a7
--- /dev/null
+++ b/bin/python/dnssec-keymgr.py.in
@@ -0,0 +1,27 @@
+#!@PYTHON@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import os
+import sys
+
+sys.path.insert(0, os.path.dirname(sys.argv[0]))
+if os.name != 'nt':
+ if '@PYTHON_INSTALL_DIR@': # value of --with-python-install-dir
+ sys.path.insert(1, '@PYTHON_INSTALL_DIR@')
+ else:
+ sys.path.insert(1, os.path.join('@prefix@', 'lib',
+ 'python' + sys.version[:3], 'site-packages'))
+
+import isc.keymgr
+
+if __name__ == "__main__":
+ isc.keymgr.main()
diff --git a/bin/python/isc/Makefile.in b/bin/python/isc/Makefile.in
new file mode 100644
index 0000000..ec17b6b
--- /dev/null
+++ b/bin/python/isc/Makefile.in
@@ -0,0 +1,43 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+SUBDIRS = tests
+
+PYTHON = @PYTHON@
+
+PYSRCS = __init__.py checkds.py coverage.py dnskey.py eventlist.py \
+ keydict.py keyevent.py keymgr.py keyseries.py keyzone.py \
+ policy.py rndc.py utils.py
+
+TARGETS = parsetab.py
+
+@BIND9_MAKE_RULES@
+
+.SUFFIXES: .py .pyc
+.py.pyc:
+ $(PYTHON) -m compileall .
+
+parsetab.py: policy.py
+ $(PYTHON) policy.py parse /dev/null > /dev/null
+ PYTHONPATH=${srcdir} $(PYTHON) -m parsetab
+
+check test: subdirs
+
+clean distclean::
+ rm -f *.pyc parser.out parsetab.py
+ rm -rf __pycache__ build
+
+distclean::
+ rm -rf ${PYSRCS}
diff --git a/bin/python/isc/__init__.py.in b/bin/python/isc/__init__.py.in
new file mode 100644
index 0000000..916333c
--- /dev/null
+++ b/bin/python/isc/__init__.py.in
@@ -0,0 +1,24 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+__all__ = ['checkds', 'coverage', 'keymgr', 'dnskey', 'eventlist',
+ 'keydict', 'keyevent', 'keyseries', 'keyzone', 'policy',
+ 'parsetab', 'rndc', 'utils']
+
+from isc.dnskey import *
+from isc.eventlist import *
+from isc.keydict import *
+from isc.keyevent import *
+from isc.keyseries import *
+from isc.keyzone import *
+from isc.policy import *
+from isc.rndc import *
+from isc.utils import *
diff --git a/bin/python/isc/checkds.py.in b/bin/python/isc/checkds.py.in
new file mode 100644
index 0000000..42fbfcd
--- /dev/null
+++ b/bin/python/isc/checkds.py.in
@@ -0,0 +1,185 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import argparse
+import os
+import sys
+from subprocess import Popen, PIPE
+
+from isc.utils import prefix,version
+
+prog = 'dnssec-checkds'
+
+
+############################################################################
+# SECRR class:
+# Class for DS/DLV resource record
+############################################################################
+class SECRR:
+ hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST', 4: 'SHA-384'}
+ rrname = ''
+ rrclass = 'IN'
+ keyid = None
+ keyalg = None
+ hashalg = None
+ digest = ''
+ ttl = 0
+
+ def __init__(self, rrtext, dlvname = None):
+ if not rrtext:
+ raise Exception
+
+ fields = rrtext.decode('ascii').split()
+ if len(fields) < 7:
+ raise Exception
+
+ if dlvname:
+ self.rrtype = "DLV"
+ self.dlvname = dlvname.lower()
+ parent = fields[0].lower().strip('.').split('.')
+ parent.reverse()
+ dlv = dlvname.split('.')
+ dlv.reverse()
+ while len(dlv) != 0 and len(parent) != 0 and parent[0] == dlv[0]:
+ parent = parent[1:]
+ dlv = dlv[1:]
+ if dlv:
+ raise Exception
+ parent.reverse()
+ self.parent = '.'.join(parent)
+ self.rrname = self.parent + '.' + self.dlvname + '.'
+ else:
+ self.rrtype = "DS"
+ self.rrname = fields[0].lower()
+
+ fields = fields[1:]
+ if fields[0].upper() in ['IN', 'CH', 'HS']:
+ self.rrclass = fields[0].upper()
+ fields = fields[1:]
+ else:
+ self.ttl = int(fields[0])
+ self.rrclass = fields[1].upper()
+ fields = fields[2:]
+
+ if fields[0].upper() != self.rrtype:
+ raise Exception('%s does not match %s' %
+ (fields[0].upper(), self.rrtype))
+
+ self.keyid, self.keyalg, self.hashalg = map(int, fields[1:4])
+ self.digest = ''.join(fields[4:]).upper()
+
+ def __repr__(self):
+ return '%s %s %s %d %d %d %s' % \
+ (self.rrname, self.rrclass, self.rrtype,
+ self.keyid, self.keyalg, self.hashalg, self.digest)
+
+ def __eq__(self, other):
+ return self.__repr__() == other.__repr__()
+
+
+############################################################################
+# check:
+# Fetch DS/DLV RRset for the given zone from the DNS; fetch DNSKEY
+# RRset from the masterfile if specified, or from DNS if not.
+# Generate a set of expected DS/DLV records from the DNSKEY RRset,
+# and report on congruency.
+############################################################################
+def check(zone, args, masterfile=None, lookaside=None):
+ rrlist = []
+ cmd = [args.dig, "+noall", "+answer", "-t", "dlv" if lookaside else "ds",
+ "-q", zone + "." + lookaside if lookaside else zone]
+ fp, _ = Popen(cmd, stdout=PIPE).communicate()
+
+ for line in fp.splitlines():
+ rrlist.append(SECRR(line, lookaside))
+ rrlist = sorted(rrlist, key=lambda rr: (rr.keyid, rr.keyalg, rr.hashalg))
+
+ klist = []
+
+ if masterfile:
+ cmd = [args.dsfromkey, "-f", masterfile]
+ if lookaside:
+ cmd += ["-l", lookaside]
+ cmd.append(zone)
+ fp, _ = Popen(cmd, stdout=PIPE).communicate()
+ else:
+ intods, _ = Popen([args.dig, "+noall", "+answer", "-t", "dnskey",
+ "-q", zone], stdout=PIPE).communicate()
+ cmd = [args.dsfromkey, "-f", "-"]
+ if lookaside:
+ cmd += ["-l", lookaside]
+ cmd.append(zone)
+ fp, _ = Popen(cmd, stdin=PIPE, stdout=PIPE).communicate(intods)
+
+ for line in fp.splitlines():
+ klist.append(SECRR(line, lookaside))
+
+ if len(klist) < 1:
+ print("No DNSKEY records found in zone apex")
+ return False
+
+ found = False
+ for rr in klist:
+ if rr in rrlist:
+ print("%s for KSK %s/%03d/%05d (%s) found in parent" %
+ (rr.rrtype, rr.rrname.strip('.'), rr.keyalg,
+ rr.keyid, SECRR.hashalgs[rr.hashalg]))
+ found = True
+ else:
+ print("%s for KSK %s/%03d/%05d (%s) missing from parent" %
+ (rr.rrtype, rr.rrname.strip('.'), rr.keyalg,
+ rr.keyid, SECRR.hashalgs[rr.hashalg]))
+
+ if not found:
+ print("No %s records were found for any DNSKEY" % ("DLV" if lookaside else "DS"))
+
+ return found
+
+############################################################################
+# parse_args:
+# Read command line arguments, set global 'args' structure
+############################################################################
+def parse_args():
+ parser = argparse.ArgumentParser(description=prog + ': checks DS coverage')
+
+ bindir = 'bin'
+ sbindir = 'bin' if os.name == 'nt' else 'sbin'
+
+ parser.add_argument('zone', type=str, help='zone to check')
+ parser.add_argument('-f', '--file', dest='masterfile', type=str,
+ help='zone master file')
+ parser.add_argument('-l', '--lookaside', dest='lookaside', type=str,
+ help='DLV lookaside zone')
+ parser.add_argument('-d', '--dig', dest='dig',
+ default=os.path.join(prefix(bindir), 'dig'),
+ type=str, help='path to \'dig\'')
+ parser.add_argument('-D', '--dsfromkey', dest='dsfromkey',
+ default=os.path.join(prefix(sbindir),
+ 'dnssec-dsfromkey'),
+ type=str, help='path to \'dig\'')
+ parser.add_argument('-v', '--version', action='version',
+ version=version)
+ args = parser.parse_args()
+
+ args.zone = args.zone.strip('.')
+ if args.lookaside:
+ args.lookaside = args.lookaside.strip('.')
+
+ return args
+
+
+############################################################################
+# Main
+############################################################################
+def main():
+ args = parse_args()
+ found = check(args.zone, args, args.masterfile, args.lookaside)
+ exit(0 if found else 1)
diff --git a/bin/python/isc/coverage.py.in b/bin/python/isc/coverage.py.in
new file mode 100644
index 0000000..4e392a7
--- /dev/null
+++ b/bin/python/isc/coverage.py.in
@@ -0,0 +1,286 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from __future__ import print_function
+import os
+import sys
+import argparse
+import glob
+import re
+import time
+import calendar
+import pprint
+from collections import defaultdict
+
+prog = 'dnssec-coverage'
+
+from isc import dnskey, eventlist, keydict, keyevent, keyzone, utils
+
+############################################################################
+# print a fatal error and exit
+############################################################################
+def fatal(*args, **kwargs):
+ print(*args, **kwargs)
+ sys.exit(1)
+
+
+############################################################################
+# output:
+############################################################################
+_firstline = True
+def output(*args, **kwargs):
+ """output text, adding a vertical space this is *not* the first
+ first section being printed since a call to vreset()"""
+ global _firstline
+ if 'skip' in kwargs:
+ skip = kwargs['skip']
+ kwargs.pop('skip', None)
+ else:
+ skip = True
+ if _firstline:
+ _firstline = False
+ elif skip:
+ print('')
+ if args:
+ print(*args, **kwargs)
+
+
+def vreset():
+ """reset vertical spacing"""
+ global _firstline
+ _firstline = True
+
+
+############################################################################
+# parse_time
+############################################################################
+def parse_time(s):
+ """ convert a formatted time (e.g., 1y, 6mo, 15mi, etc) into seconds
+ :param s: String with some text representing a time interval
+ :return: Integer with the number of seconds in the time interval
+ """
+ s = s.strip()
+
+ # if s is an integer, we're done already
+ try:
+ return int(s)
+ except ValueError:
+ pass
+
+ # try to parse as a number with a suffix indicating unit of time
+ r = re.compile(r'([0-9][0-9]*)\s*([A-Za-z]*)')
+ m = r.match(s)
+ if not m:
+ raise ValueError("Cannot parse %s" % s)
+ n, unit = m.groups()
+ n = int(n)
+ unit = unit.lower()
+ if unit.startswith('y'):
+ return n * 31536000
+ elif unit.startswith('mo'):
+ return n * 2592000
+ elif unit.startswith('w'):
+ return n * 604800
+ elif unit.startswith('d'):
+ return n * 86400
+ elif unit.startswith('h'):
+ return n * 3600
+ elif unit.startswith('mi'):
+ return n * 60
+ elif unit.startswith('s'):
+ return n
+ else:
+ raise ValueError("Invalid suffix %s" % unit)
+
+
+############################################################################
+# set_path:
+############################################################################
+def set_path(command, default=None):
+ """ find the location of a specified command. if a default is supplied
+ and it works, we use it; otherwise we search PATH for a match.
+ :param command: string with a command to look for in the path
+ :param default: default location to use
+ :return: detected location for the desired command
+ """
+
+ fpath = default
+ if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK):
+ path = os.environ["PATH"]
+ if not path:
+ path = os.path.defpath
+ for directory in path.split(os.pathsep):
+ fpath = os.path.join(directory, command)
+ if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
+ break
+ fpath = None
+
+ return fpath
+
+
+############################################################################
+# parse_args:
+############################################################################
+def parse_args():
+ """Read command line arguments, set global 'args' structure"""
+ compilezone = set_path('named-compilezone',
+ os.path.join(utils.prefix('sbin'),
+ 'named-compilezone'))
+
+ parser = argparse.ArgumentParser(description=prog + ': checks future ' +
+ 'DNSKEY coverage for a zone')
+
+ parser.add_argument('zone', type=str, nargs='*', default=None,
+ help='zone(s) to check' +
+ '(default: all zones in the directory)')
+ parser.add_argument('-K', dest='path', default='.', type=str,
+ help='a directory containing keys to process',
+ metavar='dir')
+ parser.add_argument('-f', dest='filename', type=str,
+ help='zone master file', metavar='file')
+ parser.add_argument('-m', dest='maxttl', type=str,
+ help='the longest TTL in the zone(s)',
+ metavar='time')
+ parser.add_argument('-d', dest='keyttl', type=str,
+ help='the DNSKEY TTL', metavar='time')
+ parser.add_argument('-r', dest='resign', default='1944000',
+ type=str, help='the RRSIG refresh interval '
+ 'in seconds [default: 22.5 days]',
+ metavar='time')
+ parser.add_argument('-c', dest='compilezone',
+ default=compilezone, type=str,
+ help='path to \'named-compilezone\'',
+ metavar='path')
+ parser.add_argument('-l', dest='checklimit',
+ type=str, default='0',
+ help='Length of time to check for '
+ 'DNSSEC coverage [default: 0 (unlimited)]',
+ metavar='time')
+ parser.add_argument('-z', dest='no_ksk',
+ action='store_true', default=False,
+ help='Only check zone-signing keys (ZSKs)')
+ parser.add_argument('-k', dest='no_zsk',
+ action='store_true', default=False,
+ help='Only check key-signing keys (KSKs)')
+ parser.add_argument('-D', '--debug', dest='debug_mode',
+ action='store_true', default=False,
+ help='Turn on debugging output')
+ parser.add_argument('-v', '--version', action='version',
+ version=utils.version)
+
+ args = parser.parse_args()
+
+ if args.no_zsk and args.no_ksk:
+ fatal("ERROR: -z and -k cannot be used together.")
+ elif args.no_zsk or args.no_ksk:
+ args.keytype = "KSK" if args.no_zsk else "ZSK"
+ else:
+ args.keytype = None
+
+ if args.filename and len(args.zone) > 1:
+ fatal("ERROR: -f can only be used with one zone.")
+
+ # convert from time arguments to seconds
+ try:
+ if args.maxttl:
+ m = parse_time(args.maxttl)
+ args.maxttl = m
+ except ValueError:
+ pass
+
+ try:
+ if args.keyttl:
+ k = parse_time(args.keyttl)
+ args.keyttl = k
+ except ValueError:
+ pass
+
+ try:
+ if args.resign:
+ r = parse_time(args.resign)
+ args.resign = r
+ except ValueError:
+ pass
+
+ try:
+ if args.checklimit:
+ lim = args.checklimit
+ r = parse_time(args.checklimit)
+ if r == 0:
+ args.checklimit = None
+ else:
+ args.checklimit = time.time() + r
+ except ValueError:
+ pass
+
+ # if we've got the values we need from the command line, stop now
+ if args.maxttl and args.keyttl:
+ return args
+
+ # load keyttl and maxttl data from zonefile
+ if args.zone and args.filename:
+ try:
+ zone = keyzone(args.zone[0], args.filename, args.compilezone)
+ args.maxttl = args.maxttl or zone.maxttl
+ args.keyttl = args.maxttl or zone.keyttl
+ except Exception as e:
+ print("Unable to load zone data from %s: " % args.filename, e)
+
+ if not args.maxttl:
+ output("WARNING: Maximum TTL value was not specified. Using 1 week\n"
+ "\t (604800 seconds); re-run with the -m option to get more\n"
+ "\t accurate results.")
+ args.maxttl = 604800
+
+ return args
+
+############################################################################
+# Main
+############################################################################
+def main():
+ args = parse_args()
+
+ print("PHASE 1--Loading keys to check for internal timing problems")
+
+ try:
+ kd = keydict(path=args.path, zone=args.zone, keyttl=args.keyttl)
+ except Exception as e:
+ fatal('ERROR: Unable to build key dictionary: ' + str(e))
+
+ for key in kd:
+ key.check_prepub(output)
+ if key.sep:
+ key.check_postpub(output)
+ else:
+ key.check_postpub(output, args.maxttl + args.resign)
+
+ output("PHASE 2--Scanning future key events for coverage failures")
+ vreset()
+
+ try:
+ elist = eventlist(kd)
+ except Exception as e:
+ fatal('ERROR: Unable to build event list: ' + str(e))
+
+ errors = False
+ if not args.zone:
+ if not elist.coverage(None, args.keytype, args.checklimit, output):
+ errors = True
+ else:
+ for zone in args.zone:
+ try:
+ if not elist.coverage(zone, args.keytype,
+ args.checklimit, output):
+ errors = True
+ except:
+ output('ERROR: Coverage check failed for zone ' + zone)
+
+ sys.exit(1 if errors else 0)
diff --git a/bin/python/isc/dnskey.py.in b/bin/python/isc/dnskey.py.in
new file mode 100644
index 0000000..8c5a80f
--- /dev/null
+++ b/bin/python/isc/dnskey.py.in
@@ -0,0 +1,507 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import os
+import time
+import calendar
+from subprocess import Popen, PIPE
+
+########################################################################
+# Class dnskey
+########################################################################
+class TimePast(Exception):
+ def __init__(self, key, prop, value):
+ super(TimePast, self).__init__('%s time for key %s (%d) is already past'
+ % (prop, key, value))
+
+class dnskey:
+ """An individual DNSSEC key. Identified by path, name, algorithm, keyid.
+ Contains a dictionary of metadata events."""
+
+ _PROPS = ('Created', 'Publish', 'Activate', 'Inactive', 'Delete',
+ 'Revoke', 'DSPublish', 'SyncPublish', 'SyncDelete')
+ _OPTS = (None, '-P', '-A', '-I', '-D', '-R', None, '-Psync', '-Dsync')
+
+ _ALGNAMES = (None, 'RSAMD5', 'DH', 'DSA', 'ECC', 'RSASHA1',
+ 'NSEC3DSA', 'NSEC3RSASHA1', 'RSASHA256', None,
+ 'RSASHA512', None, 'ECCGOST', 'ECDSAP256SHA256',
+ 'ECDSAP384SHA384', 'ED25519', 'ED448')
+
+ def __init__(self, key, directory=None, keyttl=None):
+ # this makes it possible to use algname as a class or instance method
+ if isinstance(key, tuple) and len(key) == 3:
+ self._dir = directory or '.'
+ (name, alg, keyid) = key
+ self.fromtuple(name, alg, keyid, keyttl)
+
+ self._dir = directory or os.path.dirname(key) or '.'
+ key = os.path.basename(key)
+ (name, alg, keyid) = key.split('+')
+ name = name[1:-1]
+ alg = int(alg)
+ keyid = int(keyid.split('.')[0])
+ self.fromtuple(name, alg, keyid, keyttl)
+
+ def fromtuple(self, name, alg, keyid, keyttl):
+ if name.endswith('.'):
+ fullname = name
+ name = name.rstrip('.')
+ else:
+ fullname = name + '.'
+
+ keystr = "K%s+%03d+%05d" % (fullname, alg, keyid)
+ key_file = self._dir + (self._dir and os.sep or '') + keystr + ".key"
+ private_file = (self._dir + (self._dir and os.sep or '') +
+ keystr + ".private")
+
+ self.keystr = keystr
+
+ self.name = name
+ self.alg = int(alg)
+ self.keyid = int(keyid)
+ self.fullname = fullname
+
+ kfp = open(key_file, "r")
+ for line in kfp:
+ if line[0] == ';':
+ continue
+ tokens = line.split()
+ if not tokens:
+ continue
+
+ if tokens[1].lower() in ('in', 'ch', 'hs'):
+ septoken = 3
+ self.ttl = keyttl
+ else:
+ septoken = 4
+ self.ttl = int(tokens[1]) if not keyttl else keyttl
+
+ if (int(tokens[septoken]) & 0x1) == 1:
+ self.sep = True
+ else:
+ self.sep = False
+ kfp.close()
+
+ pfp = open(private_file, "rU")
+
+ self.metadata = dict()
+ self._changed = dict()
+ self._delete = dict()
+ self._times = dict()
+ self._fmttime = dict()
+ self._timestamps = dict()
+ self._original = dict()
+ self._origttl = None
+
+ for line in pfp:
+ line = line.strip()
+ if not line or line[0] in ('!#'):
+ continue
+ punctuation = [line.find(c) for c in ':= '] + [len(line)]
+ found = min([pos for pos in punctuation if pos != -1])
+ name = line[:found].rstrip()
+ value = line[found:].lstrip(":= ").rstrip()
+ self.metadata[name] = value
+
+ for prop in dnskey._PROPS:
+ self._changed[prop] = False
+ if prop in self.metadata:
+ t = self.parsetime(self.metadata[prop])
+ self._times[prop] = t
+ self._fmttime[prop] = self.formattime(t)
+ self._timestamps[prop] = self.epochfromtime(t)
+ self._original[prop] = self._timestamps[prop]
+ else:
+ self._times[prop] = None
+ self._fmttime[prop] = None
+ self._timestamps[prop] = None
+ self._original[prop] = None
+
+ pfp.close()
+
+ def commit(self, settime_bin, **kwargs):
+ quiet = kwargs.get('quiet', False)
+ cmd = []
+ first = True
+
+ if self._origttl is not None:
+ cmd += ["-L", str(self.ttl)]
+
+ for prop, opt in zip(dnskey._PROPS, dnskey._OPTS):
+ if not opt or not self._changed[prop]:
+ continue
+
+ delete = False
+ if prop in self._delete and self._delete[prop]:
+ delete = True
+
+ when = 'none' if delete else self._fmttime[prop]
+ cmd += [opt, when]
+ first = False
+
+ if cmd:
+ fullcmd = [settime_bin, "-K", self._dir] + cmd + [self.keystr,]
+ if not quiet:
+ print('# ' + ' '.join(fullcmd))
+ try:
+ p = Popen(fullcmd, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = p.communicate()
+ if stderr:
+ raise Exception(str(stderr))
+ except Exception as e:
+ raise Exception('unable to run %s: %s' %
+ (settime_bin, str(e)))
+ self._origttl = None
+ for prop in dnskey._PROPS:
+ self._original[prop] = self._timestamps[prop]
+ self._changed[prop] = False
+
+ @classmethod
+ def generate(cls, keygen_bin, randomdev, keys_dir, name, alg, keysize, sep,
+ ttl, publish=None, activate=None, **kwargs):
+ quiet = kwargs.get('quiet', False)
+
+ keygen_cmd = [keygen_bin, "-q", "-K", keys_dir, "-L", str(ttl)]
+
+ if randomdev:
+ keygen_cmd += ["-r", randomdev]
+
+ if sep:
+ keygen_cmd.append("-fk")
+
+ if alg:
+ keygen_cmd += ["-a", alg]
+
+ if keysize:
+ keygen_cmd += ["-b", str(keysize)]
+
+ if publish:
+ t = dnskey.timefromepoch(publish)
+ keygen_cmd += ["-P", dnskey.formattime(t)]
+
+ if activate:
+ t = dnskey.timefromepoch(activate)
+ keygen_cmd += ["-A", dnskey.formattime(activate)]
+
+ keygen_cmd.append(name)
+
+ if not quiet:
+ print('# ' + ' '.join(keygen_cmd))
+
+ p = Popen(keygen_cmd, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = p.communicate()
+ if stderr:
+ raise Exception('unable to generate key: ' + str(stderr))
+
+ try:
+ keystr = stdout.splitlines()[0].decode('ascii')
+ newkey = dnskey(keystr, keys_dir, ttl)
+ return newkey
+ except Exception as e:
+ raise Exception('unable to parse generated key: %s' % str(e))
+
+ def generate_successor(self, keygen_bin, randomdev, prepublish, **kwargs):
+ quiet = kwargs.get('quiet', False)
+
+ if not self.inactive():
+ raise Exception("predecessor key %s has no inactive date" % self)
+
+ keygen_cmd = [keygen_bin, "-q", "-K", self._dir, "-S", self.keystr]
+
+ if self.ttl:
+ keygen_cmd += ["-L", str(self.ttl)]
+
+ if randomdev:
+ keygen_cmd += ["-r", randomdev]
+
+ if prepublish:
+ keygen_cmd += ["-i", str(prepublish)]
+
+ if not quiet:
+ print('# ' + ' '.join(keygen_cmd))
+
+ p = Popen(keygen_cmd, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = p.communicate()
+ if stderr:
+ raise Exception('unable to generate key: ' + stderr)
+
+ try:
+ keystr = stdout.splitlines()[0].decode('ascii')
+ newkey = dnskey(keystr, self._dir, self.ttl)
+ return newkey
+ except:
+ raise Exception('unable to generate successor for key %s' % self)
+
+ @staticmethod
+ def algstr(alg):
+ name = None
+ if alg in range(len(dnskey._ALGNAMES)):
+ name = dnskey._ALGNAMES[alg]
+ return name if name else ("%03d" % alg)
+
+ @staticmethod
+ def algnum(alg):
+ if not alg:
+ return None
+ alg = alg.upper()
+ try:
+ return dnskey._ALGNAMES.index(alg)
+ except ValueError:
+ return None
+
+ def algname(self, alg=None):
+ return self.algstr(alg or self.alg)
+
+ @staticmethod
+ def timefromepoch(secs):
+ return time.gmtime(secs)
+
+ @staticmethod
+ def parsetime(string):
+ return time.strptime(string, "%Y%m%d%H%M%S")
+
+ @staticmethod
+ def epochfromtime(t):
+ return calendar.timegm(t)
+
+ @staticmethod
+ def formattime(t):
+ return time.strftime("%Y%m%d%H%M%S", t)
+
+ def setmeta(self, prop, secs, now, **kwargs):
+ force = kwargs.get('force', False)
+
+ if self._timestamps[prop] == secs:
+ return
+
+ if self._original[prop] is not None and \
+ self._original[prop] < now and not force:
+ raise TimePast(self, prop, self._original[prop])
+
+ if secs is None:
+ self._changed[prop] = False \
+ if self._original[prop] is None else True
+
+ self._delete[prop] = True
+ self._timestamps[prop] = None
+ self._times[prop] = None
+ self._fmttime[prop] = None
+ return
+
+ t = self.timefromepoch(secs)
+ self._timestamps[prop] = secs
+ self._times[prop] = t
+ self._fmttime[prop] = self.formattime(t)
+ self._changed[prop] = False if \
+ self._original[prop] == self._timestamps[prop] else True
+
+ def gettime(self, prop):
+ return self._times[prop]
+
+ def getfmttime(self, prop):
+ return self._fmttime[prop]
+
+ def gettimestamp(self, prop):
+ return self._timestamps[prop]
+
+ def created(self):
+ return self._timestamps["Created"]
+
+ def syncpublish(self):
+ return self._timestamps["SyncPublish"]
+
+ def setsyncpublish(self, secs, now=time.time(), **kwargs):
+ self.setmeta("SyncPublish", secs, now, **kwargs)
+
+ def publish(self):
+ return self._timestamps["Publish"]
+
+ def setpublish(self, secs, now=time.time(), **kwargs):
+ self.setmeta("Publish", secs, now, **kwargs)
+
+ def activate(self):
+ return self._timestamps["Activate"]
+
+ def setactivate(self, secs, now=time.time(), **kwargs):
+ self.setmeta("Activate", secs, now, **kwargs)
+
+ def revoke(self):
+ return self._timestamps["Revoke"]
+
+ def setrevoke(self, secs, now=time.time(), **kwargs):
+ self.setmeta("Revoke", secs, now, **kwargs)
+
+ def inactive(self):
+ return self._timestamps["Inactive"]
+
+ def setinactive(self, secs, now=time.time(), **kwargs):
+ self.setmeta("Inactive", secs, now, **kwargs)
+
+ def delete(self):
+ return self._timestamps["Delete"]
+
+ def setdelete(self, secs, now=time.time(), **kwargs):
+ self.setmeta("Delete", secs, now, **kwargs)
+
+ def syncdelete(self):
+ return self._timestamps["SyncDelete"]
+
+ def setsyncdelete(self, secs, now=time.time(), **kwargs):
+ self.setmeta("SyncDelete", secs, now, **kwargs)
+
+ def setttl(self, ttl):
+ if ttl is None or self.ttl == ttl:
+ return
+ elif self._origttl is None:
+ self._origttl = self.ttl
+ self.ttl = ttl
+ elif self._origttl == ttl:
+ self._origttl = None
+ self.ttl = ttl
+ else:
+ self.ttl = ttl
+
+ def keytype(self):
+ return ("KSK" if self.sep else "ZSK")
+
+ def __str__(self):
+ return ("%s/%s/%05d"
+ % (self.name, self.algname(), self.keyid))
+
+ def __repr__(self):
+ return ("%s/%s/%05d (%s)"
+ % (self.name, self.algname(), self.keyid,
+ ("KSK" if self.sep else "ZSK")))
+
+ def date(self):
+ return (self.activate() or self.publish() or self.created())
+
+ # keys are sorted first by zone name, then by algorithm. within
+ # the same name/algorithm, they are sorted according to their
+ # 'date' value: the activation date if set, OR the publication
+ # if set, OR the creation date.
+ def __lt__(self, other):
+ if self.name != other.name:
+ return self.name < other.name
+ if self.alg != other.alg:
+ return self.alg < other.alg
+ return self.date() < other.date()
+
+ def check_prepub(self, output=None):
+ def noop(*args, **kwargs): pass
+ if not output:
+ output = noop
+
+ now = int(time.time())
+ a = self.activate()
+ p = self.publish()
+
+ if not a:
+ return False
+
+ if not p:
+ if a > now:
+ output("WARNING: Key %s is scheduled for\n"
+ "\t activation but not for publication."
+ % repr(self))
+ return False
+
+ if p <= now and a <= now:
+ return True
+
+ if p == a:
+ output("WARNING: %s is scheduled to be\n"
+ "\t published and activated at the same time. This\n"
+ "\t could result in a coverage gap if the zone was\n"
+ "\t previously signed. Activation should be at least\n"
+ "\t %s after publication."
+ % (repr(self),
+ dnskey.duration(self.ttl) or 'one DNSKEY TTL'))
+ return True
+
+ if a < p:
+ output("WARNING: Key %s is active before it is published"
+ % repr(self))
+ return False
+
+ if self.ttl is not None and a - p < self.ttl:
+ output("WARNING: Key %s is activated too soon\n"
+ "\t after publication; this could result in coverage \n"
+ "\t gaps due to resolver caches containing old data.\n"
+ "\t Activation should be at least %s after\n"
+ "\t publication."
+ % (repr(self),
+ dnskey.duration(self.ttl) or 'one DNSKEY TTL'))
+ return False
+
+ return True
+
+ def check_postpub(self, output = None, timespan = None):
+ def noop(*args, **kwargs): pass
+ if output is None:
+ output = noop
+
+ if timespan is None:
+ timespan = self.ttl
+
+ now = time.time()
+ d = self.delete()
+ i = self.inactive()
+
+ if not d:
+ return False
+
+ if not i:
+ if d > now:
+ output("WARNING: Key %s is scheduled for\n"
+ "\t deletion but not for inactivation." % repr(self))
+ return False
+
+ if d < now and i < now:
+ return True
+
+ if d < i:
+ output("WARNING: Key %s is scheduled for\n"
+ "\t deletion before inactivation."
+ % repr(self))
+ return False
+
+ if d - i < timespan:
+ output("WARNING: Key %s scheduled for\n"
+ "\t deletion too soon after deactivation; this may \n"
+ "\t result in coverage gaps due to resolver caches\n"
+ "\t containing old data. Deletion should be at least\n"
+ "\t %s after inactivation."
+ % (repr(self), dnskey.duration(timespan)))
+ return False
+
+ return True
+
+ @staticmethod
+ def duration(secs):
+ if not secs:
+ return None
+
+ units = [("year", 60*60*24*365),
+ ("month", 60*60*24*30),
+ ("day", 60*60*24),
+ ("hour", 60*60),
+ ("minute", 60),
+ ("second", 1)]
+
+ output = []
+ for unit in units:
+ v, secs = secs // unit[1], secs % unit[1]
+ if v > 0:
+ output.append("%d %s%s" % (v, unit[0], "s" if v > 1 else ""))
+
+ return ", ".join(output)
+
diff --git a/bin/python/isc/eventlist.py.in b/bin/python/isc/eventlist.py.in
new file mode 100644
index 0000000..5c1b31a
--- /dev/null
+++ b/bin/python/isc/eventlist.py.in
@@ -0,0 +1,166 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from collections import defaultdict
+from .dnskey import *
+from .keydict import *
+from .keyevent import *
+
+
+class eventlist:
+ _K = defaultdict(lambda: defaultdict(list))
+ _Z = defaultdict(lambda: defaultdict(list))
+ _zones = set()
+ _kdict = None
+
+ def __init__(self, kdict):
+ properties = ["SyncPublish", "Publish", "SyncDelete",
+ "Activate", "Inactive", "Delete"]
+ self._kdict = kdict
+ for zone in kdict.zones():
+ self._zones.add(zone)
+ for alg, keys in kdict[zone].items():
+ for k in keys.values():
+ for prop in properties:
+ t = k.gettime(prop)
+ if not t:
+ continue
+ e = keyevent(prop, k, t)
+ if k.sep:
+ self._K[zone][alg].append(e)
+ else:
+ self._Z[zone][alg].append(e)
+
+ self._K[zone][alg] = sorted(self._K[zone][alg],
+ key=lambda event: event.when)
+ self._Z[zone][alg] = sorted(self._Z[zone][alg],
+ key=lambda event: event.when)
+
+ # scan events per zone, algorithm, and key type, in order of
+ # occurrance, noting inconsistent states when found
+ def coverage(self, zone, keytype, until, output = None):
+ def noop(*args, **kwargs): pass
+ if not output:
+ output = noop
+
+ no_zsk = True if (keytype and keytype == "KSK") else False
+ no_ksk = True if (keytype and keytype == "ZSK") else False
+ kok = zok = True
+ found = False
+
+ if zone and not zone in self._zones:
+ output("ERROR: No key events found for %s" % zone)
+ return False
+
+ if zone:
+ found = True
+ if not no_ksk:
+ kok = self.checkzone(zone, "KSK", until, output)
+ if not no_zsk:
+ zok = self.checkzone(zone, "ZSK", until, output)
+ else:
+ for z in self._zones:
+ if not no_ksk and z in self._K.keys():
+ found = True
+ kok = self.checkzone(z, "KSK", until, output)
+ if not no_zsk and z in self._Z.keys():
+ found = True
+ kok = self.checkzone(z, "ZSK", until, output)
+
+ if not found:
+ output("ERROR: No key events found")
+ return False
+
+ return (kok and zok)
+
+ def checkzone(self, zone, keytype, until, output):
+ allok = True
+ if keytype == "KSK":
+ kz = self._K[zone]
+ else:
+ kz = self._Z[zone]
+
+ for alg in kz.keys():
+ output("Checking scheduled %s events for zone %s, "
+ "algorithm %s..." %
+ (keytype, zone, dnskey.algstr(alg)))
+ ok = eventlist.checkset(kz[alg], keytype, until, output)
+ if ok:
+ output("No errors found")
+ allok = allok and ok
+
+ return allok
+
+ @staticmethod
+ def showset(eventset, output):
+ if not eventset:
+ return
+ output(" " + eventset[0].showtime() + ":", skip=False)
+ for event in eventset:
+ output(" %s: %s" % (event.what, repr(event.key)), skip=False)
+
+ @staticmethod
+ def checkset(eventset, keytype, until, output):
+ groups = list()
+ group = list()
+
+ # collect up all events that have the same time
+ eventsfound = False
+ for event in eventset:
+ # we found an event
+ eventsfound = True
+
+ # add event to current group
+ if (not group or group[0].when == event.when):
+ group.append(event)
+
+ # if we're at the end of the list, we're done. if
+ # we've found an event with a later time, start a new group
+ if (group[0].when != event.when):
+ groups.append(group)
+ group = list()
+ group.append(event)
+
+ if group:
+ groups.append(group)
+
+ if not eventsfound:
+ output("ERROR: No %s events found" % keytype)
+ return False
+
+ active = published = None
+ for group in groups:
+ if (until and calendar.timegm(group[0].when) > until):
+ output("Ignoring events after %s" %
+ time.strftime("%a %b %d %H:%M:%S UTC %Y",
+ time.gmtime(until)))
+ return True
+
+ for event in group:
+ (active, published) = event.status(active, published)
+
+ eventlist.showset(group, output)
+
+ # and then check for inconsistencies:
+ if not active:
+ output("ERROR: No %s's are active after this event" % keytype)
+ return False
+ elif not published:
+ output("ERROR: No %s's are published after this event"
+ % keytype)
+ return False
+ elif not published.intersection(active):
+ output("ERROR: No %s's are both active and published "
+ "after this event" % keytype)
+ return False
+
+ return True
+
diff --git a/bin/python/isc/keydict.py.in b/bin/python/isc/keydict.py.in
new file mode 100644
index 0000000..578a847
--- /dev/null
+++ b/bin/python/isc/keydict.py.in
@@ -0,0 +1,84 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from collections import defaultdict
+from . import dnskey
+import os
+import glob
+
+
+########################################################################
+# Class keydict
+########################################################################
+class keydict:
+ """ A dictionary of keys, indexed by name, algorithm, and key id """
+
+ _keydict = defaultdict(lambda: defaultdict(dict))
+ _defttl = None
+ _missing = []
+
+ def __init__(self, dp=None, **kwargs):
+ self._defttl = kwargs.get('keyttl', None)
+ zones = kwargs.get('zones', None)
+
+ if not zones:
+ path = kwargs.get('path',None) or '.'
+ self.readall(path)
+ else:
+ for zone in zones:
+ if 'path' in kwargs and kwargs['path'] is not None:
+ path = kwargs['path']
+ else:
+ path = dp and dp.policy(zone).directory or '.'
+ if not self.readone(path, zone):
+ self._missing.append(zone)
+
+ def readall(self, path):
+ files = glob.glob(os.path.join(path, '*.private'))
+
+ for infile in files:
+ key = dnskey(infile, path, self._defttl)
+ self._keydict[key.name][key.alg][key.keyid] = key
+
+ def readone(self, path, zone):
+ match='K' + zone + '.+*.private'
+ files = glob.glob(os.path.join(path, match))
+
+ found = False
+ for infile in files:
+ key = dnskey(infile, path, self._defttl)
+ if key.name != zone: # shouldn't ever happen
+ continue
+ self._keydict[key.name][key.alg][key.keyid] = key
+ found = True
+
+ return found
+
+ def __iter__(self):
+ for zone, algorithms in self._keydict.items():
+ for alg, keys in algorithms.items():
+ for key in keys.values():
+ yield key
+
+ def __getitem__(self, name):
+ return self._keydict[name]
+
+ def zones(self):
+ return (self._keydict.keys())
+
+ def algorithms(self, zone):
+ return (self._keydict[zone].keys())
+
+ def keys(self, zone, alg):
+ return (self._keydict[zone][alg].keys())
+
+ def missing(self):
+ return (self._missing)
diff --git a/bin/python/isc/keyevent.py.in b/bin/python/isc/keyevent.py.in
new file mode 100644
index 0000000..cfc935a
--- /dev/null
+++ b/bin/python/isc/keyevent.py.in
@@ -0,0 +1,76 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import time
+
+
+########################################################################
+# Class keyevent
+########################################################################
+class keyevent:
+ """ A discrete key event, e.g., Publish, Activate, Inactive, Delete,
+ etc. Stores the date of the event, and identifying information
+ about the key to which the event will occur."""
+
+ def __init__(self, what, key, when=None):
+ self.what = what
+ self.when = when or key.gettime(what)
+ self.key = key
+ self.sep = key.sep
+ self.zone = key.name
+ self.alg = key.alg
+ self.keyid = key.keyid
+
+ def __repr__(self):
+ return repr((self.when, self.what, self.keyid, self.sep,
+ self.zone, self.alg))
+
+ def showtime(self):
+ return time.strftime("%a %b %d %H:%M:%S UTC %Y", self.when)
+
+ # update sets of active and published keys, based on
+ # the contents of this keyevent
+ def status(self, active, published, output = None):
+ def noop(*args, **kwargs): pass
+ if not output:
+ output = noop
+
+ if not active:
+ active = set()
+ if not published:
+ published = set()
+
+ if self.what == "Activate":
+ active.add(self.keyid)
+ elif self.what == "Publish":
+ published.add(self.keyid)
+ elif self.what == "Inactive":
+ if self.keyid not in active:
+ output("\tWARNING: %s scheduled to become inactive "
+ "before it is active"
+ % repr(self.key))
+ else:
+ active.remove(self.keyid)
+ elif self.what == "Delete":
+ if self.keyid in published:
+ published.remove(self.keyid)
+ else:
+ output("WARNING: key %s is scheduled for deletion "
+ "before it is published" % repr(self.key))
+ elif self.what == "Revoke":
+ # We don't need to worry about the logic of this one;
+ # just stop counting this key as either active or published
+ if self.keyid in published:
+ published.remove(self.keyid)
+ if self.keyid in active:
+ active.remove(self.keyid)
+
+ return active, published
diff --git a/bin/python/isc/keymgr.py.in b/bin/python/isc/keymgr.py.in
new file mode 100644
index 0000000..c193daa
--- /dev/null
+++ b/bin/python/isc/keymgr.py.in
@@ -0,0 +1,154 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from __future__ import print_function
+import os, sys, argparse, glob, re, time, calendar, pprint
+from collections import defaultdict
+
+prog='dnssec-keymgr'
+
+from isc import dnskey, keydict, keyseries, policy, parsetab, utils
+
+############################################################################
+# print a fatal error and exit
+############################################################################
+def fatal(*args, **kwargs):
+ print(*args, **kwargs)
+ sys.exit(1)
+
+############################################################################
+# find the location of an external command
+############################################################################
+def set_path(command, default=None):
+ """ find the location of a specified command. If a default is supplied,
+ exists and it's an executable, we use it; otherwise we search PATH
+ for an alternative.
+ :param command: command to look for
+ :param default: default value to use
+ :return: PATH with the location of a suitable binary
+ """
+ fpath = default
+ if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK):
+ path = os.environ["PATH"]
+ if not path:
+ path = os.path.defpath
+ for directory in path.split(os.pathsep):
+ fpath = directory + os.sep + command
+ if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
+ break
+ fpath = None
+
+ return fpath
+
+############################################################################
+# parse arguments
+############################################################################
+def parse_args():
+ """ Read command line arguments, returns 'args' object
+ :return: args object properly prepared
+ """
+
+ keygen = set_path('dnssec-keygen',
+ os.path.join(utils.prefix('sbin'), 'dnssec-keygen'))
+ settime = set_path('dnssec-settime',
+ os.path.join(utils.prefix('sbin'), 'dnssec-settime'))
+
+ parser = argparse.ArgumentParser(description=prog + ': schedule '
+ 'DNSSEC key rollovers according to a '
+ 'pre-defined policy')
+
+ parser.add_argument('zone', type=str, nargs='*', default=None,
+ help='Zone(s) to which the policy should be applied ' +
+ '(default: all zones in the directory)')
+ parser.add_argument('-K', dest='path', type=str,
+ help='Directory containing keys', metavar='dir')
+ parser.add_argument('-c', dest='policyfile', type=str,
+ help='Policy definition file', metavar='file')
+ parser.add_argument('-g', dest='keygen', default=keygen, type=str,
+ help='Path to \'dnssec-keygen\'',
+ metavar='path')
+ parser.add_argument('-r', dest='randomdev', type=str, default=None,
+ help='Path to a file containing random data to pass to \'dnssec-keygen\'',
+ metavar='path')
+ parser.add_argument('-s', dest='settime', default=settime, type=str,
+ help='Path to \'dnssec-settime\'',
+ metavar='path')
+ parser.add_argument('-k', dest='no_zsk',
+ action='store_true', default=False,
+ help='Only apply policy to key-signing keys (KSKs)')
+ parser.add_argument('-z', dest='no_ksk',
+ action='store_true', default=False,
+ help='Only apply policy to zone-signing keys (ZSKs)')
+ parser.add_argument('-f', '--force', dest='force', action='store_true',
+ default=False, help='Force updates to key events '+
+ 'even if they are in the past')
+ parser.add_argument('-q', '--quiet', dest='quiet', action='store_true',
+ default=False, help='Update keys silently')
+ parser.add_argument('-v', '--version', action='version',
+ version=utils.version)
+
+ args = parser.parse_args()
+
+ if args.no_zsk and args.no_ksk:
+ fatal("ERROR: -z and -k cannot be used together.")
+
+ if args.keygen is None:
+ fatal("ERROR: dnssec-keygen not found")
+
+ if args.settime is None:
+ fatal("ERROR: dnssec-settime not found")
+
+ # if a policy file was specified, check that it exists.
+ # if not, use the default file, unless it doesn't exist
+ if args.policyfile is not None:
+ if not os.path.exists(args.policyfile):
+ fatal('ERROR: Policy file "%s" not found' % args.policyfile)
+ else:
+ args.policyfile = os.path.join(utils.sysconfdir,
+ 'dnssec-policy.conf')
+ if not os.path.exists(args.policyfile):
+ args.policyfile = None
+
+ return args
+
+############################################################################
+# main
+############################################################################
+def main():
+ args = parse_args()
+
+ # As we may have specific locations for the binaries, we put that info
+ # into a context object that can be passed around
+ context = {'keygen_path': args.keygen,
+ 'settime_path': args.settime,
+ 'keys_path': args.path,
+ 'randomdev': args.randomdev}
+
+ try:
+ dp = policy.dnssec_policy(args.policyfile)
+ except Exception as e:
+ fatal('Unable to load DNSSEC policy: ' + str(e))
+
+ try:
+ kd = keydict(dp, path=args.path, zones=args.zone)
+ except Exception as e:
+ fatal('Unable to build key dictionary: ' + str(e))
+
+ try:
+ ks = keyseries(kd, context=context)
+ except Exception as e:
+ fatal('Unable to build key series: ' + str(e))
+
+ try:
+ ks.enforce_policy(dp, ksk=args.no_zsk, zsk=args.no_ksk,
+ force=args.force, quiet=args.quiet)
+ except Exception as e:
+ fatal('Unable to apply policy: ' + str(e))
diff --git a/bin/python/isc/keyseries.py.in b/bin/python/isc/keyseries.py.in
new file mode 100644
index 0000000..e1241f0
--- /dev/null
+++ b/bin/python/isc/keyseries.py.in
@@ -0,0 +1,191 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from collections import defaultdict
+from .dnskey import *
+from .keydict import *
+from .keyevent import *
+from .policy import *
+import time
+
+
+class keyseries:
+ _K = defaultdict(lambda: defaultdict(list))
+ _Z = defaultdict(lambda: defaultdict(list))
+ _zones = set()
+ _kdict = None
+ _context = None
+
+ def __init__(self, kdict, now=time.time(), context=None):
+ self._kdict = kdict
+ self._context = context
+ self._zones = set(kdict.missing())
+
+ for zone in kdict.zones():
+ self._zones.add(zone)
+ for alg, keys in kdict[zone].items():
+ for k in keys.values():
+ if k.sep:
+ if not (k.delete() and k.delete() < now):
+ self._K[zone][alg].append(k)
+ else:
+ if not (k.delete() and k.delete() < now):
+ self._Z[zone][alg].append(k)
+
+ self._K[zone][alg].sort()
+ self._Z[zone][alg].sort()
+
+ def __iter__(self):
+ for zone in self._zones:
+ for collection in [self._K, self._Z]:
+ if zone not in collection:
+ continue
+ for alg, keys in collection[zone].items():
+ for key in keys:
+ yield key
+
+ def dump(self):
+ for k in self:
+ print("%s" % repr(k))
+
+ def fixseries(self, keys, policy, now, **kwargs):
+ force = kwargs.get('force', False)
+ if not keys:
+ return
+
+ # handle the first key
+ key = keys[0]
+ if key.sep:
+ rp = policy.ksk_rollperiod
+ prepub = policy.ksk_prepublish or (30 * 86400)
+ postpub = policy.ksk_postpublish or (30 * 86400)
+ else:
+ rp = policy.zsk_rollperiod
+ prepub = policy.zsk_prepublish or (30 * 86400)
+ postpub = policy.zsk_postpublish or (30 * 86400)
+
+ # the first key should be published and active
+ p = key.publish()
+ a = key.activate()
+ if not p or p > now:
+ key.setpublish(now)
+ if not a or a > now:
+ key.setactivate(now)
+
+ if not rp:
+ key.setinactive(None, **kwargs)
+ key.setdelete(None, **kwargs)
+ else:
+ key.setinactive(a + rp, **kwargs)
+ key.setdelete(a + rp + postpub, **kwargs)
+
+ if policy.keyttl != key.ttl:
+ key.setttl(policy.keyttl)
+
+ # handle all the subsequent keys
+ prev = key
+ for key in keys[1:]:
+ # if no rollperiod, then all keys after the first in
+ # the series kept inactive.
+ # (XXX: we need to change this to allow standby keys)
+ if not rp:
+ key.setpublish(None, **kwargs)
+ key.setactivate(None, **kwargs)
+ key.setinactive(None, **kwargs)
+ key.setdelete(None, **kwargs)
+ if policy.keyttl != key.ttl:
+ key.setttl(policy.keyttl)
+ continue
+
+ # otherwise, ensure all dates are set correctly based on
+ # the initial key
+ a = prev.inactive()
+ p = a - prepub
+ key.setactivate(a, **kwargs)
+ key.setpublish(p, **kwargs)
+ key.setinactive(a + rp, **kwargs)
+ key.setdelete(a + rp + postpub, **kwargs)
+ prev.setdelete(a + postpub, **kwargs)
+ if policy.keyttl != key.ttl:
+ key.setttl(policy.keyttl)
+ prev = key
+
+ # if we haven't got sufficient coverage, create successor key(s)
+ while rp and prev.inactive() and \
+ prev.inactive() < now + policy.coverage:
+ # commit changes to predecessor: a successor can only be
+ # generated if Inactive has been set in the predecessor key
+ prev.commit(self._context['settime_path'], **kwargs)
+ key = prev.generate_successor(self._context['keygen_path'],
+ self._context['randomdev'],
+ prepub, **kwargs)
+
+ key.setinactive(key.activate() + rp, **kwargs)
+ key.setdelete(key.inactive() + postpub, **kwargs)
+ keys.append(key)
+ prev = key
+
+ # last key? we already know we have sufficient coverage now, so
+ # disable the inactivation of the final key (if it was set),
+ # ensuring that if dnssec-keymgr isn't run again, the last key
+ # in the series will at least remain usable.
+ prev.setinactive(None, **kwargs)
+ prev.setdelete(None, **kwargs)
+
+ # commit changes
+ for key in keys:
+ key.commit(self._context['settime_path'], **kwargs)
+
+
+ def enforce_policy(self, policies, now=time.time(), **kwargs):
+ # If zones is provided as a parameter, use that list.
+ # If not, use what we have in this object
+ zones = kwargs.get('zones', self._zones)
+ keys_dir = kwargs.get('dir', self._context.get('keys_path', None))
+ force = kwargs.get('force', False)
+
+ for zone in zones:
+ collections = []
+ policy = policies.policy(zone)
+ keys_dir = keys_dir or policy.directory or '.'
+ alg = policy.algorithm
+ algnum = dnskey.algnum(alg)
+ if 'ksk' not in kwargs or not kwargs['ksk']:
+ if len(self._Z[zone][algnum]) == 0:
+ k = dnskey.generate(self._context['keygen_path'],
+ self._context['randomdev'],
+ keys_dir, zone, alg,
+ policy.zsk_keysize, False,
+ policy.keyttl or 3600,
+ **kwargs)
+ self._Z[zone][algnum].append(k)
+ collections.append(self._Z[zone])
+
+ if 'zsk' not in kwargs or not kwargs['zsk']:
+ if len(self._K[zone][algnum]) == 0:
+ k = dnskey.generate(self._context['keygen_path'],
+ self._context['randomdev'],
+ keys_dir, zone, alg,
+ policy.ksk_keysize, True,
+ policy.keyttl or 3600,
+ **kwargs)
+ self._K[zone][algnum].append(k)
+ collections.append(self._K[zone])
+
+ for collection in collections:
+ for algorithm, keys in collection.items():
+ if algorithm != algnum:
+ continue
+ try:
+ self.fixseries(keys, policy, now, **kwargs)
+ except Exception as e:
+ raise Exception('%s/%s: %s' %
+ (zone, dnskey.algstr(algnum), str(e)))
diff --git a/bin/python/isc/keyzone.py.in b/bin/python/isc/keyzone.py.in
new file mode 100644
index 0000000..2451d43
--- /dev/null
+++ b/bin/python/isc/keyzone.py.in
@@ -0,0 +1,55 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import os
+import sys
+import re
+from subprocess import Popen, PIPE
+
+########################################################################
+# Exceptions
+########################################################################
+class KeyZoneException(Exception):
+ pass
+
+########################################################################
+# class keyzone
+########################################################################
+class keyzone:
+ """reads a zone file to find data relevant to keys"""
+
+ def __init__(self, name, filename, czpath):
+ self.maxttl = None
+ self.keyttl = None
+
+ if not name:
+ return
+
+ if not czpath or not os.path.isfile(czpath) \
+ or not os.access(czpath, os.X_OK):
+ raise KeyZoneException('"named-compilezone" not found')
+ return
+
+ maxttl = keyttl = None
+
+ fp, _ = Popen([czpath, "-o", "-", name, filename],
+ stdout=PIPE, stderr=PIPE).communicate()
+ for line in fp.splitlines():
+ if re.search('^[:space:]*;', line):
+ continue
+ fields = line.split()
+ if not maxttl or int(fields[1]) > maxttl:
+ maxttl = int(fields[1])
+ if fields[3] == "DNSKEY":
+ keyttl = int(fields[1])
+
+ self.keyttl = keyttl
+ self.maxttl = maxttl
diff --git a/bin/python/isc/policy.py.in b/bin/python/isc/policy.py.in
new file mode 100644
index 0000000..f7829fa
--- /dev/null
+++ b/bin/python/isc/policy.py.in
@@ -0,0 +1,728 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import re
+import ply.lex as lex
+import ply.yacc as yacc
+from string import *
+from copy import copy
+
+
+############################################################################
+# PolicyLex: a lexer for the policy file syntax.
+############################################################################
+class PolicyLex:
+ reserved = ('POLICY',
+ 'ALGORITHM_POLICY',
+ 'ZONE',
+ 'ALGORITHM',
+ 'DIRECTORY',
+ 'KEYTTL',
+ 'KEY_SIZE',
+ 'ROLL_PERIOD',
+ 'PRE_PUBLISH',
+ 'POST_PUBLISH',
+ 'COVERAGE',
+ 'STANDBY',
+ 'NONE')
+
+ tokens = reserved + ('DATESUFFIX',
+ 'KEYTYPE',
+ 'ALGNAME',
+ 'STR',
+ 'QSTRING',
+ 'NUMBER',
+ 'LBRACE',
+ 'RBRACE',
+ 'SEMI')
+ reserved_map = {}
+
+ t_ignore = ' \t'
+ t_ignore_olcomment = r'(//|\#).*'
+
+ t_LBRACE = r'\{'
+ t_RBRACE = r'\}'
+ t_SEMI = r';';
+
+ def t_newline(self, t):
+ r'\n+'
+ t.lexer.lineno += t.value.count("\n")
+
+ def t_comment(self, t):
+ r'/\*(.|\n)*?\*/'
+ t.lexer.lineno += t.value.count('\n')
+
+ def t_DATESUFFIX(self, t):
+ r'(?i)(?<=[0-9 \t])(y(?:ears|ear|ea|e)?|mo(?:nths|nth|nt|n)?|w(?:eeks|eek|ee|e)?|d(?:ays|ay|a)?|h(?:ours|our|ou|o)?|mi(?:nutes|nute|nut|nu|n)?|s(?:econds|econd|econ|eco|ec|e)?)\b'
+ t.value = re.match(r'(?i)(y|mo|w|d|h|mi|s)([a-z]*)', t.value).group(1).lower()
+ return t
+
+ def t_KEYTYPE(self, t):
+ r'(?i)\b(KSK|ZSK)\b'
+ t.value = t.value.upper()
+ return t
+
+ def t_ALGNAME(self, t):
+ r'(?i)\b(RSAMD5|DH|DSA|NSEC3DSA|ECC|RSASHA1|NSEC3RSASHA1|RSASHA256|RSASHA512|ECCGOST|ECDSAP256SHA256|ECDSAP384SHA384|ED25519|ED448)\b'
+ t.value = t.value.upper()
+ return t
+
+ def t_STR(self, t):
+ r'[A-Za-z._-][\w._-]*'
+ t.type = self.reserved_map.get(t.value, "STR")
+ return t
+
+ def t_QSTRING(self, t):
+ r'"([^"\n]|(\\"))*"'
+ t.type = self.reserved_map.get(t.value, "QSTRING")
+ t.value = t.value[1:-1]
+ return t
+
+ def t_NUMBER(self, t):
+ r'\d+'
+ t.value = int(t.value)
+ return t
+
+ def t_error(self, t):
+ print("Illegal character '%s'" % t.value[0])
+ t.lexer.skip(1)
+
+ def __init__(self, **kwargs):
+ if 'maketrans' in dir(str):
+ trans = str.maketrans('_', '-')
+ else:
+ trans = maketrans('_', '-')
+ for r in self.reserved:
+ self.reserved_map[r.lower().translate(trans)] = r
+ self.lexer = lex.lex(object=self, **kwargs)
+
+ def test(self, text):
+ self.lexer.input(text)
+ while True:
+ t = self.lexer.token()
+ if not t:
+ break
+ print(t)
+
+############################################################################
+# Policy: this object holds a set of DNSSEC policy settings.
+############################################################################
+class Policy:
+ is_zone = False
+ is_alg = False
+ is_constructed = False
+ ksk_rollperiod = None
+ zsk_rollperiod = None
+ ksk_prepublish = None
+ zsk_prepublish = None
+ ksk_postpublish = None
+ zsk_postpublish = None
+ ksk_keysize = None
+ zsk_keysize = None
+ ksk_standby = None
+ zsk_standby = None
+ keyttl = None
+ coverage = None
+ directory = None
+ valid_key_sz_per_algo = {'DSA': [512, 1024],
+ 'NSEC3DSA': [512, 1024],
+ 'RSAMD5': [512, 4096],
+ 'RSASHA1': [512, 4096],
+ 'NSEC3RSASHA1': [512, 4096],
+ 'RSASHA256': [512, 4096],
+ 'RSASHA512': [512, 4096],
+ 'ECCGOST': None,
+ 'ECDSAP256SHA256': None,
+ 'ECDSAP384SHA384': None,
+ 'ED25519': None,
+ 'ED448': None}
+
+ def __init__(self, name=None, algorithm=None, parent=None):
+ self.name = name
+ self.algorithm = algorithm
+ self.parent = parent
+ pass
+
+ def __repr__(self):
+ return ("%spolicy %s:\n"
+ "\tinherits %s\n"
+ "\tdirectory %s\n"
+ "\talgorithm %s\n"
+ "\tcoverage %s\n"
+ "\tksk_keysize %s\n"
+ "\tzsk_keysize %s\n"
+ "\tksk_rollperiod %s\n"
+ "\tzsk_rollperiod %s\n"
+ "\tksk_prepublish %s\n"
+ "\tksk_postpublish %s\n"
+ "\tzsk_prepublish %s\n"
+ "\tzsk_postpublish %s\n"
+ "\tksk_standby %s\n"
+ "\tzsk_standby %s\n"
+ "\tkeyttl %s\n"
+ %
+ ((self.is_constructed and 'constructed ' or \
+ self.is_zone and 'zone ' or \
+ self.is_alg and 'algorithm ' or ''),
+ self.name or 'UNKNOWN',
+ self.parent and self.parent.name or 'None',
+ self.directory and ('"' + str(self.directory) + '"') or 'None',
+ self.algorithm or 'None',
+ self.coverage and str(self.coverage) or 'None',
+ self.ksk_keysize and str(self.ksk_keysize) or 'None',
+ self.zsk_keysize and str(self.zsk_keysize) or 'None',
+ self.ksk_rollperiod and str(self.ksk_rollperiod) or 'None',
+ self.zsk_rollperiod and str(self.zsk_rollperiod) or 'None',
+ self.ksk_prepublish and str(self.ksk_prepublish) or 'None',
+ self.ksk_postpublish and str(self.ksk_postpublish) or 'None',
+ self.zsk_prepublish and str(self.zsk_prepublish) or 'None',
+ self.zsk_postpublish and str(self.zsk_postpublish) or 'None',
+ self.ksk_standby and str(self.ksk_standby) or 'None',
+ self.zsk_standby and str(self.zsk_standby) or 'None',
+ self.keyttl and str(self.keyttl) or 'None'))
+
+ def __verify_size(self, key_size, size_range):
+ return (size_range[0] <= key_size <= size_range[1])
+
+ def get_name(self):
+ return self.name
+
+ def constructed(self):
+ return self.is_constructed
+
+ def validate(self):
+ """ Check if the values in the policy make sense
+ :return: True/False if the policy passes validation
+ """
+ if self.ksk_rollperiod and \
+ self.ksk_prepublish is not None and \
+ self.ksk_prepublish > self.ksk_rollperiod:
+ print(self.ksk_rollperiod)
+ return (False,
+ ('KSK pre-publish period (%d) exceeds rollover period %d'
+ % (self.ksk_prepublish, self.ksk_rollperiod)))
+
+ if self.ksk_rollperiod and \
+ self.ksk_postpublish is not None and \
+ self.ksk_postpublish > self.ksk_rollperiod:
+ return (False,
+ ('KSK post-publish period (%d) exceeds rollover period %d'
+ % (self.ksk_postpublish, self.ksk_rollperiod)))
+
+ if self.zsk_rollperiod and \
+ self.zsk_prepublish is not None and \
+ self.zsk_prepublish >= self.zsk_rollperiod:
+ return (False,
+ ('ZSK pre-publish period (%d) exceeds rollover period %d'
+ % (self.zsk_prepublish, self.zsk_rollperiod)))
+
+ if self.zsk_rollperiod and \
+ self.zsk_postpublish is not None and \
+ self.zsk_postpublish >= self.zsk_rollperiod:
+ return (False,
+ ('ZSK post-publish period (%d) exceeds rollover period %d'
+ % (self.zsk_postpublish, self.zsk_rollperiod)))
+
+ if self.ksk_rollperiod and \
+ self.ksk_prepublish and self.ksk_postpublish and \
+ self.ksk_prepublish + self.ksk_postpublish >= self.ksk_rollperiod:
+ return (False,
+ (('KSK pre/post-publish periods (%d/%d) ' +
+ 'combined exceed rollover period %d') %
+ (self.ksk_prepublish,
+ self.ksk_postpublish,
+ self.ksk_rollperiod)))
+
+ if self.zsk_rollperiod and \
+ self.zsk_prepublish and self.zsk_postpublish and \
+ self.zsk_prepublish + self.zsk_postpublish >= self.zsk_rollperiod:
+ return (False,
+ (('ZSK pre/post-publish periods (%d/%d) ' +
+ 'combined exceed rollover period %d') %
+ (self.zsk_prepublish,
+ self.zsk_postpublish,
+ self.zsk_rollperiod)))
+
+ if self.algorithm is not None:
+ # Validate the key size
+ key_sz_range = self.valid_key_sz_per_algo.get(self.algorithm)
+ if key_sz_range is not None:
+ # Verify KSK
+ if not self.__verify_size(self.ksk_keysize, key_sz_range):
+ return False, 'KSK key size %d outside valid range %s' \
+ % (self.ksk_keysize, key_sz_range)
+
+ # Verify ZSK
+ if not self.__verify_size(self.zsk_keysize, key_sz_range):
+ return False, 'ZSK key size %d outside valid range %s' \
+ % (self.zsk_keysize, key_sz_range)
+
+ # Specific check for DSA keys
+ if self.algorithm in ['DSA', 'NSEC3DSA'] and \
+ self.ksk_keysize % 64 != 0:
+ return False, \
+ ('KSK key size %d not divisible by 64 ' +
+ 'as required for DSA') % self.ksk_keysize
+
+ if self.algorithm in ['DSA', 'NSEC3DSA'] and \
+ self.zsk_keysize % 64 != 0:
+ return False, \
+ ('ZSK key size %d not divisible by 64 ' +
+ 'as required for DSA') % self.zsk_keysize
+
+ if self.algorithm in ['ECCGOST', \
+ 'ECDSAP256SHA256', \
+ 'ECDSAP384SHA384', \
+ 'ED25519', \
+ 'ED448']:
+ self.ksk_keysize = None
+ self.zsk_keysize = None
+
+ return True, ''
+
+############################################################################
+# dnssec_policy:
+# This class reads a dnssec.policy file and creates a dictionary of
+# DNSSEC policy rules from which a policy for a specific zone can
+# be generated.
+############################################################################
+class PolicyException(Exception):
+ pass
+
+class dnssec_policy:
+ alg_policy = {}
+ named_policy = {}
+ zone_policy = {}
+ current = None
+ filename = None
+ initial = True
+
+ def __init__(self, filename=None, **kwargs):
+ self.plex = PolicyLex()
+ self.tokens = self.plex.tokens
+ if 'debug' not in kwargs:
+ kwargs['debug'] = False
+ if 'write_tables' not in kwargs:
+ kwargs['write_tables'] = False
+ self.parser = yacc.yacc(module=self, **kwargs)
+
+ # set defaults
+ self.setup('''policy global { algorithm rsasha256;
+ key-size ksk 2048;
+ key-size zsk 2048;
+ roll-period ksk 0;
+ roll-period zsk 1y;
+ pre-publish ksk 1mo;
+ pre-publish zsk 1mo;
+ post-publish ksk 1mo;
+ post-publish zsk 1mo;
+ standby ksk 0;
+ standby zsk 0;
+ keyttl 1h;
+ coverage 6mo; };
+ policy default { policy global; };''')
+
+ p = Policy()
+ p.algorithm = None
+ p.is_alg = True
+ p.ksk_keysize = 2048;
+ p.zsk_keysize = 2048;
+
+ # set default algorithm policies
+ # these need a lower default key size:
+ self.alg_policy['DSA'] = copy(p)
+ self.alg_policy['DSA'].algorithm = "DSA"
+ self.alg_policy['DSA'].name = "DSA"
+ self.alg_policy['DSA'].ksk_keysize = 1024;
+
+ self.alg_policy['NSEC3DSA'] = copy(p)
+ self.alg_policy['NSEC3DSA'].algorithm = "NSEC3DSA"
+ self.alg_policy['NSEC3DSA'].name = "NSEC3DSA"
+ self.alg_policy['NSEC3DSA'].ksk_keysize = 1024;
+
+ # these can use default settings
+ self.alg_policy['RSAMD5'] = copy(p)
+ self.alg_policy['RSAMD5'].algorithm = "RSAMD5"
+ self.alg_policy['RSAMD5'].name = "RSAMD5"
+
+ self.alg_policy['RSASHA1'] = copy(p)
+ self.alg_policy['RSASHA1'].algorithm = "RSASHA1"
+ self.alg_policy['RSASHA1'].name = "RSASHA1"
+
+ self.alg_policy['NSEC3RSASHA1'] = copy(p)
+ self.alg_policy['NSEC3RSASHA1'].algorithm = "NSEC3RSASHA1"
+ self.alg_policy['NSEC3RSASHA1'].name = "NSEC3RSASHA1"
+
+ self.alg_policy['RSASHA256'] = copy(p)
+ self.alg_policy['RSASHA256'].algorithm = "RSASHA256"
+ self.alg_policy['RSASHA256'].name = "RSASHA256"
+
+ self.alg_policy['RSASHA512'] = copy(p)
+ self.alg_policy['RSASHA512'].algorithm = "RSASHA512"
+ self.alg_policy['RSASHA512'].name = "RSASHA512"
+
+ self.alg_policy['ECCGOST'] = copy(p)
+ self.alg_policy['ECCGOST'].algorithm = "ECCGOST"
+ self.alg_policy['ECCGOST'].name = "ECCGOST"
+
+ self.alg_policy['ECDSAP256SHA256'] = copy(p)
+ self.alg_policy['ECDSAP256SHA256'].algorithm = "ECDSAP256SHA256"
+ self.alg_policy['ECDSAP256SHA256'].name = "ECDSAP256SHA256"
+ self.alg_policy['ECDSAP256SHA256'].ksk_keysize = None;
+ self.alg_policy['ECDSAP256SHA256'].zsk_keysize = None;
+
+ self.alg_policy['ECDSAP384SHA384'] = copy(p)
+ self.alg_policy['ECDSAP384SHA384'].algorithm = "ECDSAP384SHA384"
+ self.alg_policy['ECDSAP384SHA384'].name = "ECDSAP384SHA384"
+ self.alg_policy['ECDSAP384SHA384'].ksk_keysize = None;
+ self.alg_policy['ECDSAP384SHA384'].zsk_keysize = None;
+
+ self.alg_policy['ED25519'] = copy(p)
+ self.alg_policy['ED25519'].algorithm = "ED25519"
+ self.alg_policy['ED25519'].name = "ED25519"
+ self.alg_policy['ED25519'].ksk_keysize = None;
+ self.alg_policy['ED25519'].zsk_keysize = None;
+
+ self.alg_policy['ED448'] = copy(p)
+ self.alg_policy['ED448'].algorithm = "ED448"
+ self.alg_policy['ED448'].name = "ED448"
+ self.alg_policy['ED448'].ksk_keysize = None;
+ self.alg_policy['ED448'].zsk_keysize = None;
+
+ if filename:
+ self.load(filename)
+
+ def load(self, filename):
+ self.filename = filename
+ self.initial = True
+ with open(filename) as f:
+ text = f.read()
+ self.plex.lexer.lineno = 0
+ self.parser.parse(text)
+
+ self.filename = None
+
+ def setup(self, text):
+ self.initial = True
+ self.plex.lexer.lineno = 0
+ self.parser.parse(text)
+
+ def policy(self, zone, **kwargs):
+ z = zone.lower()
+ p = None
+
+ if z in self.zone_policy:
+ p = self.zone_policy[z]
+
+ if p is None:
+ p = copy(self.named_policy['default'])
+ p.name = zone
+ p.is_constructed = True
+
+ if p.algorithm is None:
+ parent = p.parent or self.named_policy['default']
+ while parent and not parent.algorithm:
+ parent = parent.parent
+ p.algorithm = parent and parent.algorithm or None
+
+ if p.algorithm in self.alg_policy:
+ ap = self.alg_policy[p.algorithm]
+ else:
+ raise PolicyException('algorithm not found')
+
+ if p.directory is None:
+ parent = p.parent or self.named_policy['default']
+ while parent is not None and not parent.directory:
+ parent = parent.parent
+ p.directory = parent and parent.directory
+
+ if p.coverage is None:
+ parent = p.parent or self.named_policy['default']
+ while parent and not parent.coverage:
+ parent = parent.parent
+ p.coverage = parent and parent.coverage or ap.coverage
+
+ if p.ksk_keysize is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.ksk_keysize:
+ parent = parent.parent
+ p.ksk_keysize = parent and parent.ksk_keysize or ap.ksk_keysize
+
+ if p.zsk_keysize is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.zsk_keysize:
+ parent = parent.parent
+ p.zsk_keysize = parent and parent.zsk_keysize or ap.zsk_keysize
+
+ if p.ksk_rollperiod is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.ksk_rollperiod:
+ parent = parent.parent
+ p.ksk_rollperiod = parent and \
+ parent.ksk_rollperiod or ap.ksk_rollperiod
+
+ if p.zsk_rollperiod is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.zsk_rollperiod:
+ parent = parent.parent
+ p.zsk_rollperiod = parent and \
+ parent.zsk_rollperiod or ap.zsk_rollperiod
+
+ if p.ksk_prepublish is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.ksk_prepublish:
+ parent = parent.parent
+ p.ksk_prepublish = parent and \
+ parent.ksk_prepublish or ap.ksk_prepublish
+
+ if p.zsk_prepublish is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.zsk_prepublish:
+ parent = parent.parent
+ p.zsk_prepublish = parent and \
+ parent.zsk_prepublish or ap.zsk_prepublish
+
+ if p.ksk_postpublish is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.ksk_postpublish:
+ parent = parent.parent
+ p.ksk_postpublish = parent and \
+ parent.ksk_postpublish or ap.ksk_postpublish
+
+ if p.zsk_postpublish is None:
+ parent = p.parent or self.named_policy['default']
+ while parent.parent and not parent.zsk_postpublish:
+ parent = parent.parent
+ p.zsk_postpublish = parent and \
+ parent.zsk_postpublish or ap.zsk_postpublish
+
+ if p.keyttl is None:
+ parent = p.parent or self.named_policy['default']
+ while parent is not None and not parent.keyttl:
+ parent = parent.parent
+ p.keyttl = parent and parent.keyttl
+
+ if 'novalidate' not in kwargs or not kwargs['novalidate']:
+ (valid, msg) = p.validate()
+ if not valid:
+ raise PolicyException(msg)
+ return None
+
+ return p
+
+
+ def p_policylist(self, p):
+ '''policylist : init policy
+ | policylist policy'''
+ pass
+
+ def p_init(self, p):
+ "init :"
+ self.initial = False
+
+ def p_policy(self, p):
+ '''policy : alg_policy
+ | zone_policy
+ | named_policy'''
+ pass
+
+ def p_name(self, p):
+ '''name : STR
+ | KEYTYPE
+ | DATESUFFIX'''
+ p[0] = p[1]
+ pass
+
+ def p_domain(self, p):
+ '''domain : STR
+ | QSTRING
+ | KEYTYPE
+ | DATESUFFIX'''
+ p[0] = p[1].strip()
+ if not re.match(r'^[\w.-][\w.-]*$', p[0]):
+ raise PolicyException('invalid domain')
+ pass
+
+ def p_new_policy(self, p):
+ "new_policy :"
+ self.current = Policy()
+
+ def p_alg_policy(self, p):
+ "alg_policy : ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMI"
+ self.current.name = p[2]
+ self.current.is_alg = True
+ self.alg_policy[p[2]] = self.current
+ pass
+
+ def p_zone_policy(self, p):
+ "zone_policy : ZONE domain new_policy policy_option_group SEMI"
+ self.current.name = p[2].rstrip('.')
+ self.current.is_zone = True
+ self.zone_policy[p[2].rstrip('.').lower()] = self.current
+ pass
+
+ def p_named_policy(self, p):
+ "named_policy : POLICY name new_policy policy_option_group SEMI"
+ self.current.name = p[2]
+ self.named_policy[p[2].lower()] = self.current
+ pass
+
+ def p_duration_1(self, p):
+ "duration : NUMBER"
+ p[0] = p[1]
+ pass
+
+ def p_duration_2(self, p):
+ "duration : NONE"
+ p[0] = None
+ pass
+
+ def p_duration_3(self, p):
+ "duration : NUMBER DATESUFFIX"
+ if p[2] == "y":
+ p[0] = p[1] * 31536000 # year
+ elif p[2] == "mo":
+ p[0] = p[1] * 2592000 # month
+ elif p[2] == "w":
+ p[0] = p[1] * 604800 # week
+ elif p[2] == "d":
+ p[0] = p[1] * 86400 # day
+ elif p[2] == "h":
+ p[0] = p[1] * 3600 # hour
+ elif p[2] == "mi":
+ p[0] = p[1] * 60 # minute
+ elif p[2] == "s":
+ p[0] = p[1] # second
+ else:
+ raise PolicyException('invalid duration')
+
+ def p_policy_option_group(self, p):
+ "policy_option_group : LBRACE policy_option_list RBRACE"
+ pass
+
+ def p_policy_option_list(self, p):
+ '''policy_option_list : policy_option SEMI
+ | policy_option_list policy_option SEMI'''
+ pass
+
+ def p_policy_option(self, p):
+ '''policy_option : parent_option
+ | directory_option
+ | coverage_option
+ | rollperiod_option
+ | prepublish_option
+ | postpublish_option
+ | keysize_option
+ | algorithm_option
+ | keyttl_option
+ | standby_option'''
+ pass
+
+ def p_alg_option_group(self, p):
+ "alg_option_group : LBRACE alg_option_list RBRACE"
+ pass
+
+ def p_alg_option_list(self, p):
+ '''alg_option_list : alg_option SEMI
+ | alg_option_list alg_option SEMI'''
+ pass
+
+ def p_alg_option(self, p):
+ '''alg_option : coverage_option
+ | rollperiod_option
+ | prepublish_option
+ | postpublish_option
+ | keyttl_option
+ | keysize_option
+ | standby_option'''
+ pass
+
+ def p_parent_option(self, p):
+ "parent_option : POLICY name"
+ self.current.parent = self.named_policy[p[2].lower()]
+
+ def p_directory_option(self, p):
+ "directory_option : DIRECTORY QSTRING"
+ self.current.directory = p[2]
+
+ def p_coverage_option(self, p):
+ "coverage_option : COVERAGE duration"
+ self.current.coverage = p[2]
+
+ def p_rollperiod_option(self, p):
+ "rollperiod_option : ROLL_PERIOD KEYTYPE duration"
+ if p[2] == "KSK":
+ self.current.ksk_rollperiod = p[3]
+ else:
+ self.current.zsk_rollperiod = p[3]
+
+ def p_prepublish_option(self, p):
+ "prepublish_option : PRE_PUBLISH KEYTYPE duration"
+ if p[2] == "KSK":
+ self.current.ksk_prepublish = p[3]
+ else:
+ self.current.zsk_prepublish = p[3]
+
+ def p_postpublish_option(self, p):
+ "postpublish_option : POST_PUBLISH KEYTYPE duration"
+ if p[2] == "KSK":
+ self.current.ksk_postpublish = p[3]
+ else:
+ self.current.zsk_postpublish = p[3]
+
+ def p_keysize_option(self, p):
+ "keysize_option : KEY_SIZE KEYTYPE NUMBER"
+ if p[2] == "KSK":
+ self.current.ksk_keysize = p[3]
+ else:
+ self.current.zsk_keysize = p[3]
+
+ def p_standby_option(self, p):
+ "standby_option : STANDBY KEYTYPE NUMBER"
+ if p[2] == "KSK":
+ self.current.ksk_standby = p[3]
+ else:
+ self.current.zsk_standby = p[3]
+
+ def p_keyttl_option(self, p):
+ "keyttl_option : KEYTTL duration"
+ self.current.keyttl = p[2]
+
+ def p_algorithm_option(self, p):
+ "algorithm_option : ALGORITHM ALGNAME"
+ self.current.algorithm = p[2]
+
+ def p_error(self, p):
+ if p:
+ print("%s%s%d:syntax error near '%s'" %
+ (self.filename or "", ":" if self.filename else "",
+ p.lineno, p.value))
+ else:
+ if not self.initial:
+ raise PolicyException("%s%s%d:unexpected end of input" %
+ (self.filename or "", ":" if self.filename else "",
+ p and p.lineno or 0))
+
+if __name__ == "__main__":
+ import sys
+ if sys.argv[1] == "lex":
+ file = open(sys.argv[2])
+ text = file.read()
+ file.close()
+ plex = PolicyLex(debug=1)
+ plex.test(text)
+ elif sys.argv[1] == "parse":
+ try:
+ pp = dnssec_policy(sys.argv[2], write_tables=True, debug=True)
+ print(pp.named_policy['default'])
+ print(pp.policy("nonexistent.zone"))
+ except Exception as e:
+ print(e.args[0])
diff --git a/bin/python/isc/rndc.py.in b/bin/python/isc/rndc.py.in
new file mode 100644
index 0000000..e1a3e77
--- /dev/null
+++ b/bin/python/isc/rndc.py.in
@@ -0,0 +1,188 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+############################################################################
+# rndc.py
+# This module implements the RNDC control protocol.
+############################################################################
+
+from collections import OrderedDict
+import time
+import struct
+import hashlib
+import hmac
+import base64
+import random
+import socket
+
+
+class rndc(object):
+ """RNDC protocol client library"""
+ __algos = {'md5': 157,
+ 'sha1': 161,
+ 'sha224': 162,
+ 'sha256': 163,
+ 'sha384': 164,
+ 'sha512': 165}
+
+ def __init__(self, host, algo, secret):
+ """Creates a persistent connection to RNDC and logs in
+ host - (ip, port) tuple
+ algo - HMAC algorithm: one of md5, sha1, sha224, sha256, sha384, sha512
+ (with optional prefix 'hmac-')
+ secret - HMAC secret, base64 encoded"""
+ self.host = host
+ algo = algo.lower()
+ if algo.startswith('hmac-'):
+ algo = algo[5:]
+ self.algo = algo
+ self.hlalgo = getattr(hashlib, algo)
+ self.secret = base64.b64decode(secret)
+ self.ser = random.randint(0, 1 << 24)
+ self.nonce = None
+ self.__connect_login()
+
+ def call(self, cmd):
+ """Call a RNDC command, all parsing is done on the server side
+ cmd - a complete string with a command (eg 'reload zone example.com')
+ """
+ return dict(self.__command(type=cmd)['_data'])
+
+ def __serialize_dict(self, data, ignore_auth=False):
+ rv = bytearray()
+ for k, v in data.items():
+ if ignore_auth and k == '_auth':
+ continue
+ rv += struct.pack('B', len(k)) + k.encode('ascii')
+ if type(v) == str:
+ rv += struct.pack('>BI', 1, len(v)) + v.encode('ascii')
+ elif type(v) == bytes:
+ rv += struct.pack('>BI', 1, len(v)) + v
+ elif type(v) == bytearray:
+ rv += struct.pack('>BI', 1, len(v)) + v
+ elif type(v) == OrderedDict:
+ sd = self.__serialize_dict(v)
+ rv += struct.pack('>BI', 2, len(sd)) + sd
+ else:
+ raise NotImplementedError('Cannot serialize element of type %s'
+ % type(v))
+ return rv
+
+ def __prep_message(self, *args, **kwargs):
+ self.ser += 1
+ now = int(time.time())
+ data = OrderedDict(*args, **kwargs)
+
+ d = OrderedDict()
+ d['_auth'] = OrderedDict()
+ d['_ctrl'] = OrderedDict()
+ d['_ctrl']['_ser'] = str(self.ser)
+ d['_ctrl']['_tim'] = str(now)
+ d['_ctrl']['_exp'] = str(now+60)
+ if self.nonce is not None:
+ d['_ctrl']['_nonce'] = self.nonce
+ d['_data'] = data
+
+ msg = self.__serialize_dict(d, ignore_auth=True)
+ hash = hmac.new(self.secret, msg, self.hlalgo).digest()
+ bhash = base64.b64encode(hash)
+ if self.algo == 'md5':
+ d['_auth']['hmd5'] = struct.pack('22s', bhash)
+ else:
+ d['_auth']['hsha'] = bytearray(struct.pack('B88s',
+ self.__algos[self.algo], bhash))
+ msg = self.__serialize_dict(d)
+ msg = struct.pack('>II', len(msg) + 4, 1) + msg
+ return msg
+
+ def __verify_msg(self, msg):
+ if self.nonce is not None and msg['_ctrl']['_nonce'] != self.nonce:
+ return False
+ if self.algo == 'md5':
+ bhash = msg['_auth']['hmd5']
+ else:
+ bhash = msg['_auth']['hsha'][1:]
+ if type(bhash) == bytes:
+ bhash = bhash.decode('ascii')
+ bhash += '=' * (4 - (len(bhash) % 4))
+ remote_hash = base64.b64decode(bhash)
+ my_msg = self.__serialize_dict(msg, ignore_auth=True)
+ my_hash = hmac.new(self.secret, my_msg, self.hlalgo).digest()
+ return (my_hash == remote_hash)
+
+ def __command(self, *args, **kwargs):
+ msg = self.__prep_message(*args, **kwargs)
+ sent = self.socket.send(msg)
+ if sent != len(msg):
+ raise IOError("Cannot send the message")
+
+ header = self.socket.recv(8)
+ if len(header) != 8:
+ # What should we throw here? Bad auth can cause this...
+ raise IOError("Can't read response header")
+
+ length, version = struct.unpack('>II', header)
+ if version != 1:
+ raise NotImplementedError('Wrong message version %d' % version)
+
+ # it includes the header
+ length -= 4
+ data = self.socket.recv(length, socket.MSG_WAITALL)
+ if len(data) != length:
+ raise IOError("Can't read response data")
+
+ if type(data) == str:
+ data = bytearray(data)
+ msg = self.__parse_message(data)
+ if not self.__verify_msg(msg):
+ raise IOError("Authentication failure")
+
+ return msg
+
+ def __connect_login(self):
+ self.socket = socket.create_connection(self.host)
+ self.nonce = None
+ msg = self.__command(type='null')
+ self.nonce = msg['_ctrl']['_nonce']
+
+ def __parse_element(self, input):
+ pos = 0
+ labellen = input[pos]
+ pos += 1
+ label = input[pos:pos+labellen].decode('ascii')
+ pos += labellen
+ type = input[pos]
+ pos += 1
+ datalen = struct.unpack('>I', input[pos:pos+4])[0]
+ pos += 4
+ data = input[pos:pos+datalen]
+ pos += datalen
+ rest = input[pos:]
+
+ if type == 1: # raw binary value
+ return label, data, rest
+ elif type == 2: # dictionary
+ d = OrderedDict()
+ while len(data) > 0:
+ ilabel, value, data = self.__parse_element(data)
+ d[ilabel] = value
+ return label, d, rest
+ # TODO type 3 - list
+ else:
+ raise NotImplementedError('Unknown element type %d' % type)
+
+ def __parse_message(self, input):
+ rv = OrderedDict()
+ hdata = None
+ while len(input) > 0:
+ label, value, input = self.__parse_element(input)
+ rv[label] = value
+ return rv
diff --git a/bin/python/isc/tests/Makefile.in b/bin/python/isc/tests/Makefile.in
new file mode 100644
index 0000000..60b9bd7
--- /dev/null
+++ b/bin/python/isc/tests/Makefile.in
@@ -0,0 +1,31 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+PYTHON = @PYTHON@
+
+PYTESTS = dnskey_test.py policy_test.py
+
+@BIND9_MAKE_RULES@
+
+check test:
+ for test in $(PYTESTS); do \
+ PYTHONPATH=${srcdir}/../.. $(PYTHON) ${srcdir}/$$test; \
+ done
+
+clean distclean::
+ rm -rf *.pyc __pycache__
+
+distclean::
+ rm -f ${PYTESTS}
diff --git a/bin/python/isc/tests/dnskey_test.py.in b/bin/python/isc/tests/dnskey_test.py.in
new file mode 100644
index 0000000..91d5245
--- /dev/null
+++ b/bin/python/isc/tests/dnskey_test.py.in
@@ -0,0 +1,52 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import sys
+import unittest
+sys.path.append('../..')
+from isc import *
+
+kdict = None
+
+
+def getkey():
+ global kdict
+ if not kdict:
+ kd = keydict(path='testdata')
+ for key in kd:
+ return key
+
+
+class DnskeyTest(unittest.TestCase):
+ def test_metdata(self):
+ key = getkey()
+ self.assertEqual(key.created(), 1448055647)
+ self.assertEqual(key.publish(), 1445463714)
+ self.assertEqual(key.activate(), 1448055714)
+ self.assertEqual(key.revoke(), 1479591714)
+ self.assertEqual(key.inactive(), 1511127714)
+ self.assertEqual(key.delete(), 1542663714)
+ self.assertEqual(key.syncpublish(), 1442871714)
+ self.assertEqual(key.syncdelete(), 1448919714)
+
+ def test_fmttime(self):
+ key = getkey()
+ self.assertEqual(key.getfmttime('Created'), '20151120214047')
+ self.assertEqual(key.getfmttime('Publish'), '20151021214154')
+ self.assertEqual(key.getfmttime('Activate'), '20151120214154')
+ self.assertEqual(key.getfmttime('Revoke'), '20161119214154')
+ self.assertEqual(key.getfmttime('Inactive'), '20171119214154')
+ self.assertEqual(key.getfmttime('Delete'), '20181119214154')
+ self.assertEqual(key.getfmttime('SyncPublish'), '20150921214154')
+ self.assertEqual(key.getfmttime('SyncDelete'), '20151130214154')
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/bin/python/isc/tests/policy_test.py.in b/bin/python/isc/tests/policy_test.py.in
new file mode 100644
index 0000000..b09c62f
--- /dev/null
+++ b/bin/python/isc/tests/policy_test.py.in
@@ -0,0 +1,92 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import sys
+import unittest
+sys.path.append('../..')
+from isc import *
+
+
+class PolicyTest(unittest.TestCase):
+ def test_keysize(self):
+ pol = policy.dnssec_policy()
+ pol.load('test-policies/01-keysize.pol')
+
+ p = pol.policy('good_rsa.test', novalidate=True)
+ self.assertEqual(p.get_name(), "good_rsa.test")
+ self.assertEqual(p.constructed(), False)
+ self.assertEqual(p.validate(), (True, ""))
+
+ p = pol.policy('good_dsa.test', novalidate=True)
+ self.assertEqual(p.get_name(), "good_dsa.test")
+ self.assertEqual(p.constructed(), False)
+ self.assertEqual(p.validate(), (True, ""))
+
+ p = pol.policy('bad_dsa.test', novalidate=True)
+ self.assertEqual(p.validate(),
+ (False, 'ZSK key size 769 not divisible by 64 as required for DSA'))
+
+ def test_prepublish(self):
+ pol = policy.dnssec_policy()
+ pol.load('test-policies/02-prepublish.pol')
+ p = pol.policy('good_prepublish.test', novalidate=True)
+ self.assertEqual(p.validate(), (True, ""))
+
+ p = pol.policy('bad_prepublish.test', novalidate=True)
+ self.assertEqual(p.validate(),
+ (False, 'KSK pre/post-publish periods '
+ '(10368000/5184000) combined exceed '
+ 'rollover period 10368000'))
+
+ def test_postpublish(self):
+ pol = policy.dnssec_policy()
+ pol.load('test-policies/03-postpublish.pol')
+
+ p = pol.policy('good_postpublish.test', novalidate=True)
+ self.assertEqual(p.validate(), (True, ""))
+
+ p = pol.policy('bad_postpublish.test', novalidate=True)
+ self.assertEqual(p.validate(),
+ (False, 'KSK pre/post-publish periods '
+ '(10368000/5184000) combined exceed '
+ 'rollover period 10368000'))
+
+ def test_combined_pre_post(self):
+ pol = policy.dnssec_policy()
+ pol.load('test-policies/04-combined-pre-post.pol')
+
+ p = pol.policy('good_combined_pre_post_ksk.test', novalidate=True)
+ self.assertEqual(p.validate(), (True, ""))
+
+ p = pol.policy('bad_combined_pre_post_ksk.test', novalidate=True)
+ self.assertEqual(p.validate(),
+ (False, 'KSK pre/post-publish periods '
+ '(5184000/5184000) combined exceed '
+ 'rollover period 10368000'))
+
+ p = pol.policy('good_combined_pre_post_zsk.test', novalidate=True)
+ self.assertEqual(p.validate(),
+ (True, ""))
+ p = pol.policy('bad_combined_pre_post_zsk.test', novalidate=True)
+ self.assertEqual(p.validate(),
+ (False, 'ZSK pre/post-publish periods '
+ '(5184000/5184000) combined exceed '
+ 'rollover period 7776000'))
+
+ def test_numeric_zone(self):
+ pol = policy.dnssec_policy()
+ pol.load('test-policies/05-numeric-zone.pol')
+
+ p = pol.policy('99example.test', novalidate=True)
+ self.assertEqual(p.validate(), (True, ""))
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/bin/python/isc/tests/test-policies/01-keysize.pol b/bin/python/isc/tests/test-policies/01-keysize.pol
new file mode 100644
index 0000000..8b62c5f
--- /dev/null
+++ b/bin/python/isc/tests/test-policies/01-keysize.pol
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+policy keysize_rsa {
+ algorithm rsasha1;
+ coverage 1y;
+ roll-period zsk 3mo;
+ pre-publish zsk 2w;
+ post-publish zsk 2w;
+ roll-period ksk 1y;
+ pre-publish ksk 1mo;
+ post-publish ksk 2mo;
+ keyttl 1h;
+ key-size ksk 2048;
+ key-size zsk 1024;
+};
+
+policy keysize_dsa {
+ algorithm dsa;
+ coverage 1y;
+ key-size ksk 2048;
+ key-size zsk 1024;
+};
+
+zone good_rsa.test {
+ policy keysize_rsa;
+};
+
+zone bad_rsa.test {
+ policy keysize_rsa;
+ key-size ksk 511;
+};
+
+zone good_dsa.test {
+ policy keysize_dsa;
+ key-size ksk 1024;
+ key-size zsk 768;
+};
+
+zone bad_dsa.test {
+ policy keysize_dsa;
+ key-size ksk 1024;
+ key-size zsk 769;
+};
diff --git a/bin/python/isc/tests/test-policies/02-prepublish.pol b/bin/python/isc/tests/test-policies/02-prepublish.pol
new file mode 100644
index 0000000..bd35386
--- /dev/null
+++ b/bin/python/isc/tests/test-policies/02-prepublish.pol
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+policy prepublish_rsa {
+ algorithm rsasha1;
+ coverage 1y;
+ roll-period zsk 3mo;
+ pre-publish zsk 2w;
+ post-publish zsk 2w;
+ roll-period ksk 1y;
+ pre-publish ksk 1mo;
+ post-publish ksk 2mo;
+ keyttl 1h;
+ key-size ksk 2048;
+ key-size zsk 1024;
+};
+
+// Policy that defines a pre-publish period lower than the rollover period
+zone good_prepublish.test {
+ policy prepublish_rsa;
+ coverage 6mo;
+ roll-period ksk 4mo;
+ pre-publish ksk 1mo;
+};
+
+// Policy that defines a pre-publish period equal to the rollover period
+zone bad_prepublish.test {
+ policy prepublish_rsa;
+ coverage 6mo;
+ roll-period ksk 4mo;
+ pre-publish ksk 4mo;
+};
+
+
diff --git a/bin/python/isc/tests/test-policies/03-postpublish.pol b/bin/python/isc/tests/test-policies/03-postpublish.pol
new file mode 100644
index 0000000..4d4a8ef
--- /dev/null
+++ b/bin/python/isc/tests/test-policies/03-postpublish.pol
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+policy postpublish_rsa {
+ algorithm rsasha1;
+ coverage 1y;
+ roll-period zsk 3mo;
+ pre-publish zsk 2w;
+ post-publish zsk 2w;
+ roll-period ksk 1y;
+ pre-publish ksk 1mo;
+ post-publish ksk 2mo;
+ keyttl 1h;
+ key-size ksk 2048;
+ key-size zsk 1024;
+};
+
+// Policy that defines a post-publish period lower than the rollover period
+zone good_postpublish.test {
+ policy postpublish_rsa;
+ coverage 6mo;
+ roll-period ksk 4mo;
+ pre-publish ksk 1mo;
+};
+
+// Policy that defines a post-publish period equal to the rollover period
+zone bad_postpublish.test {
+ policy postpublish_rsa;
+ coverage 6mo;
+ roll-period ksk 4mo;
+ pre-publish ksk 4mo;
+};
+
+
diff --git a/bin/python/isc/tests/test-policies/04-combined-pre-post.pol b/bin/python/isc/tests/test-policies/04-combined-pre-post.pol
new file mode 100644
index 0000000..d612d81
--- /dev/null
+++ b/bin/python/isc/tests/test-policies/04-combined-pre-post.pol
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+policy combined_pre_post_rsa {
+ algorithm rsasha1;
+ coverage 1y;
+ roll-period zsk 3mo;
+ pre-publish zsk 2w;
+ post-publish zsk 2w;
+ roll-period ksk 1y;
+ pre-publish ksk 1mo;
+ post-publish ksk 2mo;
+ keyttl 1h;
+ key-size ksk 2048;
+ key-size zsk 1024;
+};
+
+// Policy that defines a combined pre-publish and post-publish period lower
+// than the rollover period
+zone good_combined_pre_post_ksk.test {
+ policy combined_pre_post_rsa;
+ coverage 6mo;
+ roll-period ksk 4mo;
+ pre-publish ksk 1mo;
+ post-publish ksk 1mo;
+};
+
+// Policy that defines a combined pre-publish and post-publish period higher
+// than the rollover period
+zone bad_combined_pre_post_ksk.test {
+ policy combined_pre_post_rsa;
+ coverage 6mo;
+ roll-period ksk 4mo;
+ pre-publish ksk 2mo;
+ post-publish ksk 2mo;
+};
+
+// Policy that defines a combined pre-publish and post-publish period lower
+// than the rollover period
+zone good_combined_pre_post_zsk.test {
+ policy combined_pre_post_rsa;
+ coverage 1y;
+ roll-period zsk 3mo;
+ pre-publish zsk 1mo;
+ post-publish zsk 1mo;
+};
+
+// Policy that defines a combined pre-publish and post-publish period higher
+// than the rollover period
+zone bad_combined_pre_post_zsk.test {
+ policy combined_pre_post_rsa;
+ coverage 1y;
+ roll-period zsk 3mo;
+ pre-publish zsk 2mo;
+ post-publish zsk 2mo;
+};
+
+
diff --git a/bin/python/isc/tests/test-policies/05-numeric-zone.pol b/bin/python/isc/tests/test-policies/05-numeric-zone.pol
new file mode 100644
index 0000000..1db8c08
--- /dev/null
+++ b/bin/python/isc/tests/test-policies/05-numeric-zone.pol
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// Zone policy that uses a numeric name
+zone "99example.test" {
+ coverage 6mo;
+};
diff --git a/bin/python/isc/tests/testdata/Kexample.com.+007+35529.key b/bin/python/isc/tests/testdata/Kexample.com.+007+35529.key
new file mode 100644
index 0000000..c5afbe2
--- /dev/null
+++ b/bin/python/isc/tests/testdata/Kexample.com.+007+35529.key
@@ -0,0 +1,8 @@
+; This is a key-signing key, keyid 35529, for example.com.
+; Created: 20151120214047 (Fri Nov 20 13:40:47 2015)
+; Publish: 20151021214154 (Wed Oct 21 14:41:54 2015)
+; Activate: 20151120214154 (Fri Nov 20 13:41:54 2015)
+; Revoke: 20161119214154 (Sat Nov 19 13:41:54 2016)
+; Inactive: 20171119214154 (Sun Nov 19 13:41:54 2017)
+; Delete: 20181119214154 (Mon Nov 19 13:41:54 2018)
+example.com. IN DNSKEY 257 3 7 AwEAAbbJK96tY8d4sF6RLxh9SVIhho5s2ZhrcijT5j1SNLECen7QLutj VJPEiG8UgBLaJSGkxPDxOygYv4hwh4JXBSj89o9rNabAJtCa9XzIXSpt /cfiCfvqmcOZb9nepmDCXsC7gn/gbae/4Y5ym9XOiCp8lu+tlFWgRiJ+ kxDGN48rRPrGfpq+SfwM9NUtftVa7B0EFVzDkADKedRj0SSGYOqH+WYH CnWjhPFmgJoAw3/m4slTHW1l+mDwFvsCMjXopg4JV0CNnTybnOmyuIwO LWRhB3q8ze24sYBU1fpE9VAMxZ++4Kqh/2MZFeDAs7iPPKSmI3wkRCW5 pkwDLO5lJ9c=
diff --git a/bin/python/isc/tests/testdata/Kexample.com.+007+35529.private b/bin/python/isc/tests/testdata/Kexample.com.+007+35529.private
new file mode 100644
index 0000000..af22c6a
--- /dev/null
+++ b/bin/python/isc/tests/testdata/Kexample.com.+007+35529.private
@@ -0,0 +1,18 @@
+Private-key-format: v1.3
+Algorithm: 7 (NSEC3RSASHA1)
+Modulus: tskr3q1jx3iwXpEvGH1JUiGGjmzZmGtyKNPmPVI0sQJ6ftAu62NUk8SIbxSAEtolIaTE8PE7KBi/iHCHglcFKPz2j2s1psAm0Jr1fMhdKm39x+IJ++qZw5lv2d6mYMJewLuCf+Btp7/hjnKb1c6IKnyW762UVaBGIn6TEMY3jytE+sZ+mr5J/Az01S1+1VrsHQQVXMOQAMp51GPRJIZg6of5ZgcKdaOE8WaAmgDDf+biyVMdbWX6YPAW+wIyNeimDglXQI2dPJuc6bK4jA4tZGEHerzN7bixgFTV+kT1UAzFn77gqqH/YxkV4MCzuI88pKYjfCREJbmmTAMs7mUn1w==
+PublicExponent: AQAB
+PrivateExponent: jfiM6YU1Rd6Y5qrPsK7HP1Ko54DmNbvmzI1hfGmYYZAyQsNCXjQloix5aAW9QGdNhecrzJUhxJAMXFZC+lrKuD5a56R25JDE1Sw21nft3SHXhuQrqw5Z5hIMTWXhRrBR1lMOFnLj2PJxqCmenp+vJYjl1z20RBmbv/keE15SExFRJIJ3G0lI4V0KxprY5rgsT/vID0pS32f7rmXhgEzyWDyuxceTMidBooD5BSeEmSTYa4rvCVZ2vgnzIGSxjYDPJE2rGve2dpvdXQuujRFaf4+/FzjaOgg35rTtUmC9klfB4D6KJIfc1PNUwcH7V0VJ2fFlgZgMYi4W331QORl9sQ==
+Prime1: 479rW3EeoBwHhUKDy5YeyfnMKjhaosrcYhW4resevLzatFrvS/n2KxJnsHoEzmGr2A13naI61RndgVBBOwNDWI3/tQ+aKvcr+V9m4omROV3xYa8s1FsDbEW0Z6G0UheaqRFir8WK98/Lj6Zht1uBXHSPPf91OW0qj+b5gbX7TK8=
+Prime2: zXXlxgIq+Ih6kxsUw4Ith0nd/d2P3d42QYPjxYjsg4xYicPAjva9HltnbBQ2lr4JEG9Yyb8KalSnJUSuvXtn7bGfBzLu8W6omCeVWXQVH4NIu9AjpO16NpMKWGRfiHHbbSYJs1daTZKHC2FEmi18MKX/RauHGGOakFQ/3A/GMVk=
+Exponent1: 0o9UQ1uHNAIWFedUEHJ/jr7LOrGVYnLpZCmu7+S0K0zzatGz8ets44+FnAyDywdUKFDzKSMm/4SFXRwE4vl2VzYZlp2RLG4PEuRYK9OCF6a6F1UsvjxTItQjIbjIDSnTjMINGnMps0lDa1EpgKsyI3eEQ46eI3TBZ//k6D6G0vM=
+Exponent2: d+CYJgXRyJzo17fvT3s+0TbaHWsOq+chROyNEw4m4UIbzpW2XjO8eF/gYgERMLbEVyCAb4XVr+CgfXArfEbqhpciMHMZUyi7mbtOupiuUmqpH1v70Bj3O6xjVtuJmfTEkFSnSEppV+VsgclI26Q6V7Ai1yWTdzl2T0u4zs8tVlE=
+Coefficient: E4EYw76gIChdQDn6+Uh44/xH9Uwmvq3OETR8w/kEZ0xQ8AkTdKFKUp84nlR6gN+ljb2mUxERKrVLwnBsU8EbUlo9UccMbBGkkZ/8MyfGCBb9nUyOFtOxdHY2M0MQadesRptXHt/m30XjdohwmT7qfSIENwtgUOHbwFnn7WPMc/k=
+Created: 20151120214047
+Publish: 20151021214154
+Activate: 20151120214154
+Revoke: 20161119214154
+Inactive: 20171119214154
+Delete: 20181119214154
+SyncPublish: 20150921214154
+SyncDelete: 20151130214154
diff --git a/bin/python/isc/utils.py.in b/bin/python/isc/utils.py.in
new file mode 100644
index 0000000..0241871
--- /dev/null
+++ b/bin/python/isc/utils.py.in
@@ -0,0 +1,71 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import os
+
+# These routines permit platform-independent location of BIND 9 tools
+if os.name == 'nt':
+ import win32con
+ import win32api
+
+
+def prefix(bindir=''):
+ if os.name != 'nt':
+ return os.path.join('@prefix@', bindir)
+
+ hklm = win32con.HKEY_LOCAL_MACHINE
+ bind_subkey = "Software\\ISC\\BIND"
+ sam = win32con.KEY_READ
+ h_key = None
+ key_found = True
+ # can fail if the registry redirected for 32/64 bits
+ try:
+ h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam)
+ except:
+ key_found = False
+ # retry for 32 bit python with 64 bit bind9
+ if not key_found:
+ key_found = True
+ sam64 = sam | win32con.KEY_WOW64_64KEY
+ try:
+ h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam64)
+ except:
+ key_found = False
+ # retry 64 bit python with 32 bit bind9
+ if not key_found:
+ key_found = True
+ sam32 = sam | win32con.KEY_WOW64_32KEY
+ try:
+ h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam32)
+ except:
+ key_found = False
+ if key_found:
+ try:
+ (named_base, _) = win32api.RegQueryValueEx(h_key, "InstallDir")
+ except:
+ key_found = False
+ win32api.RegCloseKey(h_key)
+ if key_found:
+ return os.path.join(named_base, bindir)
+ return os.path.join(win32api.GetSystemDirectory(), bindir)
+
+
+def shellquote(s):
+ if os.name == 'nt':
+ return '"' + s.replace('"', '"\\"') + '"'
+ return "'" + s.replace("'", "'\\''") + "'"
+
+
+version = '@BIND9_VERSION@'
+if os.name != 'nt':
+ sysconfdir = '@expanded_sysconfdir@'
+else:
+ sysconfdir = prefix('etc')
diff --git a/bin/python/setup.py b/bin/python/setup.py
new file mode 100644
index 0000000..c50f6d1
--- /dev/null
+++ b/bin/python/setup.py
@@ -0,0 +1,21 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from distutils.core import setup
+setup(name='isc',
+ version='2.0',
+ description='Python functions to support BIND utilities',
+ url='https://www.isc.org/bind',
+ author='Internet Systems Consortium, Inc',
+ author_email='info@isc.org',
+ license='MPL',
+ requires=['ply'],
+ packages=['isc'])
diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in
new file mode 100644
index 0000000..67c7b7d
--- /dev/null
+++ b/bin/rndc/Makefile.in
@@ -0,0 +1,91 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.49 2009/12/05 23:31:40 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+LIBS = ${ISCLIBS} @LIBS@
+NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@
+
+RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+SRCS= rndc.c
+
+TARGETS = rndc@EXEEXT@
+
+MANPAGES = rndc.8 rndc.conf.5
+
+HTMLPAGES = rndc.html rndc.conf.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+rndc.@O@: rndc.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \
+ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \
+ -c ${srcdir}/rndc.c
+
+rndc@EXEEXT@: rndc.@O@ util.@O@ ${RNDCDEPLIBS}
+ export BASEOBJS="rndc.@O@ util.@O@"; \
+ export LIBS0="${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5
+
+install:: rndc@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc@EXEEXT@ ${DESTDIR}${sbindir}
+ ${INSTALL_DATA} ${srcdir}/rndc.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/rndc.conf.5 ${DESTDIR}${mandir}/man5
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man5/rndc.conf.5
+ rm -f ${DESTDIR}${mandir}/man8/rndc.8
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/rndc@EXEEXT@
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
diff --git a/bin/rndc/include/rndc/os.h b/bin/rndc/include/rndc/os.h
new file mode 100644
index 0000000..6346b2b
--- /dev/null
+++ b/bin/rndc/include/rndc/os.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#ifndef RNDC_OS_H
+#define RNDC_OS_H 1
+
+#include <isc/lang.h>
+#include <stdio.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
+
+#endif
diff --git a/bin/rndc/rndc.8 b/bin/rndc/rndc.8
new file mode 100644
index 0000000..315a1b4
--- /dev/null
+++ b/bin/rndc/rndc.8
@@ -0,0 +1,629 @@
+.\" Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: rndc
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-08-15
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "RNDC" "8" "2014\-08\-15" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+rndc \- name server control utility
+.SH "SYNOPSIS"
+.HP \w'\fBrndc\fR\ 'u
+\fBrndc\fR [\fB\-b\ \fR\fB\fIsource\-address\fR\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-k\ \fR\fB\fIkey\-file\fR\fR] [\fB\-s\ \fR\fB\fIserver\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-q\fR] [\fB\-r\fR] [\fB\-V\fR] [\fB\-y\ \fR\fB\fIkey_id\fR\fR] {command}
+.SH "DESCRIPTION"
+.PP
+\fBrndc\fR
+controls the operation of a name server\&. It supersedes the
+\fBndc\fR
+utility that was provided in old BIND releases\&. If
+\fBrndc\fR
+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\&.
+.PP
+\fBrndc\fR
+communicates with the name server over a TCP connection, sending commands authenticated with digital signatures\&. In the current versions of
+\fBrndc\fR
+and
+\fBnamed\fR, 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\&. This provides TSIG\-style authentication for the command request and the name server\*(Aqs response\&. All commands sent over the channel must be signed by a key_id known to the server\&.
+.PP
+\fBrndc\fR
+reads a configuration file to determine how to contact the name server and decide what algorithm and key it should use\&.
+.SH "OPTIONS"
+.PP
+\-b \fIsource\-address\fR
+.RS 4
+Use
+\fIsource\-address\fR
+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\&.
+.RE
+.PP
+\-c \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+/etc/rndc\&.conf\&.
+.RE
+.PP
+\-k \fIkey\-file\fR
+.RS 4
+Use
+\fIkey\-file\fR
+as the key file instead of the default,
+/etc/rndc\&.key\&. The key in
+/etc/rndc\&.key
+will be used to authenticate commands sent to the server if the
+\fIconfig\-file\fR
+does not exist\&.
+.RE
+.PP
+\-s \fIserver\fR
+.RS 4
+\fIserver\fR
+is the name or address of the server which matches a server statement in the configuration file for
+\fBrndc\fR\&. If no server is supplied on the command line, the host named by the default\-server clause in the options statement of the
+\fBrndc\fR
+configuration file will be used\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Send commands to TCP port
+\fIport\fR
+instead of BIND 9\*(Aqs default control channel port, 953\&.
+.RE
+.PP
+\-q
+.RS 4
+Quiet mode: Message text returned by the server will not be printed except when there is an error\&.
+.RE
+.PP
+\-r
+.RS 4
+Instructs
+\fBrndc\fR
+to print the result code returned by
+\fBnamed\fR
+after executing the requested command (e\&.g\&., ISC_R_SUCCESS, ISC_R_FAILURE, etc)\&.
+.RE
+.PP
+\-V
+.RS 4
+Enable verbose logging\&.
+.RE
+.PP
+\-y \fIkey_id\fR
+.RS 4
+Use the key
+\fIkey_id\fR
+from the configuration file\&.
+\fIkey_id\fR
+must be known by
+\fBnamed\fR
+with the same algorithm and secret string in order for control message validation to succeed\&. If no
+\fIkey_id\fR
+is specified,
+\fBrndc\fR
+will first look for a key clause in the server statement of the server being used, or if no server statement is present for that host, then 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\&. It should therefore not have general read or write access\&.
+.RE
+.SH "COMMANDS"
+.PP
+A list of commands supported by
+\fBrndc\fR
+can be seen by running
+\fBrndc\fR
+without arguments\&.
+.PP
+Currently supported commands are:
+.PP
+\fBaddzone \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR\fB\fIconfiguration\fR\fR\fB \fR
+.RS 4
+Add a zone while the server is running\&. This command requires the
+\fBallow\-new\-zones\fR
+option to be set to
+\fByes\fR\&. The
+\fIconfiguration\fR
+string specified on the command line is the zone configuration text that would ordinarily be placed in
+named\&.conf\&.
+.sp
+The configuration is saved in a file called
+\fIname\fR\&.nzf, where
+\fIname\fR
+is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view\&. When
+\fBnamed\fR
+is restarted, the file will be loaded into the view configuration, so that zones that were added can persist after a restart\&.
+.sp
+This sample
+\fBaddzone\fR
+command would add the zone
+example\&.com
+to the default view:
+.sp
+$\fBrndc addzone example\&.com \*(Aq{ type master; file "example\&.com\&.db"; };\*(Aq\fR
+.sp
+(Note the brackets and semi\-colon around the zone configuration text\&.)
+.sp
+See also
+\fBrndc delzone\fR
+and
+\fBrndc modzone\fR\&.
+.RE
+.PP
+\fBdelzone \fR\fB[\-clean]\fR\fB \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR
+.RS 4
+Delete a zone while the server is running\&.
+.sp
+If the
+\fB\-clean\fR
+argument is specified, the zone\*(Aqs master file (and journal file, if any) will be deleted along with the zone\&. Without the
+\fB\-clean\fR
+option, zone files must be cleaned up by hand\&. (If the zone is of type "slave" or "stub", the files needing to be cleaned up will be reported in the output of the
+\fBrndc delzone\fR
+command\&.)
+.sp
+If the zone was originally added via
+\fBrndc addzone\fR, then it will be removed permanently\&. However, if it was originally configured in
+named\&.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will come back\&. To remove it permanently, it must also be removed from
+named\&.conf
+.sp
+See also
+\fBrndc addzone\fR
+and
+\fBrndc modzone\fR\&.
+.RE
+.PP
+\fBdnstap ( \-reopen | \-roll \fR\fB[\fInumber\fR]\fR\fB )\fR
+.RS 4
+Close and re\-open DNSTAP output files\&.
+\fBrndc dnstap \-reopen\fR
+allows the output file to be renamed externally, so that
+\fBnamed\fR
+can truncate and re\-open it\&.
+\fBrndc dnstap \-roll\fR
+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
+\fInumber\fR
+is specified, then the number of backup log files is limited to that number\&.
+.RE
+.PP
+\fBdumpdb \fR\fB[\-all|\-cache|\-zones|\-adb|\-bad|\-fail]\fR\fB \fR\fB[\fIview \&.\&.\&.\fR]\fR
+.RS 4
+Dump the server\*(Aqs caches (default) and/or zones to the dump file for the specified views\&. If no view is specified, all views are dumped\&. (See the
+\fBdump\-file\fR
+option in the BIND 9 Administrator Reference Manual\&.)
+.RE
+.PP
+\fBflush\fR
+.RS 4
+Flushes the server\*(Aqs cache\&.
+.RE
+.PP
+\fBflushname\fR \fIname\fR [\fIview\fR]
+.RS 4
+Flushes the given name from the view\*(Aqs DNS cache and, if applicable, from the view\*(Aqs nameserver address database, bad server cache and SERVFAIL cache\&.
+.RE
+.PP
+\fBflushtree\fR \fIname\fR [\fIview\fR]
+.RS 4
+Flushes the given name, and all of its subdomains, from the view\*(Aqs DNS cache, address database, bad server cache, and SERVFAIL cache\&.
+.RE
+.PP
+\fBfreeze \fR\fB[\fIzone\fR [\fIclass\fR [\fIview\fR]]]\fR
+.RS 4
+Suspend 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\&. It also causes changes in the journal file to be synced into the master file\&. All dynamic update attempts will be refused while the zone is frozen\&.
+.sp
+See also
+\fBrndc thaw\fR\&.
+.RE
+.PP
+\fBhalt \fR\fB[\-p]\fR
+.RS 4
+Stop the server immediately\&. Recent changes made through dynamic update or IXFR are not saved to the master files, but will be rolled forward from the journal files when the server is restarted\&. If
+\fB\-p\fR
+is specified
+\fBnamed\fR\*(Aqs process id is returned\&. This allows an external process to determine when
+\fBnamed\fR
+had completed halting\&.
+.sp
+See also
+\fBrndc stop\fR\&.
+.RE
+.PP
+\fBloadkeys \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+Fetch all DNSSEC keys for the given zone from the key directory\&. If they are within their publication period, merge them into the zone\*(Aqs DNSKEY RRset\&. Unlike
+\fBrndc sign\fR, however, the zone is not immediately re\-signed by the new keys, but is allowed to incrementally re\-sign over time\&.
+.sp
+This command requires that the
+\fBauto\-dnssec\fR
+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\&.)
+.RE
+.PP
+\fBmanaged\-keys \fR\fB\fI(status | refresh | sync)\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+When run with the "status" keyword, print the current status of the managed\-keys database for the specified view, or for all views if none is specified\&. When run with the "refresh" keyword, force an immediate refresh of all the managed\-keys in the specified view, or all views\&. When run with the "sync" keyword, force an immediate dump of the managed\-keys database to disk (in the file
+managed\-keys\&.bind
+or (\fIviewname\fR\&.mkeys)\&.
+.RE
+.PP
+\fBmodzone \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR\fB\fIconfiguration\fR\fR\fB \fR
+.RS 4
+Modify the configuration of a zone while the server is running\&. This command requires the
+\fBallow\-new\-zones\fR
+option to be set to
+\fByes\fR\&. As with
+\fBaddzone\fR, the
+\fIconfiguration\fR
+string specified on the command line is the zone configuration text that would ordinarily be placed in
+named\&.conf\&.
+.sp
+If the zone was originally added via
+\fBrndc addzone\fR, the configuration changes will be recorded permanently and will still be in effect after the server is restarted or reconfigured\&. However, if it was originally configured in
+named\&.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will revert to its original configuration\&. To make the changes permanent, it must also be modified in
+named\&.conf
+.sp
+See also
+\fBrndc addzone\fR
+and
+\fBrndc delzone\fR\&.
+.RE
+.PP
+\fBnotify \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+Resend NOTIFY messages for the zone\&.
+.RE
+.PP
+\fBnotrace\fR
+.RS 4
+Sets the server\*(Aqs debugging level to 0\&.
+.sp
+See also
+\fBrndc trace\fR\&.
+.RE
+.PP
+\fBnta \fR\fB[( \-class \fIclass\fR | \-dump | \-force | \-remove | \-lifetime \fIduration\fR)]\fR\fB \fR\fB\fIdomain\fR\fR\fB \fR\fB[\fIview\fR]\fR\fB \fR
+.RS 4
+Sets a DNSSEC negative trust anchor (NTA) for
+\fBdomain\fR, with a lifetime of
+\fBduration\fR\&. The default lifetime is configured in
+named\&.conf
+via the
+\fBnta\-lifetime\fR
+option, and defaults to one hour\&. The lifetime cannot exceed one week\&.
+.sp
+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),
+\fBnamed\fR
+will abort the DNSSEC validation process and treat the data as insecure rather than bogus\&. This continues until the NTA\*(Aqs lifetime is elapsed\&.
+.sp
+NTAs persist across restarts of the
+\fBnamed\fR
+server\&. The NTAs for a view are saved in a file called
+\fIname\fR\&.nta, where
+\fIname\fR
+is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view\&.
+.sp
+An existing NTA can be removed by using the
+\fB\-remove\fR
+option\&.
+.sp
+An NTA\*(Aqs lifetime can be specified with the
+\fB\-lifetime\fR
+option\&. TTL\-style suffixes can be used to specify the lifetime in seconds, minutes, or hours\&. If the specified NTA already exists, its lifetime will be updated to the new value\&. Setting
+\fBlifetime\fR
+to zero is equivalent to
+\fB\-remove\fR\&.
+.sp
+If the
+\fB\-dump\fR
+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)\&.
+.sp
+Normally,
+\fBnamed\fR
+will periodically test to see whether data below an NTA can now be validated (see the
+\fBnta\-recheck\fR
+option in the Administrator Reference Manual for details)\&. If data can be validated, then the NTA is regarded as no longer necessary, and will be allowed to expire early\&. The
+\fB\-force\fR
+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\&.
+.sp
+The view class can be specified with
+\fB\-class\fR\&. The default is class
+\fBIN\fR, which is the only class for which DNSSEC is currently supported\&.
+.sp
+All of these options can be shortened, i\&.e\&., to
+\fB\-l\fR,
+\fB\-r\fR,
+\fB\-d\fR,
+\fB\-f\fR, and
+\fB\-c\fR\&.
+.RE
+.PP
+\fBquerylog\fR [ on | off ]
+.RS 4
+Enable or disable query logging\&. (For backward compatibility, this command can also be used without an argument to toggle query logging on and off\&.)
+.sp
+Query logging can also be enabled by explicitly directing the
+\fBqueries\fR\fBcategory\fR
+to a
+\fBchannel\fR
+in the
+\fBlogging\fR
+section of
+named\&.conf
+or by specifying
+\fBquerylog yes;\fR
+in the
+\fBoptions\fR
+section of
+named\&.conf\&.
+.RE
+.PP
+\fBreconfig\fR
+.RS 4
+Reload the configuration file and load new zones, but do not reload existing zone files even if they have changed\&. This is faster than a full
+\fBreload\fR
+when there is a large number of zones because it avoids the need to examine the modification times of the zones files\&.
+.RE
+.PP
+\fBrecursing\fR
+.RS 4
+Dump the list of queries
+\fBnamed\fR
+is currently recursing on, and the list of domains to which iterative queries are currently being sent\&. (The second list includes the number of fetches currently active for the given domain, and how many have been passed or dropped because of the
+\fBfetches\-per\-zone\fR
+option\&.)
+.RE
+.PP
+\fBrefresh \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+Schedule zone maintenance for the given zone\&.
+.RE
+.PP
+\fBreload\fR
+.RS 4
+Reload configuration file and zones\&.
+.RE
+.PP
+\fBreload \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+Reload the given zone\&.
+.RE
+.PP
+\fBretransfer \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+Retransfer the given slave zone from the master server\&.
+.sp
+If the zone is configured to use
+\fBinline\-signing\fR, the signed version of the zone is discarded; after the retransfer of the unsigned version is complete, the signed version will be regenerated with all new signatures\&.
+.RE
+.PP
+\fBscan\fR
+.RS 4
+Scan the list of available network interfaces for changes, without performing a full
+\fBreconfig\fR
+or waiting for the
+\fBinterface\-interval\fR
+timer\&.
+.RE
+.PP
+\fBsecroots \fR\fB[\-]\fR\fB \fR\fB[\fIview \&.\&.\&.\fR]\fR
+.RS 4
+Dump the server\*(Aqs security roots and negative trust anchors for the specified views\&. If no view is specified, all views are dumped\&.
+.sp
+If the first argument is "\-", then the output is returned via the
+\fBrndc\fR
+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
+\fBsecroots\-file\fR
+option in
+named\&.conf\&.
+.sp
+See also
+\fBrndc managed\-keys\fR\&.
+.RE
+.PP
+\fBshowzone \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR
+.RS 4
+Print the configuration of a running zone\&.
+.sp
+See also
+\fBrndc zonestatus\fR\&.
+.RE
+.PP
+\fBsign \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+Fetch all DNSSEC keys for the given zone from the key directory (see the
+\fBkey\-directory\fR
+option in the BIND 9 Administrator Reference Manual)\&. If they are within their publication period, merge them into the zone\*(Aqs DNSKEY RRset\&. If the DNSKEY RRset is changed, then the zone is automatically re\-signed with the new key set\&.
+.sp
+This command requires that the
+\fBauto\-dnssec\fR
+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 Administrator Reference Manual for more details\&.)
+.sp
+See also
+\fBrndc loadkeys\fR\&.
+.RE
+.PP
+\fBsigning \fR\fB[( \-list | \-clear \fIkeyid/algorithm\fR | \-clear all | \-nsec3param ( \fIparameters\fR | none ) | \-serial \fIvalue\fR ) ]\fR\fB \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR
+.RS 4
+List, edit, or remove 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
+\fBsig\-signing\-type\fR\&.
+\fBrndc signing \-list\fR
+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\&.
+.sp
+\fBrndc signing \-clear\fR
+can remove a single key (specified in the same format that
+\fBrndc signing \-list\fR
+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 will be retained\&.
+.sp
+\fBrndc signing \-nsec3param\fR
+sets the NSEC3 parameters for a zone\&. This is the only supported mechanism for using NSEC3 with
+\fBinline\-signing\fR
+zones\&. Parameters are specified in the same format as an NSEC3PARAM resource record: hash algorithm, flags, iterations, and salt, in that order\&.
+.sp
+Currently, the only defined value for hash algorithm is
+1, representing SHA\-1\&. The
+\fBflags\fR
+may be set to
+0
+or
+1, depending on whether you wish to set the opt\-out bit in the NSEC3 chain\&.
+\fBiterations\fR
+defines the number of additional times to apply the algorithm when generating an NSEC3 hash\&. The
+\fBsalt\fR
+is a string of data expressed in hexadecimal, a hyphen (`\-\*(Aq) if no salt is to be used, or the keyword
+auto, which causes
+\fBnamed\fR
+to generate a random 64\-bit salt\&.
+.sp
+So, for example, to create an NSEC3 chain using the SHA\-1 hash algorithm, no opt\-out flag, 10 iterations, and a salt value of "FFFF", use:
+\fBrndc signing \-nsec3param 1 0 10 FFFF \fR\fB\fIzone\fR\fR\&. To set the opt\-out flag, 15 iterations, and no salt, use:
+\fBrndc signing \-nsec3param 1 1 15 \- \fR\fB\fIzone\fR\fR\&.
+.sp
+\fBrndc signing \-nsec3param none\fR
+removes an existing NSEC3 chain and replaces it with NSEC\&.
+.sp
+\fBrndc signing \-serial value\fR
+sets the serial number of the zone to value\&. If the value would cause the serial number to go backwards it will be rejected\&. The primary use is to set the serial on inline signed zones\&.
+.RE
+.PP
+\fBstats\fR
+.RS 4
+Write server statistics to the statistics file\&. (See the
+\fBstatistics\-file\fR
+option in the BIND 9 Administrator Reference Manual\&.)
+.RE
+.PP
+\fBstatus\fR
+.RS 4
+Display status of the server\&. Note that the number of zones includes the internal
+\fBbind/CH\fR
+zone and the default
+\fB\&./IN\fR
+hint zone if there is not an explicit root zone configured\&.
+.RE
+.PP
+\fBstop \fR\fB[\-p]\fR
+.RS 4
+Stop 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
+\fB\-p\fR
+is specified
+\fBnamed\fR\*(Aqs process id is returned\&. This allows an external process to determine when
+\fBnamed\fR
+had completed stopping\&.
+.sp
+See also
+\fBrndc halt\fR\&.
+.RE
+.PP
+\fBsync \fR\fB[\-clean]\fR\fB \fR\fB[\fIzone\fR [\fIclass\fR [\fIview\fR]]]\fR
+.RS 4
+Sync 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\&.
+.RE
+.PP
+\fBthaw \fR\fB[\fIzone\fR [\fIclass\fR [\fIview\fR]]]\fR
+.RS 4
+Enable 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 will no longer be refused\&. If the zone has changed and the
+\fBixfr\-from\-differences\fR
+option is in use, then the journal file will be updated to reflect changes in the zone\&. Otherwise, if the zone has changed, any existing journal file will be removed\&.
+.sp
+See also
+\fBrndc freeze\fR\&.
+.RE
+.PP
+\fBtrace\fR
+.RS 4
+Increment the servers debugging level by one\&.
+.RE
+.PP
+\fBtrace \fR\fB\fIlevel\fR\fR
+.RS 4
+Sets the server\*(Aqs debugging level to an explicit value\&.
+.sp
+See also
+\fBrndc notrace\fR\&.
+.RE
+.PP
+\fBtsig\-delete\fR \fIkeyname\fR [\fIview\fR]
+.RS 4
+Delete a given TKEY\-negotiated key from the server\&. (This does not apply to statically configured TSIG keys\&.)
+.RE
+.PP
+\fBtsig\-list\fR
+.RS 4
+List the names of all TSIG keys currently configured for use by
+\fBnamed\fR
+in each view\&. The list both statically configured keys and dynamic TKEY\-negotiated keys\&.
+.RE
+.PP
+\fBvalidation ( on | off | status ) \fR\fB[\fIview \&.\&.\&.\fR]\fR\fB \fR
+.RS 4
+Enable, disable, or check the current status of DNSSEC validation\&. Note
+\fBdnssec\-enable\fR
+also needs to be set to
+\fByes\fR
+or
+\fBauto\fR
+to be effective\&. It defaults to enabled\&.
+.RE
+.PP
+\fBzonestatus \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR
+.RS 4
+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\&.
+.sp
+See also
+\fBrndc showzone\fR\&.
+.RE
+.SH "LIMITATIONS"
+.PP
+There is currently no way to provide the shared secret for a
+\fBkey_id\fR
+without using the configuration file\&.
+.PP
+Several error messages could be clearer\&.
+.SH "SEE ALSO"
+.PP
+\fBrndc.conf\fR(5),
+\fBrndc-confgen\fR(8),
+\fBnamed\fR(8),
+\fBnamed.conf\fR(5),
+\fBndc\fR(8),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000, 2001, 2004, 2005, 2007, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c
new file mode 100644
index 0000000..9eb0ce0
--- /dev/null
+++ b/bin/rndc/rndc.c
@@ -0,0 +1,984 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/net.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/socket.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <pk11/site.h>
+
+#include <isccfg/namedconf.h>
+
+#include <isccc/alist.h>
+#include <isccc/base64.h>
+#include <isccc/cc.h>
+#include <isccc/ccmsg.h>
+#include <isccc/result.h>
+#include <isccc/sexpr.h>
+#include <isccc/types.h>
+#include <isccc/util.h>
+
+#include <dns/name.h>
+
+#include <bind9/getaddresses.h>
+
+#include "util.h"
+
+#define SERVERADDRS 10
+
+const char *progname;
+bool verbose;
+
+static const char *admin_conffile;
+static const char *admin_keyfile;
+static const char *version = 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_socketmgr_t *socketmgr = NULL;
+static isc_buffer_t *databuf;
+static isccc_ccmsg_t 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;
+static int sends, recvs, connects;
+static char *command;
+static char *args;
+static char program[256];
+static isc_socket_t *sock = NULL;
+static uint32_t serial;
+static bool quiet = false;
+static bool showresult = false;
+
+static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task);
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(int status) ISC_PLATFORM_NORETURN_POST;
+
+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] 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\
+ 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|-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\
+ 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\
+ 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 [ yes | no | 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);
+}
+
+static void
+get_addresses(const char *host, in_port_t port) {
+ isc_result_t result;
+ int found = 0, count;
+
+ 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_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+
+ UNUSED(task);
+
+ sends--;
+ if (sevent->result != ISC_R_SUCCESS)
+ fatal("send failed: %s", isc_result_totext(sevent->result));
+ isc_event_free(&event);
+ if (sends == 0 && recvs == 0) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
+ }
+}
+
+static void
+rndc_recvdone(isc_task_t *task, isc_event_t *event) {
+ isccc_sexpr_t *response = NULL;
+ isccc_sexpr_t *data;
+ isccc_region_t source;
+ char *errormsg = NULL;
+ char *textmsg = NULL;
+ isc_result_t result;
+
+ recvs--;
+
+ if (ccmsg.result == ISC_R_EOF)
+ fatal("connection to remote host closed\n"
+ "This may indicate that\n"
+ "* the remote server is using an older version of"
+ " the command protocol,\n"
+ "* this host is not authorized to connect,\n"
+ "* the clocks are not synchronized, or\n"
+ "* the key is invalid.");
+
+ if (ccmsg.result != ISC_R_SUCCESS)
+ fatal("recv failed: %s", isc_result_totext(ccmsg.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");
+ }
+
+ isc_event_free(&event);
+ isccc_sexpr_free(&response);
+ if (sends == 0 && recvs == 0) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
+ }
+}
+
+static void
+rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
+ isccc_sexpr_t *response = NULL;
+ isccc_sexpr_t *_ctrl;
+ isccc_region_t source;
+ isc_result_t result;
+ uint32_t nonce;
+ isccc_sexpr_t *request = NULL;
+ isccc_time_t now;
+ isc_region_t r;
+ isccc_sexpr_t *data;
+ isc_buffer_t b;
+
+ recvs--;
+
+ if (ccmsg.result == ISC_R_EOF)
+ fatal("connection to remote host closed\n"
+ "This may indicate that\n"
+ "* the remote server is using an older 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, or\n"
+ "* the key is invalid.");
+
+ if (ccmsg.result != ISC_R_SUCCESS)
+ fatal("recv failed: %s", isc_result_totext(ccmsg.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;
+
+ isccc_ccmsg_cancelread(&ccmsg);
+ DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
+ rndc_recvdone, NULL));
+ recvs++;
+ DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
+ NULL));
+ sends++;
+
+ isc_event_free(&event);
+ isccc_sexpr_free(&response);
+ isccc_sexpr_free(&request);
+ return;
+}
+
+static void
+rndc_connected(isc_task_t *task, isc_event_t *event) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isccc_sexpr_t *request = NULL;
+ isccc_sexpr_t *data;
+ isccc_time_t now;
+ isc_region_t r;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ connects--;
+
+ if (sevent->result != ISC_R_SUCCESS) {
+ isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
+ sizeof(socktext));
+ if (sevent->result != ISC_R_CANCELED &&
+ ++currentaddr < nserveraddrs)
+ {
+ notify("connection failed: %s: %s", socktext,
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&sock);
+ isc_event_free(&event);
+ rndc_startconnect(&serveraddrs[currentaddr], task);
+ return;
+ } else
+ fatal("connect failed: %s: %s", socktext,
+ isc_result_totext(sevent->result));
+ }
+
+ 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, sock, &ccmsg);
+ isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
+
+ DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
+ rndc_recvnonce, NULL));
+ recvs++;
+ DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
+ NULL));
+ sends++;
+ isc_event_free(&event);
+ isccc_sexpr_free(&request);
+}
+
+static void
+rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
+ isc_result_t result;
+ int pf;
+ isc_sockettype_t type;
+
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, socktext, sizeof(socktext));
+
+ notify("using server %s (%s)", servername, socktext);
+
+ pf = isc_sockaddr_pf(addr);
+ if (pf == AF_INET || pf == AF_INET6)
+ type = isc_sockettype_tcp;
+ else
+ type = isc_sockettype_unix;
+ DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
+ switch (isc_sockaddr_pf(addr)) {
+ case AF_INET:
+ DO("bind socket", isc_socket_bind(sock, &local4, 0));
+ break;
+ case AF_INET6:
+ DO("bind socket", isc_socket_bind(sock, &local6, 0));
+ break;
+ default:
+ break;
+ }
+ DO("connect", isc_socket_connect(sock, addr, task, rndc_connected,
+ NULL));
+ connects++;
+}
+
+static void
+rndc_start(isc_task_t *task, isc_event_t *event) {
+ isc_event_free(&event);
+
+ currentaddr = 0;
+ rndc_startconnect(&serveraddrs[currentaddr], task);
+}
+
+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;
+ 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))
+ {
+ key = cfg_listelt_value(elt);
+ if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)),
+ 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);
+
+#ifndef PK11_MD5_DISABLE
+ if (strcasecmp(algorithmstr, "hmac-md5") == 0)
+ algorithm = ISCCC_ALG_HMACMD5;
+ else
+#endif
+ 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_taskmgr_t *taskmgr = NULL;
+ isc_task_t *task = NULL;
+ 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;
+
+ while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:qrs:Vy:"))
+ != -1) {
+ switch (ch) {
+ 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 (argc < 1)
+ usage(1);
+
+ isc_random_get(&serial);
+
+ DO("create memory context", isc_mem_create(0, 0, &rndc_mctx));
+ DO("create socket manager", isc_socketmgr_create(rndc_mctx, &socketmgr));
+ DO("create task manager", isc_taskmgr_create(rndc_mctx, 1, 0, &taskmgr));
+ DO("create task", isc_task_create(taskmgr, 0, &task));
+
+ DO("create logging context", isc_log_create(rndc_mctx, &log, &logconfig));
+ isc_log_setcontext(log);
+ DO("setting log tag", isc_log_settag(logconfig, progname));
+ logdest.file.stream = stderr;
+ logdest.file.name = NULL;
+ logdest.file.versions = ISC_LOG_ROLLNEVER;
+ logdest.file.maximum_size = 0;
+ DO("creating log channel",
+ 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);
+
+ isccc_result_register();
+
+ command = *argv;
+
+ DO("allocate data buffer",
+ 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);
+ if (args == NULL)
+ DO("isc_mem_get", ISC_R_NOMEMORY);
+
+ 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);
+
+ notify("%s", command);
+
+ if (strcmp(command, "restart") == 0)
+ fatal("'%s' is not implemented", command);
+
+ if (nserveraddrs == 0)
+ get_addresses(servername, (in_port_t) remoteport);
+
+ DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL));
+
+ result = isc_app_run();
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_app_run() failed: %s", isc_result_totext(result));
+
+ if (connects > 0 || sends > 0 || recvs > 0)
+ isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_log_destroy(&log);
+ isc_log_setcontext(NULL);
+
+ cfg_obj_destroy(pctx, &config);
+ cfg_parser_destroy(&pctx);
+
+ isc_mem_put(rndc_mctx, args, argslen);
+ isccc_ccmsg_invalidate(&ccmsg);
+
+ dns_name_destroy();
+
+ 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 b/bin/rndc/rndc.conf
new file mode 100644
index 0000000..6800331
--- /dev/null
+++ b/bin/rndc/rndc.conf
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Sample rndc configuration file.
+ */
+
+options {
+ default-server localhost;
+ default-key "key";
+};
+
+server localhost {
+ key "key";
+};
+
+key "cc64b3d1db63fc88d7cb5d2f9f57d258" {
+ algorithm hmac-sha256;
+ secret "34f88008d07deabbe65bd01f1d233d47";
+};
+
+server "test1" {
+ key "cc64b3d1db63fc88d7cb5d2f9f57d258";
+ port 5353;
+ addresses { 10.53.0.1; };
+};
+
+key "key" {
+ algorithm hmac-sha256;
+ secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
+};
diff --git a/bin/rndc/rndc.conf.5 b/bin/rndc/rndc.conf.5
new file mode 100644
index 0000000..056ea6c
--- /dev/null
+++ b/bin/rndc/rndc.conf.5
@@ -0,0 +1,234 @@
+.\" Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: rndc.conf
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2013-03-14
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "RNDC\&.CONF" "5" "2013\-03\-14" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+rndc.conf \- rndc configuration file
+.SH "SYNOPSIS"
+.HP \w'\fBrndc\&.conf\fR\ 'u
+\fBrndc\&.conf\fR
+.SH "DESCRIPTION"
+.PP
+rndc\&.conf
+is the configuration file for
+\fBrndc\fR, the BIND 9 name server control utility\&. This file has a similar structure and syntax to
+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:
+.PP
+C style: /* */
+.PP
+C++ style: // to end of line
+.PP
+Unix style: # to end of line
+.PP
+rndc\&.conf
+is much simpler than
+named\&.conf\&. The file uses three statements: an options statement, a server statement and a key statement\&.
+.PP
+The
+\fBoptions\fR
+statement contains five clauses\&. The
+\fBdefault\-server\fR
+clause is followed by the name or address of a name server\&. This host will be used when no name server is given as an argument to
+\fBrndc\fR\&. The
+\fBdefault\-key\fR
+clause is followed by the name of a key which is identified by a
+\fBkey\fR
+statement\&. If no
+\fBkeyid\fR
+is provided on the rndc command line, and no
+\fBkey\fR
+clause is found in a matching
+\fBserver\fR
+statement, this default key will be used to authenticate the server\*(Aqs commands and responses\&. The
+\fBdefault\-port\fR
+clause is followed by the port to connect to on the remote name server\&. If no
+\fBport\fR
+option is provided on the rndc command line, and no
+\fBport\fR
+clause is found in a matching
+\fBserver\fR
+statement, this default port will be used to connect\&. The
+\fBdefault\-source\-address\fR
+and
+\fBdefault\-source\-address\-v6\fR
+clauses which can be used to set the IPv4 and IPv6 source addresses respectively\&.
+.PP
+After the
+\fBserver\fR
+keyword, the server statement includes a string which is the hostname or address for a name server\&. The statement has three possible clauses:
+\fBkey\fR,
+\fBport\fR
+and
+\fBaddresses\fR\&. 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
+\fBaddresses\fR
+clause is supplied these addresses will be used instead of the server name\&. Each address can take an optional port\&. If an
+\fBsource\-address\fR
+or
+\fBsource\-address\-v6\fR
+of supplied then these will be used to specify the IPv4 and IPv6 source addresses respectively\&.
+.PP
+The
+\fBkey\fR
+statement begins with an identifying string, the name of the key\&. The statement has two clauses\&.
+\fBalgorithm\fR
+identifies the authentication algorithm for
+\fBrndc\fR
+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\*(Aqs authentication key\&. The base\-64 string is enclosed in double quotes\&.
+.PP
+There are two common ways to generate the base\-64 string for the secret\&. The BIND 9 program
+\fBrndc\-confgen\fR
+can be used to generate a random key, or the
+\fBmmencode\fR
+program, also known as
+\fBmimencode\fR, can be used to generate a base\-64 string from known input\&.
+\fBmmencode\fR
+does not ship with BIND 9 but is available on many systems\&. See the EXAMPLE section for sample command lines for each\&.
+.SH "EXAMPLE"
+.PP
+.if n \{\
+.RS 4
+.\}
+.nf
+ options {
+ default\-server localhost;
+ default\-key samplekey;
+ };
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+.if n \{\
+.RS 4
+.\}
+.nf
+ server localhost {
+ key samplekey;
+ };
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+.if n \{\
+.RS 4
+.\}
+.nf
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+.if n \{\
+.RS 4
+.\}
+.nf
+ key samplekey {
+ algorithm hmac\-sha256;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+.if n \{\
+.RS 4
+.\}
+.nf
+ key testkey {
+ algorithm hmac\-sha256;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+In the above example,
+\fBrndc\fR
+will by default use the server at localhost (127\&.0\&.0\&.1) and the key called samplekey\&. Commands to the localhost server will use the samplekey key, which must also be defined in the server\*(Aqs 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\&.
+.PP
+If
+\fBrndc \-s testserver\fR
+is used then
+\fBrndc\fR
+will connect to server on localhost port 5353 using the key testkey\&.
+.PP
+To generate a random secret with
+\fBrndc\-confgen\fR:
+.PP
+\fBrndc\-confgen\fR
+.PP
+A complete
+rndc\&.conf
+file, including the randomly generated key, will be written to the standard output\&. Commented\-out
+\fBkey\fR
+and
+\fBcontrols\fR
+statements for
+named\&.conf
+are also printed\&.
+.PP
+To generate a base\-64 secret with
+\fBmmencode\fR:
+.PP
+\fBecho "known plaintext for a secret" | mmencode\fR
+.SH "NAME SERVER CONFIGURATION"
+.PP
+The name server must be configured to accept rndc connections and to recognize the key specified in the
+rndc\&.conf
+file, using the controls statement in
+named\&.conf\&. See the sections on the
+\fBcontrols\fR
+statement in the BIND 9 Administrator Reference Manual for details\&.
+.SH "SEE ALSO"
+.PP
+\fBrndc\fR(8),
+\fBrndc-confgen\fR(8),
+\fBmmencode\fR(1),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000, 2001, 2004, 2005, 2007, 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/rndc/rndc.conf.docbook b/bin/rndc/rndc.conf.docbook
new file mode 100644
index 0000000..a021526
--- /dev/null
+++ b/bin/rndc/rndc.conf.docbook
@@ -0,0 +1,241 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.rndc.conf">
+ <info>
+ <date>2013-03-14</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><filename>rndc.conf</filename></refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><filename>rndc.conf</filename></refname>
+ <refpurpose>rndc configuration file</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>rndc.conf</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><filename>rndc.conf</filename> is the configuration file
+ for <command>rndc</command>, the BIND 9 name server control
+ utility. This file has a similar structure and syntax to
+ <filename>named.conf</filename>. 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:
+ </para>
+ <para>
+ C style: /* */
+ </para>
+ <para>
+ C++ style: // to end of line
+ </para>
+ <para>
+ Unix style: # to end of line
+ </para>
+ <para><filename>rndc.conf</filename> is much simpler than
+ <filename>named.conf</filename>. The file uses three
+ statements: an options statement, a server statement
+ and a key statement.
+ </para>
+ <para>
+ The <option>options</option> statement contains five clauses.
+ The <option>default-server</option> clause is followed by the
+ name or address of a name server. This host will be used when
+ no name server is given as an argument to
+ <command>rndc</command>. The <option>default-key</option>
+ clause is followed by the name of a key which is identified by
+ a <option>key</option> statement. If no
+ <option>keyid</option> is provided on the rndc command line,
+ and no <option>key</option> clause is found in a matching
+ <option>server</option> statement, this default key will be
+ used to authenticate the server's commands and responses. The
+ <option>default-port</option> clause is followed by the port
+ to connect to on the remote name server. If no
+ <option>port</option> option is provided on the rndc command
+ line, and no <option>port</option> clause is found in a
+ matching <option>server</option> statement, this default port
+ will be used to connect.
+ The <option>default-source-address</option> and
+ <option>default-source-address-v6</option> clauses which
+ can be used to set the IPv4 and IPv6 source addresses
+ respectively.
+ </para>
+ <para>
+ After the <option>server</option> keyword, the server
+ statement includes a string which is the hostname or address
+ for a name server. The statement has three possible clauses:
+ <option>key</option>, <option>port</option> and
+ <option>addresses</option>. 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 <option>addresses</option>
+ clause is supplied these addresses will be used instead of
+ the server name. Each address can take an optional port.
+ If an <option>source-address</option> or <option>source-address-v6</option>
+ of supplied then these will be used to specify the IPv4 and IPv6
+ source addresses respectively.
+ </para>
+ <para>
+ The <option>key</option> statement begins with an identifying
+ string, the name of the key. The statement has two clauses.
+ <option>algorithm</option> identifies the authentication algorithm
+ for <command>rndc</command> 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.
+ </para>
+ <para>
+ There are two common ways to generate the base-64 string for the
+ secret. The BIND 9 program <command>rndc-confgen</command>
+ can
+ be used to generate a random key, or the
+ <command>mmencode</command> program, also known as
+ <command>mimencode</command>, can be used to generate a
+ base-64
+ string from known input. <command>mmencode</command> does
+ not
+ ship with BIND 9 but is available on many systems. See the
+ EXAMPLE section for sample command lines for each.
+ </para>
+ </refsection>
+
+ <refsection><info><title>EXAMPLE</title></info>
+
+
+ <para><programlisting>
+ options {
+ default-server localhost;
+ default-key samplekey;
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ server localhost {
+ key samplekey;
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ key samplekey {
+ algorithm hmac-sha256;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ key testkey {
+ algorithm hmac-sha256;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+ </programlisting>
+ </para>
+
+ <para>
+ In the above example, <command>rndc</command> will by
+ default use
+ the server at localhost (127.0.0.1) and the key called samplekey.
+ Commands to the localhost server will 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.
+ </para>
+ <para>
+ If <command>rndc -s testserver</command> is used then <command>rndc</command> will
+ connect to server on localhost port 5353 using the key testkey.
+ </para>
+ <para>
+ To generate a random secret with <command>rndc-confgen</command>:
+ </para>
+ <para><userinput>rndc-confgen</userinput>
+ </para>
+ <para>
+ A complete <filename>rndc.conf</filename> file, including
+ the
+ randomly generated key, will be written to the standard
+ output. Commented-out <option>key</option> and
+ <option>controls</option> statements for
+ <filename>named.conf</filename> are also printed.
+ </para>
+ <para>
+ To generate a base-64 secret with <command>mmencode</command>:
+ </para>
+ <para><userinput>echo "known plaintext for a secret" | mmencode</userinput>
+ </para>
+ </refsection>
+
+ <refsection><info><title>NAME SERVER CONFIGURATION</title></info>
+
+ <para>
+ The name server must be configured to accept rndc connections and
+ to recognize the key specified in the <filename>rndc.conf</filename>
+ file, using the controls statement in <filename>named.conf</filename>.
+ See the sections on the <option>controls</option> statement in the
+ BIND 9 Administrator Reference Manual for details.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>mmencode</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/rndc/rndc.conf.html b/bin/rndc/rndc.conf.html
new file mode 100644
index 0000000..c7ca53e
--- /dev/null
+++ b/bin/rndc/rndc.conf.html
@@ -0,0 +1,234 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc.conf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.rndc.conf"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <code class="filename">rndc.conf</code>
+ &#8212; rndc configuration file
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">rndc.conf</code>
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><code class="filename">rndc.conf</code> is the configuration file
+ for <span class="command"><strong>rndc</strong></span>, the BIND 9 name server control
+ utility. This file has a similar structure and syntax to
+ <code class="filename">named.conf</code>. 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:
+ </p>
+ <p>
+ C style: /* */
+ </p>
+ <p>
+ C++ style: // to end of line
+ </p>
+ <p>
+ Unix style: # to end of line
+ </p>
+ <p><code class="filename">rndc.conf</code> is much simpler than
+ <code class="filename">named.conf</code>. The file uses three
+ statements: an options statement, a server statement
+ and a key statement.
+ </p>
+ <p>
+ The <code class="option">options</code> statement contains five clauses.
+ The <code class="option">default-server</code> clause is followed by the
+ name or address of a name server. This host will be used when
+ no name server is given as an argument to
+ <span class="command"><strong>rndc</strong></span>. The <code class="option">default-key</code>
+ clause is followed by the name of a key which is identified by
+ a <code class="option">key</code> statement. If no
+ <code class="option">keyid</code> is provided on the rndc command line,
+ and no <code class="option">key</code> clause is found in a matching
+ <code class="option">server</code> statement, this default key will be
+ used to authenticate the server's commands and responses. The
+ <code class="option">default-port</code> clause is followed by the port
+ to connect to on the remote name server. If no
+ <code class="option">port</code> option is provided on the rndc command
+ line, and no <code class="option">port</code> clause is found in a
+ matching <code class="option">server</code> statement, this default port
+ will be used to connect.
+ The <code class="option">default-source-address</code> and
+ <code class="option">default-source-address-v6</code> clauses which
+ can be used to set the IPv4 and IPv6 source addresses
+ respectively.
+ </p>
+ <p>
+ After the <code class="option">server</code> keyword, the server
+ statement includes a string which is the hostname or address
+ for a name server. The statement has three possible clauses:
+ <code class="option">key</code>, <code class="option">port</code> and
+ <code class="option">addresses</code>. 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 <code class="option">addresses</code>
+ clause is supplied these addresses will be used instead of
+ the server name. Each address can take an optional port.
+ If an <code class="option">source-address</code> or <code class="option">source-address-v6</code>
+ of supplied then these will be used to specify the IPv4 and IPv6
+ source addresses respectively.
+ </p>
+ <p>
+ The <code class="option">key</code> statement begins with an identifying
+ string, the name of the key. The statement has two clauses.
+ <code class="option">algorithm</code> identifies the authentication algorithm
+ for <span class="command"><strong>rndc</strong></span> 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.
+ </p>
+ <p>
+ There are two common ways to generate the base-64 string for the
+ secret. The BIND 9 program <span class="command"><strong>rndc-confgen</strong></span>
+ can
+ be used to generate a random key, or the
+ <span class="command"><strong>mmencode</strong></span> program, also known as
+ <span class="command"><strong>mimencode</strong></span>, can be used to generate a
+ base-64
+ string from known input. <span class="command"><strong>mmencode</strong></span> does
+ not
+ ship with BIND 9 but is available on many systems. See the
+ EXAMPLE section for sample command lines for each.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>EXAMPLE</h2>
+
+
+ <pre class="programlisting">
+ options {
+ default-server localhost;
+ default-key samplekey;
+ };
+</pre>
+<p>
+ </p>
+ <pre class="programlisting">
+ server localhost {
+ key samplekey;
+ };
+</pre>
+<p>
+ </p>
+ <pre class="programlisting">
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+</pre>
+<p>
+ </p>
+ <pre class="programlisting">
+ key samplekey {
+ algorithm hmac-sha256;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+</pre>
+<p>
+ </p>
+ <pre class="programlisting">
+ key testkey {
+ algorithm hmac-sha256;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+ </pre>
+<p>
+ </p>
+
+ <p>
+ In the above example, <span class="command"><strong>rndc</strong></span> will by
+ default use
+ the server at localhost (127.0.0.1) and the key called samplekey.
+ Commands to the localhost server will 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.
+ </p>
+ <p>
+ If <span class="command"><strong>rndc -s testserver</strong></span> is used then <span class="command"><strong>rndc</strong></span> will
+ connect to server on localhost port 5353 using the key testkey.
+ </p>
+ <p>
+ To generate a random secret with <span class="command"><strong>rndc-confgen</strong></span>:
+ </p>
+ <p><strong class="userinput"><code>rndc-confgen</code></strong>
+ </p>
+ <p>
+ A complete <code class="filename">rndc.conf</code> file, including
+ the
+ randomly generated key, will be written to the standard
+ output. Commented-out <code class="option">key</code> and
+ <code class="option">controls</code> statements for
+ <code class="filename">named.conf</code> are also printed.
+ </p>
+ <p>
+ To generate a base-64 secret with <span class="command"><strong>mmencode</strong></span>:
+ </p>
+ <p><strong class="userinput"><code>echo "known plaintext for a secret" | mmencode</code></strong>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>NAME SERVER CONFIGURATION</h2>
+
+ <p>
+ The name server must be configured to accept rndc connections and
+ to recognize the key specified in the <code class="filename">rndc.conf</code>
+ file, using the controls statement in <code class="filename">named.conf</code>.
+ See the sections on the <code class="option">controls</code> statement in the
+ BIND 9 Administrator Reference Manual for details.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">rndc</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc-confgen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">mmencode</span>(1)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/rndc/rndc.docbook b/bin/rndc/rndc.docbook
new file mode 100644
index 0000000..ddc138a
--- /dev/null
+++ b/bin/rndc/rndc.docbook
@@ -0,0 +1,1014 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.rndc">
+ <info>
+ <date>2014-08-15</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>rndc</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>rndc</application></refname>
+ <refpurpose>name server control utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>rndc</command>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">source-address</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">key-file</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">server</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-r</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-y <replaceable class="parameter">key_id</replaceable></option></arg>
+ <arg choice="req" rep="norepeat">command</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>rndc</command>
+ controls the operation of a name
+ server. It supersedes the <command>ndc</command> utility
+ that was provided in old BIND releases. If
+ <command>rndc</command> 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.
+ </para>
+ <para><command>rndc</command>
+ communicates with the name server over a TCP connection, sending
+ commands authenticated with digital signatures. In the current
+ versions of
+ <command>rndc</command> and <command>named</command>,
+ 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.
+ This 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 key_id known to the
+ server.
+ </para>
+ <para><command>rndc</command>
+ reads a configuration file to
+ determine how to contact the name server and decide what
+ algorithm and key it should use.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-b <replaceable class="parameter">source-address</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">source-address</replaceable>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable>
+ as the configuration file instead of the default,
+ <filename>/etc/rndc.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">key-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">key-file</replaceable>
+ as the key file instead of the default,
+ <filename>/etc/rndc.key</filename>. The key in
+ <filename>/etc/rndc.key</filename> will be used to
+ authenticate
+ commands sent to the server if the <replaceable class="parameter">config-file</replaceable>
+ does not exist.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">server</replaceable></term>
+ <listitem>
+ <para><replaceable class="parameter">server</replaceable> is
+ the name or address of the server which matches a
+ server statement in the configuration file for
+ <command>rndc</command>. If no server is supplied on the
+ command line, the host named by the default-server clause
+ in the options statement of the <command>rndc</command>
+ configuration file will be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Send commands to TCP port
+ <replaceable class="parameter">port</replaceable>
+ instead
+ of BIND 9's default control channel port, 953.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ Quiet mode: Message text returned by the server
+ will not be printed except when there is an error.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r</term>
+ <listitem>
+ <para>
+ Instructs <command>rndc</command> to print the result code
+ returned by <command>named</command> after executing the
+ requested command (e.g., ISC_R_SUCCESS, ISC_R_FAILURE, etc).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Enable verbose logging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y <replaceable class="parameter">key_id</replaceable></term>
+ <listitem>
+ <para>
+ Use the key <replaceable class="parameter">key_id</replaceable>
+ from the configuration file.
+ <replaceable class="parameter">key_id</replaceable>
+ must be
+ known by <command>named</command> with the same algorithm and secret string
+ in order for control message validation to succeed.
+ If no <replaceable class="parameter">key_id</replaceable>
+ is specified, <command>rndc</command> will first look
+ for a key clause in the server statement of the server
+ being used, or if no server statement is present for that
+ host, then 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. It should therefore not have general read
+ or write access.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>COMMANDS</title></info>
+
+ <para>
+ A list of commands supported by <command>rndc</command> can
+ be seen by running <command>rndc</command> without arguments.
+ </para>
+ <para>
+ Currently supported commands are:
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><userinput>addzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> <replaceable>configuration</replaceable> </userinput></term>
+ <listitem>
+ <para>
+ Add a zone while the server is running. This
+ command requires the
+ <command>allow-new-zones</command> option to be set
+ to <userinput>yes</userinput>. The
+ <replaceable>configuration</replaceable> string
+ specified on the command line is the zone
+ configuration text that would ordinarily be
+ placed in <filename>named.conf</filename>.
+ </para>
+ <para>
+ The configuration is saved in a file called
+ <filename><replaceable>name</replaceable>.nzf</filename>,
+ where <replaceable>name</replaceable> is the
+ name of the view, or if it contains characters
+ that are incompatible with use as a file name, a
+ cryptographic hash generated from the name
+ of the view.
+ When <command>named</command> is
+ restarted, the file will be loaded into the view
+ configuration, so that zones that were added
+ can persist after a restart.
+ </para>
+ <para>
+ This sample <command>addzone</command> command
+ would add the zone <literal>example.com</literal>
+ to the default view:
+ </para>
+ <para>
+<prompt>$ </prompt><userinput>rndc addzone example.com '{ type master; file "example.com.db"; };'</userinput>
+ </para>
+ <para>
+ (Note the brackets and semi-colon around the zone
+ configuration text.)
+ </para>
+ <para>
+ See also <command>rndc delzone</command> and <command>rndc modzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>delzone <optional>-clean</optional> <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
+ <listitem>
+ <para>
+ Delete a zone while the server is running.
+ </para>
+ <para>
+ If the <option>-clean</option> argument is specified,
+ the zone's master file (and journal file, if any)
+ will be deleted along with the zone. Without the
+ <option>-clean</option> option, zone files must
+ be cleaned up by hand. (If the zone is of
+ type "slave" or "stub", the files needing to
+ be cleaned up will be reported in the output
+ of the <command>rndc delzone</command> command.)
+ </para>
+ <para>
+ If the zone was originally added via
+ <command>rndc addzone</command>, then it will be
+ removed permanently. However, if it was originally
+ configured in <filename>named.conf</filename>, then
+ that original configuration is still in place; when
+ the server is restarted or reconfigured, the zone will
+ come back. To remove it permanently, it must also be
+ removed from <filename>named.conf</filename>
+ </para>
+ <para>
+ See also <command>rndc addzone</command> and <command>rndc modzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>dnstap ( -reopen | -roll <optional><replaceable>number</replaceable></optional> )</userinput></term>
+ <listitem>
+ <para>
+ Close and re-open DNSTAP output files.
+ <command>rndc dnstap -reopen</command> allows the output
+ file to be renamed externally, so
+ that <command>named</command> can truncate and re-open it.
+ <command>rndc dnstap -roll</command> 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 <replaceable>number</replaceable> is specified, then the
+ number of backup log files is limited to that number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>dumpdb <optional>-all|-cache|-zones|-adb|-bad|-fail</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
+ <listitem>
+ <para>
+ Dump 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 <command>dump-file</command> option in
+ the BIND 9 Administrator Reference Manual.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>flush</userinput></term>
+ <listitem>
+ <para>
+ Flushes the server's cache.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>flushname</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>flushtree</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
+ <listitem>
+ <para>
+ Flushes the given name, and all of its subdomains,
+ from the view's DNS cache, address database,
+ bad server cache, and SERVFAIL cache.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>freeze <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Suspend 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. It also causes changes in the
+ journal file to be synced into the master file.
+ All dynamic update attempts will be refused while
+ the zone is frozen.
+ </para>
+ <para>
+ See also <command>rndc thaw</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>halt <optional>-p</optional></userinput></term>
+ <listitem>
+ <para>
+ Stop the server immediately. Recent changes
+ made through dynamic update or IXFR are not saved to
+ the master files, but will be rolled forward from the
+ journal files when the server is restarted.
+ If <option>-p</option> is specified <command>named</command>'s process id is returned.
+ This allows an external process to determine when <command>named</command>
+ had completed halting.
+ </para>
+ <para>
+ See also <command>rndc stop</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>loadkeys <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Fetch all DNSSEC keys for the given zone
+ from the key directory. If they are within
+ their publication period, merge them into the
+ zone's DNSKEY RRset. Unlike <command>rndc
+ sign</command>, however, the zone is not
+ immediately re-signed by the new keys, but is
+ allowed to incrementally re-sign over time.
+ </para>
+ <para>
+ This command requires that the
+ <command>auto-dnssec</command> zone option
+ be set to <literal>maintain</literal>,
+ and also requires the zone to be configured to
+ allow dynamic DNS.
+ (See "Dynamic Update Policies" in the Administrator
+ Reference Manual for more details.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>managed-keys <replaceable>(status | refresh | sync)</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ When run with the "status" keyword, print the current
+ status of the managed-keys database for the specified
+ view, or for all views if none is specified. When run
+ with the "refresh" keyword, force an immediate refresh
+ of all the managed-keys in the specified view, or all
+ views. When run with the "sync" keyword, force an
+ immediate dump of the managed-keys database to disk (in
+ the file <filename>managed-keys.bind</filename> or
+ (<filename><replaceable>viewname</replaceable>.mkeys</filename>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>modzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> <replaceable>configuration</replaceable> </userinput></term>
+ <listitem>
+ <para>
+ Modify the configuration of a zone while the server
+ is running. This command requires the
+ <command>allow-new-zones</command> option to be
+ set to <userinput>yes</userinput>. As with
+ <command>addzone</command>, the
+ <replaceable>configuration</replaceable> string
+ specified on the command line is the zone
+ configuration text that would ordinarily be
+ placed in <filename>named.conf</filename>.
+ </para>
+ <para>
+ If the zone was originally added via
+ <command>rndc addzone</command>, the configuration
+ changes will be recorded permanently and will still be
+ in effect after the server is restarted or reconfigured.
+ However, if it was originally configured in
+ <filename>named.conf</filename>, then that original
+ configuration is still in place; when the server is
+ restarted or reconfigured, the zone will revert to
+ its original configuration. To make the changes
+ permanent, it must also be modified in
+ <filename>named.conf</filename>
+ </para>
+ <para>
+ See also <command>rndc addzone</command> and <command>rndc delzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>notify <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Resend NOTIFY messages for the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>notrace</userinput></term>
+ <listitem>
+ <para>
+ Sets the server's debugging level to 0.
+ </para>
+ <para>
+ See also <command>rndc trace</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>nta
+ <optional>( -class <replaceable>class</replaceable> | -dump | -force | -remove | -lifetime <replaceable>duration</replaceable>)</optional>
+ <replaceable>domain</replaceable>
+ <optional><replaceable>view</replaceable></optional>
+ </userinput></term>
+ <listitem>
+ <para>
+ Sets a DNSSEC negative trust anchor (NTA)
+ for <option>domain</option>, with a lifetime of
+ <option>duration</option>. The default lifetime is
+ configured in <filename>named.conf</filename> via the
+ <option>nta-lifetime</option> option, and defaults to
+ one hour. The lifetime cannot exceed one week.
+ </para>
+ <para>
+ 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), <command>named</command> will
+ abort the DNSSEC validation process and treat the data as
+ insecure rather than bogus. This continues until the
+ NTA's lifetime is elapsed.
+ </para>
+ <para>
+ NTAs persist across restarts of the <command>named</command> server.
+ The NTAs for a view are saved in a file called
+ <filename><replaceable>name</replaceable>.nta</filename>,
+ where <replaceable>name</replaceable> is the
+ name of the view, or if it contains characters
+ that are incompatible with use as a file name, a
+ cryptographic hash generated from the name
+ of the view.
+ </para>
+ <para>
+ An existing NTA can be removed by using the
+ <option>-remove</option> option.
+ </para>
+ <para>
+ An NTA's lifetime can be specified with the
+ <option>-lifetime</option> option. TTL-style
+ suffixes can be used to specify the lifetime in
+ seconds, minutes, or hours. If the specified NTA
+ already exists, its lifetime will be updated to the
+ new value. Setting <option>lifetime</option> to zero
+ is equivalent to <option>-remove</option>.
+ </para>
+ <para>
+ If the <option>-dump</option> 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).
+ </para>
+ <para>
+ Normally, <command>named</command> will periodically
+ test to see whether data below an NTA can now be
+ validated (see the <option>nta-recheck</option> option
+ in the Administrator Reference Manual for details).
+ If data can be validated, then the NTA is regarded as
+ no longer necessary, and will be allowed to expire
+ early. The <option>-force</option> 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.
+ </para>
+ <para>
+ The view class can be specified with <option>-class</option>.
+ The default is class <userinput>IN</userinput>, which is
+ the only class for which DNSSEC is currently supported.
+ </para>
+ <para>
+ All of these options can be shortened, i.e., to
+ <option>-l</option>, <option>-r</option>, <option>-d</option>,
+ <option>-f</option>, and <option>-c</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>querylog</userinput> <optional> on | off </optional> </term>
+ <listitem>
+ <para>
+ Enable or disable query logging. (For backward
+ compatibility, this command can also be used without
+ an argument to toggle query logging on and off.)
+ </para>
+ <para>
+ Query logging can also be enabled
+ by explicitly directing the <command>queries</command>
+ <command>category</command> to a
+ <command>channel</command> in the
+ <command>logging</command> section of
+ <filename>named.conf</filename> or by specifying
+ <command>querylog yes;</command> in the
+ <command>options</command> section of
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>reconfig</userinput></term>
+ <listitem>
+ <para>
+ Reload the configuration file and load new zones,
+ but do not reload existing zone files even if they
+ have changed.
+ This is faster than a full <command>reload</command> when there
+ is a large number of zones because it avoids the need
+ to examine the
+ modification times of the zones files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>recursing</userinput></term>
+ <listitem>
+ <para>
+ Dump the list of queries <command>named</command> is currently
+ recursing on, and the list of domains to which iterative
+ queries are currently being sent. (The second list includes
+ the number of fetches currently active for the given domain,
+ and how many have been passed or dropped because of the
+ <option>fetches-per-zone</option> option.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>refresh <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Schedule zone maintenance for the given zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>reload</userinput></term>
+ <listitem>
+ <para>
+ Reload configuration file and zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>reload <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Reload the given zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>retransfer <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Retransfer the given slave zone from the master server.
+ </para>
+ <para>
+ If the zone is configured to use
+ <command>inline-signing</command>, the signed
+ version of the zone is discarded; after the
+ retransfer of the unsigned version is complete, the
+ signed version will be regenerated with all new
+ signatures.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>scan</userinput></term>
+ <listitem>
+ <para>
+ Scan the list of available network interfaces
+ for changes, without performing a full
+ <command>reconfig</command> or waiting for the
+ <command>interface-interval</command> timer.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>secroots <optional>-</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
+ <listitem>
+ <para>
+ Dump the server's security roots and negative trust anchors
+ for the specified views. If no view is specified, all views
+ are dumped.
+ </para>
+ <para>
+ If the first argument is "-", then the output is
+ returned via the <command>rndc</command> response channel
+ and printed to the standard output.
+ Otherwise, it is written to the secroots dump file, which
+ defaults to <filename>named.secroots</filename>, but can be
+ overridden via the <option>secroots-file</option> option in
+ <filename>named.conf</filename>.
+ </para>
+ <para>
+ See also <command>rndc managed-keys</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>showzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
+ <listitem>
+ <para>
+ Print the configuration of a running zone.
+ </para>
+ <para>
+ See also <command>rndc zonestatus</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>sign <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Fetch all DNSSEC keys for the given zone
+ from the key directory (see the
+ <command>key-directory</command> option in
+ the BIND 9 Administrator Reference Manual). If they are within
+ their publication period, merge them into the
+ zone's DNSKEY RRset. If the DNSKEY RRset
+ is changed, then the zone is automatically
+ re-signed with the new key set.
+ </para>
+ <para>
+ This command requires that the
+ <command>auto-dnssec</command> zone option be set
+ to <literal>allow</literal> or
+ <literal>maintain</literal>,
+ and also requires the zone to be configured to
+ allow dynamic DNS.
+ (See "Dynamic Update Policies" in the Administrator
+ Reference Manual for more details.)
+ </para>
+ <para>
+ See also <command>rndc loadkeys</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>signing <optional>( -list | -clear <replaceable>keyid/algorithm</replaceable> | -clear <literal>all</literal> | -nsec3param ( <replaceable>parameters</replaceable> | <literal>none</literal> ) | -serial <replaceable>value</replaceable> ) </optional> <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
+ <listitem>
+ <para>
+ List, edit, or remove 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
+ <command>sig-signing-type</command>.
+ <command>rndc signing -list</command> 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.
+ </para>
+ <para>
+ <command>rndc signing -clear</command> can remove
+ a single key (specified in the same format that
+ <command>rndc signing -list</command> 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
+ will be retained.
+ </para>
+ <para>
+ <command>rndc signing -nsec3param</command> sets
+ the NSEC3 parameters for a zone. This is the
+ only supported mechanism for using NSEC3 with
+ <command>inline-signing</command> zones.
+ Parameters are specified in the same format as
+ an NSEC3PARAM resource record: hash algorithm,
+ flags, iterations, and salt, in that order.
+ </para>
+ <para>
+ Currently, the only defined value for hash algorithm
+ is <literal>1</literal>, representing SHA-1.
+ The <option>flags</option> may be set to
+ <literal>0</literal> or <literal>1</literal>,
+ depending on whether you wish to set the opt-out
+ bit in the NSEC3 chain. <option>iterations</option>
+ defines the number of additional times to apply
+ the algorithm when generating an NSEC3 hash. The
+ <option>salt</option> is a string of data expressed
+ in hexadecimal, a hyphen (`-') if no salt is
+ to be used, or the keyword <literal>auto</literal>,
+ which causes <command>named</command> to generate a
+ random 64-bit salt.
+ </para>
+ <para>
+ So, for example, to create an NSEC3 chain using
+ the SHA-1 hash algorithm, no opt-out flag,
+ 10 iterations, and a salt value of "FFFF", use:
+ <command>rndc signing -nsec3param 1 0 10 FFFF <replaceable>zone</replaceable></command>.
+ To set the opt-out flag, 15 iterations, and no
+ salt, use:
+ <command>rndc signing -nsec3param 1 1 15 - <replaceable>zone</replaceable></command>.
+ </para>
+ <para>
+ <command>rndc signing -nsec3param none</command>
+ removes an existing NSEC3 chain and replaces it
+ with NSEC.
+ </para>
+ <para>
+ <command>rndc signing -serial value</command> sets
+ the serial number of the zone to value. If the value
+ would cause the serial number to go backwards it will
+ be rejected. The primary use is to set the serial on
+ inline signed zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>stats</userinput></term>
+ <listitem>
+ <para>
+ Write server statistics to the statistics file.
+ (See the <command>statistics-file</command> option in
+ the BIND 9 Administrator Reference Manual.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>status</userinput></term>
+ <listitem>
+ <para>
+ Display status of the server.
+ Note that the number of zones includes the internal <command>bind/CH</command> zone
+ and the default <command>./IN</command>
+ hint zone if there is not an
+ explicit root zone configured.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>stop <optional>-p</optional></userinput></term>
+ <listitem>
+ <para>
+ Stop 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 <option>-p</option> is specified <command>named</command>'s process id is returned.
+ This allows an external process to determine when <command>named</command>
+ had completed stopping.
+ </para>
+ <para>See also <command>rndc halt</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>sync <optional>-clean</optional> <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Sync 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>thaw <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Enable 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 will no longer be refused. If
+ the zone has changed and the
+ <command>ixfr-from-differences</command> option is
+ in use, then the journal file will be updated to
+ reflect changes in the zone. Otherwise, if the
+ zone has changed, any existing journal file will be
+ removed.
+ </para>
+ <para>See also <command>rndc freeze</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>trace</userinput></term>
+ <listitem>
+ <para>
+ Increment the servers debugging level by one.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>trace <replaceable>level</replaceable></userinput></term>
+ <listitem>
+ <para>
+ Sets the server's debugging level to an explicit
+ value.
+ </para>
+ <para>
+ See also <command>rndc notrace</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>tsig-delete</userinput> <replaceable>keyname</replaceable> <optional><replaceable>view</replaceable></optional></term>
+ <listitem>
+ <para>
+ Delete a given TKEY-negotiated key from the server.
+ (This does not apply to statically configured TSIG
+ keys.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>tsig-list</userinput></term>
+ <listitem>
+ <para>
+ List the names of all TSIG keys currently configured
+ for use by <command>named</command> in each view. The
+ list both statically configured keys and dynamic
+ TKEY-negotiated keys.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>validation ( on | off | status ) <optional><replaceable>view ...</replaceable></optional> </userinput></term>
+ <listitem>
+ <para>
+ Enable, disable, or check the current status of
+ DNSSEC validation.
+ Note <command>dnssec-enable</command> also needs to be
+ set to <userinput>yes</userinput> or
+ <userinput>auto</userinput> to be effective.
+ It defaults to enabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>zonestatus <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ <para>
+ See also <command>rndc showzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>LIMITATIONS</title></info>
+
+ <para>
+ There is currently no way to provide the shared secret for a
+ <option>key_id</option> without using the configuration file.
+ </para>
+ <para>
+ Several error messages could be clearer.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>rndc.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>ndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/rndc/rndc.html b/bin/rndc/rndc.html
new file mode 100644
index 0000000..88b046d
--- /dev/null
+++ b/bin/rndc/rndc.html
@@ -0,0 +1,860 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.rndc"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">rndc</span>
+ &#8212; name server control utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">rndc</code>
+ [<code class="option">-b <em class="replaceable"><code>source-address</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>]
+ [<code class="option">-k <em class="replaceable"><code>key-file</code></em></code>]
+ [<code class="option">-s <em class="replaceable"><code>server</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>port</code></em></code>]
+ [<code class="option">-q</code>]
+ [<code class="option">-r</code>]
+ [<code class="option">-V</code>]
+ [<code class="option">-y <em class="replaceable"><code>key_id</code></em></code>]
+ {command}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>rndc</strong></span>
+ controls the operation of a name
+ server. It supersedes the <span class="command"><strong>ndc</strong></span> utility
+ that was provided in old BIND releases. If
+ <span class="command"><strong>rndc</strong></span> 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.
+ </p>
+ <p><span class="command"><strong>rndc</strong></span>
+ communicates with the name server over a TCP connection, sending
+ commands authenticated with digital signatures. In the current
+ versions of
+ <span class="command"><strong>rndc</strong></span> and <span class="command"><strong>named</strong></span>,
+ 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.
+ This 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 key_id known to the
+ server.
+ </p>
+ <p><span class="command"><strong>rndc</strong></span>
+ reads a configuration file to
+ determine how to contact the name server and decide what
+ algorithm and key it should use.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-b <em class="replaceable"><code>source-address</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>source-address</code></em>
+ 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.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>config-file</code></em>
+ as the configuration file instead of the default,
+ <code class="filename">/etc/rndc.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>key-file</code></em></span></dt>
+<dd>
+ <p>
+ Use <em class="replaceable"><code>key-file</code></em>
+ as the key file instead of the default,
+ <code class="filename">/etc/rndc.key</code>. The key in
+ <code class="filename">/etc/rndc.key</code> will be used to
+ authenticate
+ commands sent to the server if the <em class="replaceable"><code>config-file</code></em>
+ does not exist.
+ </p>
+ </dd>
+<dt><span class="term">-s <em class="replaceable"><code>server</code></em></span></dt>
+<dd>
+ <p><em class="replaceable"><code>server</code></em> is
+ the name or address of the server which matches a
+ server statement in the configuration file for
+ <span class="command"><strong>rndc</strong></span>. If no server is supplied on the
+ command line, the host named by the default-server clause
+ in the options statement of the <span class="command"><strong>rndc</strong></span>
+ configuration file will be used.
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Send commands to TCP port
+ <em class="replaceable"><code>port</code></em>
+ instead
+ of BIND 9's default control channel port, 953.
+ </p>
+ </dd>
+<dt><span class="term">-q</span></dt>
+<dd>
+ <p>
+ Quiet mode: Message text returned by the server
+ will not be printed except when there is an error.
+ </p>
+ </dd>
+<dt><span class="term">-r</span></dt>
+<dd>
+ <p>
+ Instructs <span class="command"><strong>rndc</strong></span> to print the result code
+ returned by <span class="command"><strong>named</strong></span> after executing the
+ requested command (e.g., ISC_R_SUCCESS, ISC_R_FAILURE, etc).
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Enable verbose logging.
+ </p>
+ </dd>
+<dt><span class="term">-y <em class="replaceable"><code>key_id</code></em></span></dt>
+<dd>
+ <p>
+ Use the key <em class="replaceable"><code>key_id</code></em>
+ from the configuration file.
+ <em class="replaceable"><code>key_id</code></em>
+ must be
+ known by <span class="command"><strong>named</strong></span> with the same algorithm and secret string
+ in order for control message validation to succeed.
+ If no <em class="replaceable"><code>key_id</code></em>
+ is specified, <span class="command"><strong>rndc</strong></span> will first look
+ for a key clause in the server statement of the server
+ being used, or if no server statement is present for that
+ host, then 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. It should therefore not have general read
+ or write access.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>COMMANDS</h2>
+
+ <p>
+ A list of commands supported by <span class="command"><strong>rndc</strong></span> can
+ be seen by running <span class="command"><strong>rndc</strong></span> without arguments.
+ </p>
+ <p>
+ Currently supported commands are:
+ </p>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><strong class="userinput"><code>addzone <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>] <em class="replaceable"><code>configuration</code></em> </code></strong></span></dt>
+<dd>
+ <p>
+ Add a zone while the server is running. This
+ command requires the
+ <span class="command"><strong>allow-new-zones</strong></span> option to be set
+ to <strong class="userinput"><code>yes</code></strong>. The
+ <em class="replaceable"><code>configuration</code></em> string
+ specified on the command line is the zone
+ configuration text that would ordinarily be
+ placed in <code class="filename">named.conf</code>.
+ </p>
+ <p>
+ The configuration is saved in a file called
+ <code class="filename"><em class="replaceable"><code>name</code></em>.nzf</code>,
+ where <em class="replaceable"><code>name</code></em> is the
+ name of the view, or if it contains characters
+ that are incompatible with use as a file name, a
+ cryptographic hash generated from the name
+ of the view.
+ When <span class="command"><strong>named</strong></span> is
+ restarted, the file will be loaded into the view
+ configuration, so that zones that were added
+ can persist after a restart.
+ </p>
+ <p>
+ This sample <span class="command"><strong>addzone</strong></span> command
+ would add the zone <code class="literal">example.com</code>
+ to the default view:
+ </p>
+ <p>
+<code class="prompt">$ </code><strong class="userinput"><code>rndc addzone example.com '{ type master; file "example.com.db"; };'</code></strong>
+ </p>
+ <p>
+ (Note the brackets and semi-colon around the zone
+ configuration text.)
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc delzone</strong></span> and <span class="command"><strong>rndc modzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>delzone [<span class="optional">-clean</span>] <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>] </code></strong></span></dt>
+<dd>
+ <p>
+ Delete a zone while the server is running.
+ </p>
+ <p>
+ If the <code class="option">-clean</code> argument is specified,
+ the zone's master file (and journal file, if any)
+ will be deleted along with the zone. Without the
+ <code class="option">-clean</code> option, zone files must
+ be cleaned up by hand. (If the zone is of
+ type "slave" or "stub", the files needing to
+ be cleaned up will be reported in the output
+ of the <span class="command"><strong>rndc delzone</strong></span> command.)
+ </p>
+ <p>
+ If the zone was originally added via
+ <span class="command"><strong>rndc addzone</strong></span>, then it will be
+ removed permanently. However, if it was originally
+ configured in <code class="filename">named.conf</code>, then
+ that original configuration is still in place; when
+ the server is restarted or reconfigured, the zone will
+ come back. To remove it permanently, it must also be
+ removed from <code class="filename">named.conf</code>
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc addzone</strong></span> and <span class="command"><strong>rndc modzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>dnstap ( -reopen | -roll [<span class="optional"><em class="replaceable"><code>number</code></em></span>] )</code></strong></span></dt>
+<dd>
+ <p>
+ Close and re-open DNSTAP output files.
+ <span class="command"><strong>rndc dnstap -reopen</strong></span> allows the output
+ file to be renamed externally, so
+ that <span class="command"><strong>named</strong></span> can truncate and re-open it.
+ <span class="command"><strong>rndc dnstap -roll</strong></span> 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 <em class="replaceable"><code>number</code></em> is specified, then the
+ number of backup log files is limited to that number.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>dumpdb [<span class="optional">-all|-cache|-zones|-adb|-bad|-fail</span>] [<span class="optional"><em class="replaceable"><code>view ...</code></em></span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Dump 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 <span class="command"><strong>dump-file</strong></span> option in
+ the BIND 9 Administrator Reference Manual.)
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>flush</code></strong></span></dt>
+<dd>
+ <p>
+ Flushes the server's cache.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>flushname</code></strong> <em class="replaceable"><code>name</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>] </span></dt>
+<dd>
+ <p>
+ 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.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>flushtree</code></strong> <em class="replaceable"><code>name</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>] </span></dt>
+<dd>
+ <p>
+ Flushes the given name, and all of its subdomains,
+ from the view's DNS cache, address database,
+ bad server cache, and SERVFAIL cache.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>freeze [<span class="optional"><em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Suspend 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. It also causes changes in the
+ journal file to be synced into the master file.
+ All dynamic update attempts will be refused while
+ the zone is frozen.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc thaw</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>halt [<span class="optional">-p</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Stop the server immediately. Recent changes
+ made through dynamic update or IXFR are not saved to
+ the master files, but will be rolled forward from the
+ journal files when the server is restarted.
+ If <code class="option">-p</code> is specified <span class="command"><strong>named</strong></span>'s process id is returned.
+ This allows an external process to determine when <span class="command"><strong>named</strong></span>
+ had completed halting.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc stop</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>loadkeys <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Fetch all DNSSEC keys for the given zone
+ from the key directory. If they are within
+ their publication period, merge them into the
+ zone's DNSKEY RRset. Unlike <span class="command"><strong>rndc
+ sign</strong></span>, however, the zone is not
+ immediately re-signed by the new keys, but is
+ allowed to incrementally re-sign over time.
+ </p>
+ <p>
+ This command requires that the
+ <span class="command"><strong>auto-dnssec</strong></span> zone option
+ be set to <code class="literal">maintain</code>,
+ and also requires the zone to be configured to
+ allow dynamic DNS.
+ (See "Dynamic Update Policies" in the Administrator
+ Reference Manual for more details.)
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>managed-keys <em class="replaceable"><code>(status | refresh | sync)</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ When run with the "status" keyword, print the current
+ status of the managed-keys database for the specified
+ view, or for all views if none is specified. When run
+ with the "refresh" keyword, force an immediate refresh
+ of all the managed-keys in the specified view, or all
+ views. When run with the "sync" keyword, force an
+ immediate dump of the managed-keys database to disk (in
+ the file <code class="filename">managed-keys.bind</code> or
+ (<code class="filename"><em class="replaceable"><code>viewname</code></em>.mkeys</code>).
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>modzone <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>] <em class="replaceable"><code>configuration</code></em> </code></strong></span></dt>
+<dd>
+ <p>
+ Modify the configuration of a zone while the server
+ is running. This command requires the
+ <span class="command"><strong>allow-new-zones</strong></span> option to be
+ set to <strong class="userinput"><code>yes</code></strong>. As with
+ <span class="command"><strong>addzone</strong></span>, the
+ <em class="replaceable"><code>configuration</code></em> string
+ specified on the command line is the zone
+ configuration text that would ordinarily be
+ placed in <code class="filename">named.conf</code>.
+ </p>
+ <p>
+ If the zone was originally added via
+ <span class="command"><strong>rndc addzone</strong></span>, the configuration
+ changes will be recorded permanently and will still be
+ in effect after the server is restarted or reconfigured.
+ However, if it was originally configured in
+ <code class="filename">named.conf</code>, then that original
+ configuration is still in place; when the server is
+ restarted or reconfigured, the zone will revert to
+ its original configuration. To make the changes
+ permanent, it must also be modified in
+ <code class="filename">named.conf</code>
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc addzone</strong></span> and <span class="command"><strong>rndc delzone</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>notify <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Resend NOTIFY messages for the zone.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>notrace</code></strong></span></dt>
+<dd>
+ <p>
+ Sets the server's debugging level to 0.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc trace</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>nta
+ [<span class="optional">( -class <em class="replaceable"><code>class</code></em> | -dump | -force | -remove | -lifetime <em class="replaceable"><code>duration</code></em>)</span>]
+ <em class="replaceable"><code>domain</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]
+ </code></strong></span></dt>
+<dd>
+ <p>
+ Sets a DNSSEC negative trust anchor (NTA)
+ for <code class="option">domain</code>, with a lifetime of
+ <code class="option">duration</code>. The default lifetime is
+ configured in <code class="filename">named.conf</code> via the
+ <code class="option">nta-lifetime</code> option, and defaults to
+ one hour. The lifetime cannot exceed one week.
+ </p>
+ <p>
+ 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), <span class="command"><strong>named</strong></span> will
+ abort the DNSSEC validation process and treat the data as
+ insecure rather than bogus. This continues until the
+ NTA's lifetime is elapsed.
+ </p>
+ <p>
+ NTAs persist across restarts of the <span class="command"><strong>named</strong></span> server.
+ The NTAs for a view are saved in a file called
+ <code class="filename"><em class="replaceable"><code>name</code></em>.nta</code>,
+ where <em class="replaceable"><code>name</code></em> is the
+ name of the view, or if it contains characters
+ that are incompatible with use as a file name, a
+ cryptographic hash generated from the name
+ of the view.
+ </p>
+ <p>
+ An existing NTA can be removed by using the
+ <code class="option">-remove</code> option.
+ </p>
+ <p>
+ An NTA's lifetime can be specified with the
+ <code class="option">-lifetime</code> option. TTL-style
+ suffixes can be used to specify the lifetime in
+ seconds, minutes, or hours. If the specified NTA
+ already exists, its lifetime will be updated to the
+ new value. Setting <code class="option">lifetime</code> to zero
+ is equivalent to <code class="option">-remove</code>.
+ </p>
+ <p>
+ If the <code class="option">-dump</code> 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).
+ </p>
+ <p>
+ Normally, <span class="command"><strong>named</strong></span> will periodically
+ test to see whether data below an NTA can now be
+ validated (see the <code class="option">nta-recheck</code> option
+ in the Administrator Reference Manual for details).
+ If data can be validated, then the NTA is regarded as
+ no longer necessary, and will be allowed to expire
+ early. The <code class="option">-force</code> 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.
+ </p>
+ <p>
+ The view class can be specified with <code class="option">-class</code>.
+ The default is class <strong class="userinput"><code>IN</code></strong>, which is
+ the only class for which DNSSEC is currently supported.
+ </p>
+ <p>
+ All of these options can be shortened, i.e., to
+ <code class="option">-l</code>, <code class="option">-r</code>, <code class="option">-d</code>,
+ <code class="option">-f</code>, and <code class="option">-c</code>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>querylog</code></strong> [<span class="optional"> on | off </span>] </span></dt>
+<dd>
+ <p>
+ Enable or disable query logging. (For backward
+ compatibility, this command can also be used without
+ an argument to toggle query logging on and off.)
+ </p>
+ <p>
+ Query logging can also be enabled
+ by explicitly directing the <span class="command"><strong>queries</strong></span>
+ <span class="command"><strong>category</strong></span> to a
+ <span class="command"><strong>channel</strong></span> in the
+ <span class="command"><strong>logging</strong></span> section of
+ <code class="filename">named.conf</code> or by specifying
+ <span class="command"><strong>querylog yes;</strong></span> in the
+ <span class="command"><strong>options</strong></span> section of
+ <code class="filename">named.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>reconfig</code></strong></span></dt>
+<dd>
+ <p>
+ Reload the configuration file and load new zones,
+ but do not reload existing zone files even if they
+ have changed.
+ This is faster than a full <span class="command"><strong>reload</strong></span> when there
+ is a large number of zones because it avoids the need
+ to examine the
+ modification times of the zones files.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>recursing</code></strong></span></dt>
+<dd>
+ <p>
+ Dump the list of queries <span class="command"><strong>named</strong></span> is currently
+ recursing on, and the list of domains to which iterative
+ queries are currently being sent. (The second list includes
+ the number of fetches currently active for the given domain,
+ and how many have been passed or dropped because of the
+ <code class="option">fetches-per-zone</code> option.)
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>refresh <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Schedule zone maintenance for the given zone.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>reload</code></strong></span></dt>
+<dd>
+ <p>
+ Reload configuration file and zones.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>reload <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Reload the given zone.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>retransfer <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Retransfer the given slave zone from the master server.
+ </p>
+ <p>
+ If the zone is configured to use
+ <span class="command"><strong>inline-signing</strong></span>, the signed
+ version of the zone is discarded; after the
+ retransfer of the unsigned version is complete, the
+ signed version will be regenerated with all new
+ signatures.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>scan</code></strong></span></dt>
+<dd>
+ <p>
+ Scan the list of available network interfaces
+ for changes, without performing a full
+ <span class="command"><strong>reconfig</strong></span> or waiting for the
+ <span class="command"><strong>interface-interval</strong></span> timer.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>secroots [<span class="optional">-</span>] [<span class="optional"><em class="replaceable"><code>view ...</code></em></span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Dump the server's security roots and negative trust anchors
+ for the specified views. If no view is specified, all views
+ are dumped.
+ </p>
+ <p>
+ If the first argument is "-", then the output is
+ returned via the <span class="command"><strong>rndc</strong></span> response channel
+ and printed to the standard output.
+ Otherwise, it is written to the secroots dump file, which
+ defaults to <code class="filename">named.secroots</code>, but can be
+ overridden via the <code class="option">secroots-file</code> option in
+ <code class="filename">named.conf</code>.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc managed-keys</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>showzone <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>] </code></strong></span></dt>
+<dd>
+ <p>
+ Print the configuration of a running zone.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc zonestatus</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>sign <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Fetch all DNSSEC keys for the given zone
+ from the key directory (see the
+ <span class="command"><strong>key-directory</strong></span> option in
+ the BIND 9 Administrator Reference Manual). If they are within
+ their publication period, merge them into the
+ zone's DNSKEY RRset. If the DNSKEY RRset
+ is changed, then the zone is automatically
+ re-signed with the new key set.
+ </p>
+ <p>
+ This command requires that the
+ <span class="command"><strong>auto-dnssec</strong></span> zone option be set
+ to <code class="literal">allow</code> or
+ <code class="literal">maintain</code>,
+ and also requires the zone to be configured to
+ allow dynamic DNS.
+ (See "Dynamic Update Policies" in the Administrator
+ Reference Manual for more details.)
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc loadkeys</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>signing [<span class="optional">( -list | -clear <em class="replaceable"><code>keyid/algorithm</code></em> | -clear <code class="literal">all</code> | -nsec3param ( <em class="replaceable"><code>parameters</code></em> | <code class="literal">none</code> ) | -serial <em class="replaceable"><code>value</code></em> ) </span>] <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>] </code></strong></span></dt>
+<dd>
+ <p>
+ List, edit, or remove 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
+ <span class="command"><strong>sig-signing-type</strong></span>.
+ <span class="command"><strong>rndc signing -list</strong></span> 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.
+ </p>
+ <p>
+ <span class="command"><strong>rndc signing -clear</strong></span> can remove
+ a single key (specified in the same format that
+ <span class="command"><strong>rndc signing -list</strong></span> 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
+ will be retained.
+ </p>
+ <p>
+ <span class="command"><strong>rndc signing -nsec3param</strong></span> sets
+ the NSEC3 parameters for a zone. This is the
+ only supported mechanism for using NSEC3 with
+ <span class="command"><strong>inline-signing</strong></span> zones.
+ Parameters are specified in the same format as
+ an NSEC3PARAM resource record: hash algorithm,
+ flags, iterations, and salt, in that order.
+ </p>
+ <p>
+ Currently, the only defined value for hash algorithm
+ is <code class="literal">1</code>, representing SHA-1.
+ The <code class="option">flags</code> may be set to
+ <code class="literal">0</code> or <code class="literal">1</code>,
+ depending on whether you wish to set the opt-out
+ bit in the NSEC3 chain. <code class="option">iterations</code>
+ defines the number of additional times to apply
+ the algorithm when generating an NSEC3 hash. The
+ <code class="option">salt</code> is a string of data expressed
+ in hexadecimal, a hyphen (`-') if no salt is
+ to be used, or the keyword <code class="literal">auto</code>,
+ which causes <span class="command"><strong>named</strong></span> to generate a
+ random 64-bit salt.
+ </p>
+ <p>
+ So, for example, to create an NSEC3 chain using
+ the SHA-1 hash algorithm, no opt-out flag,
+ 10 iterations, and a salt value of "FFFF", use:
+ <span class="command"><strong>rndc signing -nsec3param 1 0 10 FFFF <em class="replaceable"><code>zone</code></em></strong></span>.
+ To set the opt-out flag, 15 iterations, and no
+ salt, use:
+ <span class="command"><strong>rndc signing -nsec3param 1 1 15 - <em class="replaceable"><code>zone</code></em></strong></span>.
+ </p>
+ <p>
+ <span class="command"><strong>rndc signing -nsec3param none</strong></span>
+ removes an existing NSEC3 chain and replaces it
+ with NSEC.
+ </p>
+ <p>
+ <span class="command"><strong>rndc signing -serial value</strong></span> sets
+ the serial number of the zone to value. If the value
+ would cause the serial number to go backwards it will
+ be rejected. The primary use is to set the serial on
+ inline signed zones.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>stats</code></strong></span></dt>
+<dd>
+ <p>
+ Write server statistics to the statistics file.
+ (See the <span class="command"><strong>statistics-file</strong></span> option in
+ the BIND 9 Administrator Reference Manual.)
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>status</code></strong></span></dt>
+<dd>
+ <p>
+ Display status of the server.
+ Note that the number of zones includes the internal <span class="command"><strong>bind/CH</strong></span> zone
+ and the default <span class="command"><strong>./IN</strong></span>
+ hint zone if there is not an
+ explicit root zone configured.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>stop [<span class="optional">-p</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Stop 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 <code class="option">-p</code> is specified <span class="command"><strong>named</strong></span>'s process id is returned.
+ This allows an external process to determine when <span class="command"><strong>named</strong></span>
+ had completed stopping.
+ </p>
+ <p>See also <span class="command"><strong>rndc halt</strong></span>.</p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>sync [<span class="optional">-clean</span>] [<span class="optional"><em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Sync 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.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>thaw [<span class="optional"><em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ Enable 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 will no longer be refused. If
+ the zone has changed and the
+ <span class="command"><strong>ixfr-from-differences</strong></span> option is
+ in use, then the journal file will be updated to
+ reflect changes in the zone. Otherwise, if the
+ zone has changed, any existing journal file will be
+ removed.
+ </p>
+ <p>See also <span class="command"><strong>rndc freeze</strong></span>.</p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>trace</code></strong></span></dt>
+<dd>
+ <p>
+ Increment the servers debugging level by one.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>trace <em class="replaceable"><code>level</code></em></code></strong></span></dt>
+<dd>
+ <p>
+ Sets the server's debugging level to an explicit
+ value.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc notrace</strong></span>.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>tsig-delete</code></strong> <em class="replaceable"><code>keyname</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span></dt>
+<dd>
+ <p>
+ Delete a given TKEY-negotiated key from the server.
+ (This does not apply to statically configured TSIG
+ keys.)
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>tsig-list</code></strong></span></dt>
+<dd>
+ <p>
+ List the names of all TSIG keys currently configured
+ for use by <span class="command"><strong>named</strong></span> in each view. The
+ list both statically configured keys and dynamic
+ TKEY-negotiated keys.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>validation ( on | off | status ) [<span class="optional"><em class="replaceable"><code>view ...</code></em></span>] </code></strong></span></dt>
+<dd>
+ <p>
+ Enable, disable, or check the current status of
+ DNSSEC validation.
+ Note <span class="command"><strong>dnssec-enable</strong></span> also needs to be
+ set to <strong class="userinput"><code>yes</code></strong> or
+ <strong class="userinput"><code>auto</code></strong> to be effective.
+ It defaults to enabled.
+ </p>
+ </dd>
+<dt><span class="term"><strong class="userinput"><code>zonestatus <em class="replaceable"><code>zone</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em> [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd>
+ <p>
+ 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.
+ </p>
+ <p>
+ See also <span class="command"><strong>rndc showzone</strong></span>.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>LIMITATIONS</h2>
+
+ <p>
+ There is currently no way to provide the shared secret for a
+ <code class="option">key_id</code> without using the configuration file.
+ </p>
+ <p>
+ Several error messages could be clearer.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">rndc.conf</span>(5)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc-confgen</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named.conf</span>(5)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">ndc</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/rndc/util.c b/bin/rndc/util.c
new file mode 100644
index 0000000..0066e7c
--- /dev/null
+++ b/bin/rndc/util.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/print.h>
+
+#include "util.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);
+ fputs("\n", stderr);
+ }
+}
+
+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..fa4a62b
--- /dev/null
+++ b/bin/rndc/util.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef RNDC_UTIL_H
+#define RNDC_UTIL_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+#include <isc/formatcheck.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);
+
+ISC_PLATFORM_NORETURN_PRE void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+ISC_LANG_ENDDECLS
+
+#endif /* RNDC_UTIL_H */
diff --git a/bin/rndc/win32/rndc.dsp.in b/bin/rndc/win32/rndc.dsp.in
new file mode 100644
index 0000000..5bee95a
--- /dev/null
+++ b/bin/rndc/win32/rndc.dsp.in
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="rndc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=rndc - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rndc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndc.mak" CFG="rndc - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rndc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/util.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /profile @MACHINE@ /out:"../../../Build/Release/rndc.exe"
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/util.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/rndc.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rndc - @PLATFORM@ Release"
+# Name "rndc - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\rndc.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/rndc/win32/rndc.dsw b/bin/rndc/win32/rndc.dsw
new file mode 100644
index 0000000..97d3e43
--- /dev/null
+++ b/bin/rndc/win32/rndc.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rndc"=".\rndc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/rndc/win32/rndc.mak.in b/bin/rndc/win32/rndc.mak.in
new file mode 100644
index 0000000..242f0bb
--- /dev/null
+++ b/bin/rndc/win32/rndc.mak.in
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on rndc.dsp
+!IF "$(CFG)" == ""
+CFG=rndc - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to rndc - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rndc - @PLATFORM@ Release" && "$(CFG)" != "rndc - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndc.mak" CFG="rndc - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rndc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\rndc.exe"
+
+!ELSE
+
+ALL : "libbind9 - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" "libisccc - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "..\..\..\Build\Release\rndc.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN" "libisccc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\rndc.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\rndc.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\rndc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rndc.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /profile @MACHINE@ /out:"../../../Build/Release/rndc.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\rndc.obj" \
+ "$(INTDIR)\util.obj" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccc\win32\Release\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib"
+
+"..\..\..\Build\Release\rndc.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\rndc.exe" "$(OUTDIR)\rndc.bsc"
+
+!ELSE
+
+ALL : "libbind9 - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" "libisccc - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "..\..\..\Build\Debug\rndc.exe" "$(OUTDIR)\rndc.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ DebugCLEAN" "libisccc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\rndc.obj"
+ -@erase "$(INTDIR)\rndc.sbr"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\rndc.bsc"
+ -@erase "$(OUTDIR)\rndc.pdb"
+ -@erase "..\..\..\Build\Debug\rndc.exe"
+ -@erase "..\..\..\Build\Debug\rndc.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rndc.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\rndc.sbr" \
+ "$(INTDIR)\util.sbr"
+
+"$(OUTDIR)\rndc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rndc.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/rndc.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\rndc.obj" \
+ "$(INTDIR)\util.obj" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccc\win32\Debug\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib"
+
+"..\..\..\Build\Debug\rndc.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("rndc.dep")
+!INCLUDE "rndc.dep"
+!ELSE
+!MESSAGE Warning: cannot find "rndc.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release" || "$(CFG)" == "rndc - @PLATFORM@ Debug"
+SOURCE=..\rndc.c
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\rndc.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\rndc.obj" "$(INTDIR)\rndc.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\util.c
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+"libisccc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+"libisccc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+"libisccfg - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccfg - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+"libisccfg - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccfg - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/rndc/win32/rndc.vcxproj.filters.in b/bin/rndc/win32/rndc.vcxproj.filters.in
new file mode 100644
index 0000000..5187c16
--- /dev/null
+++ b/bin/rndc/win32/rndc.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rndc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/rndc/win32/rndc.vcxproj.in b/bin/rndc/win32/rndc.vcxproj.in
new file mode 100644
index 0000000..bdf4d32
--- /dev/null
+++ b/bin/rndc/win32/rndc.vcxproj.in
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{39721F26-8B80-4AA9-9826-2AEF7322C3D5}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>rndc</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>util.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>util.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\util.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rndc.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/rndc/win32/rndc.vcxproj.user b/bin/rndc/win32/rndc.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/rndc/win32/rndc.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/rndc/win32/rndcutil.dsp.in b/bin/rndc/win32/rndcutil.dsp.in
new file mode 100644
index 0000000..aafdd3c
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.dsp.in
@@ -0,0 +1,119 @@
+# Microsoft Developer Studio Project File - Name="rndcutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104
+
+CFG=rndcutil - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rndcutil.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndcutil.mak" CFG="rndcutil - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndcutil - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE "rndcutil - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndcutil - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fdutil
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/util.lib"
+LIB32=lib.exe
+# ADD BASE LIB32
+# ADD LIB32 /out:"Release/util.lib"
+
+!ELSEIF "$(CFG)" == "rndcutil - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fdutil
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug /out:"Debug/util.lib"
+LIB32=lib.exe
+# ADD BASE LIB32
+# ADD LIB32 /out:"Debug/util.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "rndcutil - @PLATFORM@ Release"
+# Name "rndcutil - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\util.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/rndc/win32/rndcutil.dsw b/bin/rndc/win32/rndcutil.dsw
new file mode 100644
index 0000000..c6d981a
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rndcutil"=".\rndcutil.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/rndc/win32/rndcutil.vcxproj.filters.in b/bin/rndc/win32/rndcutil.vcxproj.filters.in
new file mode 100644
index 0000000..766ea80
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\util.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/rndc/win32/rndcutil.vcxproj.in b/bin/rndc/win32/rndcutil.vcxproj.in
new file mode 100644
index 0000000..eac31af
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.vcxproj.in
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7C8681A1-E3A8-470E-9EEF-16054D111A19}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>rndcutil</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>util</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>util</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\util.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\util.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/rndc/win32/rndcutil.vcxproj.user b/bin/rndc/win32/rndcutil.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in
new file mode 100644
index 0000000..de68130
--- /dev/null
+++ b/bin/tests/Makefile.in
@@ -0,0 +1,85 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \
+ @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@
+CWARNINGS =
+BACKTRACECFLAGS = @BACKTRACECFLAGS@
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ @ISC_OPENSSL_LIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCDEPNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS = system @PKCS11_TOOLS@
+TESTDIRS = system
+
+# Test programs that are built by default:
+# cfg_test is needed for regenerating doc/misc/options
+# makejournal is needed by system tests
+# wire_test is needed for fuzz testing
+# other opptional test programs have been moved to ./optional
+
+# Alphabetically
+XTARGETS = all_tests
+TARGETS = cfg_test@EXEEXT@ makejournal@EXEEXT@ \
+ wire_test@EXEEXT@ @XTARGETS@
+
+SRCS = cfg_test.c makejournal.c wire_test.c
+
+@BIND9_MAKE_RULES@
+
+.NOTPARALLEL:
+
+.PHONY:
+all_tests:
+ echo "making depend in `pwd`/optional"; \
+ (cd optional; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" $@)
+
+wire_test@EXEEXT@: wire_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ wire_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+cfg_test@EXEEXT@: cfg_test.@O@ ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ cfg_test.@O@ \
+ ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+makejournal@EXEEXT@: makejournal.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ makejournal.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+distclean::
+ rm -f headerdep_test.sh
+
+clean distclean::
+ rm -f ${TARGETS}
+ ( cd optional; $(MAKE) $@)
+
+check: test
+
+test:
+ @for dir in $(SUBDIRS) ;\
+ do \
+ ( cd $$dir; $(MAKE) test ) ;\
+ done
diff --git a/bin/tests/bigtest/README b/bin/tests/bigtest/README
new file mode 100644
index 0000000..0daea5c
--- /dev/null
+++ b/bin/tests/bigtest/README
@@ -0,0 +1,18 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+ bash buildzones.sh < zones # creates setup, run, servers/* master/*
+ # named.conf
+ sudo sh setup # configure interfaces
+ sh run # setup
+
+ ../named/named [-g] -c named.conf
+
+ sh tests.sh < zones
+
+ sudo sh teardown # teardown interfaces
+
+The test server can controlled with
+
+ rndc -k rndc.key -s 127.127.0.0 -p 5300
diff --git a/bin/tests/bigtest/buildzones.sh b/bin/tests/bigtest/buildzones.sh
new file mode 100644
index 0000000..f8d531a
--- /dev/null
+++ b/bin/tests/bigtest/buildzones.sh
@@ -0,0 +1,267 @@
+#!/bin/bash
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. ../conf.sh
+
+addr=127.127.0.0
+ttl=300
+named=${NAMED}
+keygen=${KEYGEN}
+dsfromkey=${DSFROMKEY}
+
+nextaddr() {
+ OLDIF="$IFS"
+ IFS="${IFS}."
+ set $1
+ IFS="$OLDIFS"
+ _a=$1 _b=$2 _c=$3 _d=$4
+ _d=$(($_d + 1))
+ case $_d in
+ 256) _c=$(($_c + 1)); _d=0;;
+ esac
+ case $_c in
+ 256) _b=$(($_b + 1)); _c=0;;
+ esac
+ echo $_a.$_b.$_c.$_d
+}
+
+parent() {
+ OLDIF="$IFS"
+ IFS="${IFS}."
+ set $1
+ IFS="$OLDIFS"
+ shift
+ while [ $# -ne 0 ]
+ do
+ printf %s ${1}
+ shift
+ printf %s ${1:+.}
+
+ done
+}
+
+blackhole() {
+ echo 'options {'
+ echo ' port 5300;'
+ echo " listen-on { $1; };"
+ echo " query-source $1;"
+ echo " notify-source $1;"
+ echo " transfer-source $1;"
+ echo ' key-directory "keys";'
+ echo " recursion ${2:-no};"
+ echo ' pid-file "pids/'"${addr}"'.pid";'
+ echo ' blackhole { 127.127.0.0; };'
+ echo '};'
+}
+
+refuse() {
+ echo 'options {'
+ echo ' port 5300;'
+ echo " listen-on { $1; };"
+ echo " query-source $1;"
+ echo " notify-source $1;"
+ echo " transfer-source $1;"
+ echo ' key-directory "keys";'
+ echo " recursion ${2:-no};"
+ echo ' pid-file "pids/'"${addr}"'.pid";'
+ echo ' allow-query { !127.127.0.0; any; };'
+ echo '};'
+}
+
+options() {
+ echo 'options {'
+ echo ' port 5300;'
+ echo " listen-on { $1; };"
+ echo " query-source $1;"
+ echo " notify-source $1;"
+ echo " transfer-source $1;"
+ echo ' key-directory "keys";'
+ echo " recursion ${2:-no};"
+ echo ' pid-file "pids/'"${addr}"'.pid";'
+ echo '};'
+}
+
+controls() {
+ echo 'include "rndc.key";'
+ echo "controls { inet $addr port 9953 allow { any; } keys { "rndc-key"; }; };"
+}
+
+delay() {
+ _s=$1
+ OLDIF="$IFS"
+ IFS="${IFS}/"
+ set ${2:-.}
+ IFS="$OLDIFS"
+
+ case $1 in
+ .) _d=;;
+ *) _d=$1;;
+ esac
+ case $_s in
+ 1) echo -T delay=${_d:-100};;
+ 2) echo -T delay=${2:-50};;
+ 3) echo -T delay=${3:-150};;
+ 4) echo -T delay=${4:-250};;
+ 5) echo -T delay=${5:-125};;
+ 6) echo -T delay=${6:-25};;
+ 7) echo -T delay=${7:-75};;
+ 8) echo -T delay=${8:-125};;
+ 9) echo -T delay=${9:-10};;
+ 10) echo -T delay=${10:-40};;
+ 11) echo -T delay=${11:-80};;
+ 12) echo -T delay=${12:-90};;
+ *) echo -T delay=50;;
+ esac
+}
+
+trusted-keys () {
+ awk '$3 == "DNSKEY" {
+ b = ""; for (i=7; i <= NF; i++) { b = b $i; };
+ print "trusted-keys { \""$1"\"",$4,$5,$6,"\""b"\"; };" };'
+}
+
+signed-zone () {
+ echo "zone "'"'"${1:-.}"'"'" {"
+ echo " type master;"
+ echo " file "'"'"master/${2}.db"'"'";"
+ echo " auto-dnssec maintain;"
+ echo " allow-update { any; };"
+ echo "};"
+}
+
+unsigned-zone () {
+ echo "zone "'"'"${1:-.}"'"'" {"
+ echo " type master;"
+ echo " file "'"'"master/${2}.db"'"'";"
+ echo "};"
+}
+
+slave-zone () {
+ echo "zone "'"'"${zone:-.}"'"'" {"
+ echo " type slave;"
+ echo " masters { ${master}; };"
+ echo "};"
+}
+
+rm -rf servers master keys setup teardown run
+mkdir -p servers
+mkdir -p master
+mkdir -p keys
+
+echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup
+echo "ifconfig lo0 $addr -alias" >> teardown
+controls $addr > named.conf
+options $addr yes >> named.conf
+echo 'zone "." { type hint; file "master/hint.db"; };' >> named.conf
+
+while read zone servers nsfmt signed delay blackhole refuse flags
+do
+ i=1
+ case "${zone}" in
+ .) file=root zone=;;
+ *) file="$zone";;
+ esac
+ if [ "${zone}" != "" ] ; then
+ p=$(parent $zone)
+ case "${p}" in
+ "") p=root;;
+ esac
+ else
+ p=hint
+ fi
+ #echo "zone='${zone}' parent='${p}'"
+ addr=$(nextaddr $addr)
+ ns=$(printf "$nsfmt" ${i} "${zone}")
+ d=$(delay $i ${delay:-.})
+
+ echo "${zone}. ${ttl} soa ${ns}. hostmaster.${zone}${zone:+.} 1 3600 1200 604800 1200" >> master/${file}.db
+ echo "${zone}. ${ttl} ns ${ns}." >> master/${file}.db
+ echo "${ns}. ${ttl} a ${addr}" >> master/${file}.db
+ echo "${zone}. ${ttl} ns ${ns}." >> master/${p}.db
+ echo "${ns}. ${ttl} a ${addr}" >> master/${p}.db
+ if [ $signed = "S" ]; then
+ kskkey=`${keygen} -K keys -f KSK ${zone:-.}`
+ zskkey=`${keygen} -K keys ${zone:-.}`
+ if [ "${zone}" != "" ] ; then
+ ${dsfromkey} -T ${ttl} keys/${kskkey}.key >> master/${p}.db
+ else
+ trusted-keys < keys/${kskkey}.key >> named.conf
+ fi
+ fi
+ echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup
+ echo "ifconfig lo0 $addr -alias" >> teardown
+ echo "${named} -D bigtest -c servers/${addr}.conf $d $flags" >> run
+ options ${addr} > servers/${addr}.conf
+ case ${signed} in
+ S) signed-zone ${zone:-.} ${file} >> servers/${addr}.conf;;
+ P) unsigned-zone ${zone:-.} ${file} >> servers/${addr}.conf;;
+ *) echo ${signed}; exit 1;;
+ esac
+
+ # slave servers
+ while [ $i -lt $servers ]
+ do
+ master=$addr
+ i=$(($i + 1))
+ ns=$(printf "$nsfmt" ${i} "${zone}")
+ d=$(delay $i ${delay:-.})
+ addr=$(nextaddr $addr)
+ echo "${zone}. ${ttl} ns ${ns}." >> master/${file}.db
+ echo "${ns}. ${ttl} a ${addr}" >> master/${file}.db
+ echo "${zone}. ${ttl} ns ${ns}." >> master/${p}.db
+ echo "${ns}. ${ttl} a ${addr}" >> master/${p}.db
+ echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup
+ echo "ifconfig lo0 $addr -alias" >> teardown
+ echo "${named} -D bigtest -c servers/${addr}.conf $d $flags" >> run
+ if [ $i = ${refuse:-.} ]
+ then
+ refuse $addr > servers/${addr}.conf
+ elif [ $i = ${blackhole:-.} ]
+ then
+ blackhole $addr > servers/${addr}.conf
+ else
+ options $addr > servers/${addr}.conf
+ fi
+ slave-zone ${zone:-.} ${master} >> servers/${addr}.conf
+ done
+ if [ "${zone}" != "" ] ; then
+ echo "www.${zone}. ${ttl} a 127.0.0.1" >> master/${file}.db
+ echo "www.${zone}. ${ttl} aaaa ::1" >> master/${file}.db
+ echo "${zone}. ${ttl} mx 10 mail.${zone}." >> master/${file}.db
+ echo "mail.${zone}. ${ttl} a 127.0.0.1" >> master/${file}.db
+ echo "mail.${zone}. ${ttl} aaaa ::1" >> master/${file}.db
+ echo "*.big.${zone}. ${ttl} txt (" >> master/${file}.db
+ i=0
+ while [ $i -lt 150 ]
+ do
+ echo "1234567890" >> master/${file}.db
+ i=$(($i + 1))
+ done
+ echo ")" >> master/${file}.db
+ echo "*.medium.${zone}. ${ttl} txt (" >> master/${file}.db
+ i=0
+ while [ $i -lt 120 ]
+ do
+ echo "1234567890" >> master/${file}.db
+ i=$(($i + 1))
+ done
+ echo ")" >> master/${file}.db
+ echo "*.medium.${zone}. ${ttl} txt (" >> master/${file}.db
+ i=0
+ while [ $i -lt 120 ]
+ do
+ echo "1234567890" >> master/${file}.db
+ i=$(($i + 1))
+ done
+ echo ")" >> master/${file}.db
+ fi
+done
diff --git a/bin/tests/bigtest/rndc.key b/bin/tests/bigtest/rndc.key
new file mode 100644
index 0000000..f279e14
--- /dev/null
+++ b/bin/tests/bigtest/rndc.key
@@ -0,0 +1,5 @@
+key "rndc-key" {
+ algorithm hmac-md5;
+ secret "xxxxxxxxxxxxxxxxxxxxHg==";
+};
+
diff --git a/bin/tests/bigtest/tests.sh b/bin/tests/bigtest/tests.sh
new file mode 100644
index 0000000..7b3bd8f
--- /dev/null
+++ b/bin/tests/bigtest/tests.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+TOP=$( (cd ../../.. && pwd) )
+dig=${TOP}/bin/dig/dig
+
+cmd="${dig} -p 5300 @127.127.0.0 txt"
+inner() {
+ zone=$1 i=$2 to=$3
+ x=$i
+ dout=dig$x.out
+ tout=time$x.out
+ while [ $i -lt $to ]
+ do
+ case $zone in
+ .) zone=;;
+ esac
+
+ (time -p $cmd $i.${sub}$zone > $dout ) 2> $tout
+ s=`sed -n '/real/s/[^0-9]*\([0-9]*\)\..*/\1/p' $tout`
+ case $s in
+ 0);;
+ 1) t1=`expr ${t1:-0} + 1`;;
+ 2) t2=`expr ${t2:-0} + 1`;;
+ 3) t3=`expr ${t3:-0} + 1`;;
+ *) echo $i `grep real $tout`;;
+ esac
+
+ grep "status: \(NXDOMAIN\|NOERROR\)" $dout > /dev/null || {
+ echo $cmd $i.${sub}$zone
+ cat $dout
+ }
+ i=`expr $i + 1`
+ done
+ if test ${t1:-0} -ne 0 -o ${t2:-0} -ne 0 -o ${t3:-0} -ne 0
+ then
+ echo "$x timeouts: t1=${t1:-0} t2=${t2:-0} t3=${t3:-0}"
+ fi
+}
+
+while read zone rest
+do
+ for sub in "" medium. big.
+ do
+ case $zone in
+ .) echo doing ${sub:-.};;
+ *) echo doing $sub$zone;;
+ esac
+ ( inner $zone 1 100) &
+ ( inner $zone 101 200) &
+ ( inner $zone 201 300) &
+ ( inner $zone 301 400) &
+ ( inner $zone 401 500) &
+ ( inner $zone 501 600) &
+ ( inner $zone 601 700) &
+ ( inner $zone 701 800) &
+ ( inner $zone 801 900) &
+ ( inner $zone 901 1000) &
+ ( inner $zone 1001 1100) &
+ ( inner $zone 1101 1200) &
+ ( inner $zone 1201 1300) &
+ ( inner $zone 1301 1400) &
+ ( inner $zone 1401 1500) &
+ ( inner $zone 1501 1600) &
+ ( inner $zone 1601 1700) &
+ wait
+ done
+done
diff --git a/bin/tests/bigtest/zones b/bin/tests/bigtest/zones
new file mode 100644
index 0000000..0bdcdfe
--- /dev/null
+++ b/bin/tests/bigtest/zones
@@ -0,0 +1,18 @@
+noedns-1.tld 1 ns%u.%s P . x x -T noedns
+dropedns-1.tld 1 ns%u.%s P . x x -T dropedns
+maxudp512-1.tld 1 ns%u.%s S . x x -T maxudp=512
+maxudp1460-1.tld 1 ns%u.%s S . x x -T maxudp=1460
+plain-1.tld 1 ns%u.%s S . x x
+noedns-3.tld 3 ns%u.%s P . 2 x -T noedns
+dropedns-3.tld 3 ns%u.%s P . 2 x -T dropedns
+maxudp512-3.tld 3 ns%u.%s S . x x -T maxudp=512
+maxudp1460-3.tld 3 ns%u.%s S . x x -T maxudp=1460
+plain-3.tld 3 ns%u.%s S . x 3
+noedns-5.tld 5 ns%u.%s P . 3 x -T noedns
+dropedns-5.tld 5 ns%u.%s P . x x -T dropedns
+maxudp512-5.tld 5 ns%u.%s S . x x -T maxudp=512
+maxudp1460-5.tld 5 ns%u.%s S . x x -T maxudp=1460
+400ms-1.tld 5 ns%u.%s S 400/400/400/400/400 2 x
+plain-5.tld 5 ns%u.%s S . x x
+tld 12 ns%u.%s S . 5 8
+. 12 ns%u.root-servers.nil%s S . x x
diff --git a/bin/tests/cfg_test.c b/bin/tests/cfg_test.c
new file mode 100644
index 0000000..4d63c3b
--- /dev/null
+++ b/bin/tests/cfg_test.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/grammar.h>
+#include <isccfg/namedconf.h>
+
+#include <dns/log.h>
+
+static void
+check_result(isc_result_t result, const char *format, ...) {
+ va_list args;
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, ": %s\n", isc_result_totext(result));
+ exit(1);
+}
+
+static void
+output(void *closure, const char *text, int textlen) {
+ UNUSED(closure);
+ (void) fwrite(text, 1, textlen, stdout);
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: cfg_test --rndc|--named "
+ "[--grammar] [--memstats] conffile\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ isc_mem_t *mctx = NULL;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_logdestination_t destination;
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *cfg = NULL;
+ cfg_type_t *type = NULL;
+ bool grammar = false;
+ bool memstats = false;
+ char *filename = NULL;
+ unsigned int zonetype = 0;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ result = isc_log_create(mctx, &lctx, &lcfg);
+ check_result(result, "isc_log_create()");
+ isc_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME);
+ check_result(result, "isc_log_createchannel()");
+ result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
+ check_result(result, "isc_log_usechannel()");
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(lctx, 2);
+
+ if (argc < 3)
+ usage();
+
+ while (argc > 1) {
+ if (strcmp(argv[1], "--grammar") == 0) {
+ grammar = true;
+ } else if (strcmp(argv[1], "--zonegrammar") == 0) {
+ argv++, argc--;
+ if (argc <= 1) {
+ usage();
+ }
+ if (strcmp(argv[1], "master") == 0 ||
+ strcmp(argv[1], "primary") == 0)
+ {
+ zonetype = CFG_ZONE_MASTER;
+ } else if (strcmp(argv[1], "slave") == 0 ||
+ strcmp(argv[1], "seconary") == 0)
+ {
+ zonetype = CFG_ZONE_SLAVE;
+ } else if (strcmp(argv[1], "stub") == 0) {
+ zonetype = CFG_ZONE_STUB;
+ } else if (strcmp(argv[1], "static-stub") == 0) {
+ zonetype = CFG_ZONE_STATICSTUB;
+ } else if (strcmp(argv[1], "hint") == 0) {
+ zonetype = CFG_ZONE_HINT;
+ } else if (strcmp(argv[1], "forward") == 0) {
+ zonetype = CFG_ZONE_FORWARD;
+ } else if (strcmp(argv[1], "redirect") == 0) {
+ zonetype = CFG_ZONE_REDIRECT;
+ } else if (strcmp(argv[1], "delegation-only") == 0) {
+ zonetype = CFG_ZONE_DELEGATION;
+ } else if (strcmp(argv[1], "in-view") == 0) {
+ zonetype = CFG_ZONE_INVIEW;
+ } else {
+ usage();
+ }
+ } else if (strcmp(argv[1], "--memstats") == 0) {
+ memstats = true;
+ } else if (strcmp(argv[1], "--named") == 0) {
+ type = &cfg_type_namedconf;
+ } else if (strcmp(argv[1], "--rndc") == 0) {
+ type = &cfg_type_rndcconf;
+ } else if (argv[1][0] == '-') {
+ usage();
+ } else {
+ filename = argv[1];
+ }
+ argv++, argc--;
+ }
+
+ if (grammar) {
+ if (type == NULL)
+ usage();
+ cfg_print_grammar(type, output, NULL);
+ } else if (zonetype != 0) {
+ cfg_print_zonegrammar(zonetype, output, NULL);
+ } else {
+ if (type == NULL || filename == NULL)
+ usage();
+ RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &pctx) == ISC_R_SUCCESS);
+
+ result = cfg_parse_file(pctx, filename, type, &cfg);
+
+ fprintf(stderr, "read config: %s\n", isc_result_totext(result));
+
+ if (result != ISC_R_SUCCESS)
+ exit(1);
+
+ cfg_print(cfg, output, NULL);
+
+ cfg_obj_destroy(pctx, &cfg);
+
+ cfg_parser_destroy(&pctx);
+ }
+
+ isc_log_destroy(&lctx);
+ if (memstats)
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+
+ fflush(stdout);
+ if (ferror(stdout)) {
+ fprintf(stderr, "write error\n");
+ return (1);
+ } else
+ return (0);
+}
diff --git a/bin/tests/fromhex.pl b/bin/tests/fromhex.pl
new file mode 100644
index 0000000..ab8a74c
--- /dev/null
+++ b/bin/tests/fromhex.pl
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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/headerdep_test.sh.in b/bin/tests/headerdep_test.sh.in
new file mode 100644
index 0000000..3a94d47
--- /dev/null
+++ b/bin/tests/headerdep_test.sh.in
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Check the installed bind9 headers to make sure that no header
+# depends on another header having been included first.
+#
+
+prefix=@prefix@
+tmp=/tmp/thdr$$.tmp
+
+status=0
+
+echo "Checking for header interdependencies..."
+
+# Make a list of header files.
+(cd $prefix/include; find . -name '*.h' -print | sed 's!^./!!') > $tmp
+
+# Check each header.
+while read h
+do
+ echo " - <$h>"
+
+ # Build a test program.
+ cat <<EOF >test.c
+#include <$h>
+EOF
+
+ # Compile the test program.
+ if
+ gcc @STD_CWARNINGS@ @STD_CINCLUDES@ -I$prefix/include -c test.c 2>&1
+ then
+ :
+ else
+ status=1
+ fi
+done <$tmp
+
+rm -f test.c test.o $tmp
+
+exit $status
diff --git a/bin/tests/makejournal.c b/bin/tests/makejournal.c
new file mode 100644
index 0000000..61a41b0
--- /dev/null
+++ b/bin/tests/makejournal.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdbool.h>
+
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.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 <isc/print.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#include <stdlib.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;
+isc_entropy_t *ectx = NULL;
+
+static bool hash_active = false, 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);
+ 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;
+ CHECK(isc_mem_create(0, 0, &mctx));
+ CHECK(isc_entropy_create(mctx, &ectx));
+
+ CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+ hash_active = true;
+
+ CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING));
+ dst_active = true;
+
+ CHECK(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;
+ CHECK(isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC,
+ &destination, 0));
+ CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL));
+
+ dns_result_register();
+
+ 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 (hash_active) {
+ isc_hash_destroy();
+ hash_active = false;
+ }
+ if (ectx != NULL)
+ isc_entropy_detach(&ectx);
+ if (mctx != NULL)
+ isc_mem_destroy(&mctx);
+
+ return(result != ISC_R_SUCCESS ? 1 : 0);
+}
diff --git a/bin/tests/named.conf b/bin/tests/named.conf
new file mode 100644
index 0000000..5673e98
--- /dev/null
+++ b/bin/tests/named.conf
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is a worthless, nonrunnable example of a named.conf file that has
+ * every conceivable syntax element in use. We use it to test the parser.
+ * It could also be used as a conceptual template for users of new features.
+ */
+
+/*
+ * C-style comments are OK
+ */
+
+// So are C++-style comments
+
+# So are shell-style comments
+
+// watch out for ";" -- it's important!
+
+options {
+ additional-from-auth true;
+ additional-from-cache false;
+
+ version "my version string";
+ random-device "/dev/random";
+ directory "/tmp";
+
+ port 666;
+
+ sig-validity-interval 33;
+
+# Obsolete
+ named-xfer "/usr/libexec/named-xfer"; // _PATH_XFER
+
+ dump-file "named_dump.db"; // _PATH_DUMPFILE
+ pid-file "/var/run/named.pid"; // _PATH_PIDFILE
+ statistics-file "named.stats"; // _PATH_STATS
+ memstatistics-file "named.memstats"; // _PATH_MEMSTATS
+
+ max-cache-ttl 999;
+ auth-nxdomain yes; // always set AA on NXDOMAIN.
+ // don't set this to 'no' unless
+ // you know what you're doing -- older
+ // servers won't like it.
+
+# Obsolete
+ deallocate-on-exit no;
+
+ dialup yes;
+
+# Obsolete
+ fake-iquery no;
+
+ fetch-glue yes;
+ has-old-clients yes;
+ host-statistics no;
+
+# Obsolete
+ multiple-cnames no; // if yes, then a name my have more
+ // than one CNAME RR. This use
+ // is non-standard and is not
+ // recommended, but it is available
+ // because previous releases supported
+ // it and it was used by large sites
+ // for load balancing.
+
+ notify yes; // send NOTIFY messages. You can set
+ // notify on a zone-by-zone
+ // basis in the "zone" statement
+ // see (below)
+ recursion yes;
+ rfc2308-type1 no;
+
+# Obsolete
+ use-id-pool yes;
+
+# Obsolete
+ treat-cr-as-space yes;
+
+ also-notify { 10.0.2.3; };
+
+ // The "forward" option is only meaningful if you've defined
+ // forwarders. "first" gives the normal BIND
+ // forwarding behavior, i.e. ask the forwarders first, and if that
+ // doesn't work then do the full lookup. You can also say
+ // "forward only;" which is what used to be specified with
+ // "slave" or "options forward-only". "only" will never attempt
+ // a full lookup; only the forwarders will be used.
+ forward first;
+ forwarders {
+ 1.2.3.4;
+ 5.6.7.8;
+ };
+
+ check-names master fail;
+ check-names slave warn;
+ check-names response ignore;
+
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-recursion { !any; };
+ blackhole { 45/24; };
+ keep-response-order { 46/24; };
+
+ listen-on {
+ 10/24;
+ 10.0.0.3;
+ };
+
+ listen-on port 53 { any; };
+
+ listen-on { 5.6.7.8; };
+
+ listen-on port 1234 {
+ !1.2.3.4;
+ 1.2.3/24;
+ };
+
+ listen-on-v6 {
+ 1:1:1:1:1:1:1:1;
+ };
+
+ listen-on-v6 port 777 {
+ 2:2:2:2:2:2:2:2;
+ };
+
+ query-source-v6 address 8:7:6:5:4:3:2:1 port *;
+ query-source port * address 10.0.0.54 ;
+
+ lame-ttl 444;
+
+ max-transfer-time-in 300;
+ max-transfer-time-out 10;
+ max-transfer-idle-in 100;
+ max-transfer-idle-out 11;
+
+ max-retry-time 1234;
+ min-retry-time 1111;
+ max-refresh-time 888;
+ min-refresh-time 777;
+
+ max-ncache-ttl 333;
+ min-roots 15;
+ serial-queries 34;
+
+ transfer-format one-answer;
+
+ transfers-in 10;
+ transfers-per-ns 2;
+ transfers-out 0;
+
+ transfer-source 10.0.0.5;
+ transfer-source-v6 4:3:2:1:5:6:7:8;
+
+ request-ixfr yes;
+ provide-ixfr yes;
+
+# Now called 'provide-ixfr'
+# maintain-ixfr-base no; // If yes, keep transaction log file for IXFR
+
+ max-ixfr-log-size 20m;
+ coresize 100;
+ datasize 101;
+ files 230;
+ max-cache-size 1m;
+ stacksize 231;
+ cleaning-interval 1000;
+ heartbeat-interval 1001;
+ interface-interval 1002;
+ statistics-interval 1003;
+
+ topology {
+ 10/8;
+
+ !1.2.3/24;
+
+ { 1.2/16; 3/8; };
+
+
+ };
+
+ sortlist { 10/8; 11/8; };
+
+ tkey-domain "foo.com";
+ tkey-dhkey "xyz" 666 ;
+
+ rrset-order {
+ class IN type A name "foo" order random;
+ order cyclic;
+ };
+};
+
+/*
+ * Control listeners, for "ndc". Every nameserver needs at least one.
+ */
+controls {
+ // 'inet' lines without a 'port' defaults to 'port 953'
+ // 'keys' must be used and the list must have at least one entry
+ inet * port 52 allow { any; } keys { "key2"; };
+ unix "/var/run/ndc" perm 0600 owner 0 group 0; // ignored by named.
+ inet 10.0.0.1 allow { any; key foo; } keys { "key4";};
+ inet 10.0.0.2 allow { none; } keys { "key-1"; "key-2"; };
+ inet 10.0.0.2 allow { none; };
+};
+
+zone "master.demo.zone" {
+ type master; // what used to be called "primary"
+ database "somedb -option1 -option2 arg1 arg2 arg3";
+ file "master.demo.zone";
+ check-names fail;
+ allow-update { none; };
+ allow-update-forwarding { 10.0.0.5; !any; };
+ allow-transfer { any; };
+ allow-query { any; };
+ sig-validity-interval 990;
+ notify explicit;
+ also-notify { 1.0.0.1; }; // don't notify any nameservers other
+ // than those on the NS list for this
+ // zone
+ forward first;
+ forwarders { 10.0.0.3; 1:2:3:4:5:6:7:8; };
+};
+
+zone "slave.demo.zone" {
+ type slave; // what used to be called "secondary"
+ file "slave.demo.zone";
+ ixfr-base "slave.demo.zone.ixfr"; // File name for IXFR transaction log file
+ masters {
+ 1.2.3.4 port 10 key "foo"; // where to zone transfer from
+ 5.6.7.8;
+ 6.7.8.9 key "zippo";
+ };
+ transfer-source 10.0.0.53; // fixes multihoming problems
+ check-names warn;
+ allow-update { none; };
+ allow-transfer { any; };
+ allow-update-forwarding { any; };
+ allow-query { any; };
+ max-transfer-time-in 120; // if not set, global option is used.
+ max-transfer-time-out 1; // if not set, global option is used.
+ max-transfer-idle-in 2; // if not set, global option is used.
+ max-transfer-idle-out 3; // if not set, global option is used.
+ also-notify { 1.0.0.2; };
+ forward only;
+ forwarders { 10.45.45.45; 10.0.0.3; 1:2:3:4:5:6:7:8; };
+};
+
+key "non-viewkey" { secret "YWFh" ; algorithm "zzz" ; };
+
+view "test-view" in {
+ key "viewkey" { algorithm "xxx" ; secret "eXl5" ; };
+ also-notify { 10.2.2.3; };
+ trusted-keys {
+ foo.com. 4 3 2 "abdefghijklmnopqrstuvwxyz";
+ };
+ sig-validity-interval 45;
+ max-cache-size 100000;
+ allow-query { 10.0.0.30;};
+ additional-from-cache false;
+ additional-from-auth no;
+ match-clients { 10.0.0.1 ; };
+ check-names master warn;
+ check-names slave ignore;
+ check-names response fail;
+ auth-nxdomain false;
+ recursion true;
+ provide-ixfr false;
+ request-ixfr true;
+ fetch-glue true;
+ notify false;
+ rfc2308-type1 false;
+ transfer-source 10.0.0.55;
+ transfer-source-v6 4:3:8:1:5:6:7:8;
+ query-source port * address 10.0.0.54 ;
+ query-source-v6 address 6:6:6:6:6:6:6:6 port *;
+ max-transfer-time-out 45;
+ max-transfer-idle-out 55;
+ cleaning-interval 100;
+ min-roots 3;
+ lame-ttl 477;
+ max-ncache-ttl 333;
+ max-cache-ttl 777;
+ transfer-format many-answers;
+ max-retry-time 7;
+ min-retry-time 4;
+ max-refresh-time 999;
+ min-refresh-time 111;
+
+ zone "view-zone.com" {
+ type master;
+ allow-update-forwarding { 10.0.0.34;};
+ file "view-zone-master";
+ };
+
+ server 5.6.7.8 {
+ keys "viewkey";
+ };
+
+ server 10.9.8.7 {
+ keys "non-viewkey";
+ };
+ dialup yes;
+};
+
+
+zone "stub.demo.zone" {
+ type stub; // stub zones are like slave zones,
+ // except that only the NS records
+ // are transferred.
+ dialup yes;
+ file "stub.demo.zone";
+ masters {
+ 1.2.3.4 ; // where to zone transfer from
+ 5.6.7.8 port 999;
+ };
+ check-names warn;
+ allow-update { none; };
+ allow-transfer { any; };
+ allow-query { any; };
+
+ max-retry-time 10;
+ min-retry-time 11;
+ max-refresh-time 12;
+ min-refresh-time 13;
+
+ max-transfer-time-in 120; // if not set, global option is used.
+ pubkey 257 255 1 "a useless key";
+ pubkey 257 255 1 "another useless key";
+};
+
+zone "." {
+ type hint; // used to be specified w/ "cache"
+ file "cache.db";
+// pubkey 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q==";
+};
+
+trusted-keys {
+ "." 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q==";
+};
+
+
+acl can_query { !1.2.3/24; any; }; // network 1.2.3.0 mask 255.255.255.0
+ // is disallowed; rest are OK
+acl can_axfr { 1.2.3.4; can_query; }; // host 1.2.3.4 and any host allowed
+ // by can_query are OK
+
+zone "disabled-zone.com" {
+ type master;
+ file "bar";
+
+ max-retry-time 100;
+ min-retry-time 110;
+ max-refresh-time 120;
+ min-refresh-time 130;
+};
+
+zone "non-default-acl.demo.zone" {
+ type master;
+ file "foo";
+ allow-query { can_query; };
+ allow-transfer { can_axfr; };
+ allow-update {
+ 1.2.3.4;
+ 5.6.7.8;
+ };
+ pubkey 666 665 664 "key of the beast";
+ // Errors trapped by parser:
+ // identity or name not absolute
+ // 'wildcard' match type and no wildcard character in name
+ //
+ // issues:
+ // - certain rdatatype values (such as "key") are config file keywords and
+ // must be quoted or a syntax error will occur.
+ //
+
+ update-policy {
+ grant root.domain. subdomain host.domain. A MX CNAME;
+ grant sub.root.domain. wildcard *.host.domain. A;
+ grant root.domain. name host.domain. a ns md mf cname soa mb mg
+ mr "null" wks ptr hinfo minfo mx txt rp afsdb x25
+ isdn rt nsap sig "key" px gpos aaaa loc nxt srv naptr kx
+ cert a6 dname opt unspec uri tkey tsig ;
+ grant foo.bar.com. self foo.bar.com. a;
+ };
+};
+
+key sample_key { // for TSIG; supported by parser
+ algorithm hmac-md5; // but not yet implemented in the
+ secret "eW91ciBzZWNyZXQgaGVyZQ=="; // rest of the server
+};
+
+key key2 {
+ algorithm hmac-md5;
+ secret "ZXJlaCB0ZXJjZXMgcm91eQ==";
+};
+
+acl key_acl { key sample_key; }; // a request signed with sample_key
+
+server 1.2.3.4 {
+ request-ixfr no;
+ provide-ixfr no;
+ bogus no; // if yes, we won't query or listen
+ // to this server
+ transfer-format one-answer; // set transfer format for this
+ // server (see the description of
+ // 'transfer-format' above)
+ // if not specified, the global option
+ // will be used
+ transfers 0; // not implemented
+ keys { "sample_key" }; // for TSIG; supported by the parser
+ // but not yet implemented in the
+ // rest of the server
+# Now called 'request-ixfr'
+# support-ixfr yes; // for IXFR supported by server
+ // if yes, the listed server talks IXFR
+};
+
+logging {
+ /*
+ * All log output goes to one or more "channels"; you can make as
+ * many of them as you want.
+ */
+
+ channel syslog_errors { // this channel will send errors or
+ syslog user; // or worse to syslog (user facility)
+ severity error;
+ };
+
+ channel stderr_errors {
+ stderr;
+ };
+
+ /*
+ * Channels have a severity level. Messages at severity levels
+ * greater than or equal to the channel's level will be logged on
+ * the channel. In order of decreasing severity, the levels are:
+ *
+ * critical a fatal error
+ * error
+ * warning
+ * notice a normal, but significant event
+ * info an informational message
+ * debug 1 the least detailed debugging info
+ * ...
+ * debug 99 the most detailed debugging info
+ */
+
+ /*
+ * Here are the built-in channels:
+ *
+ * channel default_syslog {
+ * syslog daemon;
+ * severity info;
+ * };
+ *
+ * channel default_debug {
+ * file "named.run"; // note: stderr is used instead
+ * // of "named.run" if the server
+ * // is started with the "-f"
+ * // option.
+ * severity dynamic; // this means log debugging
+ * // at whatever debugging level
+ * // the server is at, and don't
+ * // log anything if not
+ * // debugging.
+ * };
+ *
+ * channel null { // this is the bit bucket;
+ * file "/dev/null"; // any logging to this channel
+ * // is discarded.
+ * };
+ *
+ * channel default_stderr { // writes to stderr
+ * file "<stderr>"; // this is illustrative only;
+ * // there's currently no way
+ * // of saying "stderr" in the
+ * // configuration language.
+ * // i.e. don't try this at home.
+ * severity info;
+ * };
+ *
+ * default_stderr only works before the server daemonizes (i.e.
+ * during initial startup) or when it is running in foreground
+ * mode (-f command line option).
+ */
+
+ /*
+ * There are many categories, so you can send the logs
+ * you want to see wherever you want, without seeing logs you
+ * don't want. Right now the categories are
+ *
+ * default the catch-all. many things still
+ * aren't classified into categories, and
+ * they all end up here. also, if you
+ * don't specify any channels for a
+ * category, the default category is used
+ * instead.
+ * config high-level configuration file
+ * processing
+ * parser low-level configuration file processing
+ * queries what used to be called "query logging"
+ * lame-servers messages like "Lame server on ..."
+ * statistics
+ * panic if the server has to shut itself
+ * down due to an internal problem, it
+ * logs the problem here (as well as
+ * in the problem's native category)
+ * update dynamic update
+ * ncache negative caching
+ * xfer-in zone transfers we're receiving
+ * xfer-out zone transfers we're sending
+ * db all database operations
+ * eventlib debugging info from the event system
+ * (see below)
+ * packet dumps of packets received and sent
+ * (see below)
+ * notify the NOTIFY protocol
+ * cname messages like "XX points to a CNAME"
+ * security approved/unapproved requests
+ * os operating system problems
+ * insist consistency check failures
+ * maintenance periodic maintenance
+ * load zone loading
+ * response-checks messages like
+ * "Malformed response ..."
+ * "wrong ans. name ..."
+ * "unrelated additional info ..."
+ * "invalid RR type ..."
+ * "bad referral ..."
+ */
+
+ category parser {
+ syslog_errors; // you can log to as many channels
+ default_syslog; // as you want
+ };
+
+ category lame-servers { null; }; // don't log these at all
+
+ channel moderate_debug {
+ file "foo"; // foo
+ severity debug 3; // level 3 debugging to file
+ print-time yes; // timestamp log entries
+ print-category yes; // print category name
+ print-severity yes; // print severity level
+ /*
+ * Note that debugging must have been turned on either
+ * on the command line or with a signal to get debugging
+ * output (non-debugging output will still be written to
+ * this channel).
+ */
+ };
+
+ channel another {
+ file "bar" versions 99 size 10M;
+ severity info;
+ };
+
+ channel third {
+ file "bar" size 100000 versions unlimited;
+ severity debug; // use default debug level
+ };
+
+ /*
+ * If you don't want to see "zone XXXX loaded" messages but do
+ * want to see any problems, you could do the following.
+ */
+ channel no_info_messages {
+ syslog;
+ severity notice;
+ };
+
+ category load { no_info_messages; };
+
+ /*
+ * You can also define category "default"; it gets used when no
+ * "category" statement has been given for a category.
+ */
+ category default {
+ default_syslog;
+ moderate_debug;
+ };
+
+ /*
+ * If you don't define category default yourself, the default
+ * default category will be used. It is
+ *
+ * category default { default_syslog; default_debug; };
+ */
+
+ /*
+ * If you don't define category panic yourself, the default
+ * panic category will be used. It is
+ *
+ * category panic { default_syslog; default_stderr; };
+ */
+
+ /*
+ * Two categories, 'packet' and 'eventlib', are special. Only one
+ * channel may be assigned to each of them, and it must be a
+ * file channel. If you don't define them yourself, they default to
+ *
+ * category eventlib { default_debug; };
+ *
+ * category packet { default_debug; };
+ */
+};
+
+#include "filename"; // can't do within a statement
+
diff --git a/bin/tests/optional/Kchild.example.+003+04017.key b/bin/tests/optional/Kchild.example.+003+04017.key
new file mode 100644
index 0000000..9f5cbac
--- /dev/null
+++ b/bin/tests/optional/Kchild.example.+003+04017.key
@@ -0,0 +1 @@
+child.example. IN KEY 256 3 3 ALeiYGFXbil6PgHnkm5ZE67ygEVDvGT/gqZmLH7tGboofcPSfyhh1hpw dxZgJ26d/gynWMGVSYzaXfzsxpPoNeYn+qeevQoJOaxXXlfcy8Ik52Rm eW0J9mWlf9hsD7ShIhh1+0kRYGCOCaU25wIe3SLVkN3HgqiCBDYnBY0u nMkqRadiUnoEa3Tcvc9kJx9r9gDstR2A9A5sBhFLI/XQ0gViHHLVpQ4x hz+rTLb/xrBoAb5sQJT3xUjhhdNo9HuL6kwdLdSu//PCl1QnY9NpYPVV SKUo
diff --git a/bin/tests/optional/Kchild.example.+003+04017.private b/bin/tests/optional/Kchild.example.+003+04017.private
new file mode 100644
index 0000000..176ff98
--- /dev/null
+++ b/bin/tests/optional/Kchild.example.+003+04017.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.2
+Algorithm: 3 (DSA)
+Prime(p): vGT/gqZmLH7tGboofcPSfyhh1hpwdxZgJ26d/gynWMGVSYzaXfzsxpPoNeYn+qeevQoJOaxXXlfcy8Ik52RmeQ==
+Subprime(q): t6JgYVduKXo+AeeSblkTrvKARUM=
+Base(g): bQn2ZaV/2GwPtKEiGHX7SRFgYI4JpTbnAh7dItWQ3ceCqIIENicFjS6cySpFp2JSegRrdNy9z2QnH2v2AOy1HQ==
+Private_value(x): J1Ctez8+w1PTR56Hze3pGoe0Wag=
+Public_value(y): gPQObAYRSyP10NIFYhxy1aUOMYc/q0y2/8awaAG+bECU98VI4YXTaPR7i+pMHS3Urv/zwpdUJ2PTaWD1VUilKA==
diff --git a/bin/tests/optional/Makefile.in b/bin/tests/optional/Makefile.in
new file mode 100644
index 0000000..4442a80
--- /dev/null
+++ b/bin/tests/optional/Makefile.in
@@ -0,0 +1,299 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \
+ ${LWRES_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+
+CDEFINES = @CRYPTO@ @USE_GSSAPI@
+
+CWARNINGS =
+BACKTRACECFLAGS = @BACKTRACECFLAGS@
+
+DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+ISCNOSYMLIBS = ../../../lib/isc/libisc-nosymtbl.@A@ @ISC_OPENSSL_LIBS@
+ISCCFGLIBS = ../../../lib/isccfg/libisccfg.@A@
+LWRESDEPLIBS = ../../../lib/lwres/liblwres.@A@
+
+DNSDEPLIBS = ../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+ISCDEPNOSYMLIBS = ../../../lib/isc/libisc-nosymtbl.@A@
+ISCCFGDEPLIBS = ../../../lib/isccfg/libisccfg.@A@
+LWRESLIBS = ../../../lib/lwres/liblwres.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS =
+
+# These programs are not built by default, but only when
+# configured with --enable-developer or built explicitly with
+# "make all_tests"
+
+TARGETS = @XTARGETS@
+XTARGETS = adb_test@EXEEXT@ \
+ byaddr_test@EXEEXT@ \
+ backtrace_test@EXEEXT@ \
+ backtrace_test_nosymtbl@EXEEXT@ \
+ byname_test@EXEEXT@ \
+ db_test@EXEEXT@ \
+ dst_test@EXEEXT@ \
+ entropy_test@EXEEXT@ \
+ entropy2_test@EXEEXT@ \
+ gsstest@EXEEXT@ \
+ gxba_test@EXEEXT@ \
+ gxbn_test@EXEEXT@ \
+ hash_test@EXEEXT@ \
+ fsaccess_test@EXEEXT@ \
+ inter_test@EXEEXT@ \
+ keyboard_test@EXEEXT@ \
+ lex_test@EXEEXT@ \
+ lfsr_test@EXEEXT@ \
+ log_test@EXEEXT@ \
+ lwres_test@EXEEXT@ \
+ lwresconf_test@EXEEXT@ \
+ master_test@EXEEXT@ \
+ mempool_test@EXEEXT@ \
+ name_test@EXEEXT@ \
+ nsecify@EXEEXT@ \
+ ratelimiter_test@EXEEXT@ \
+ rbt_test@EXEEXT@ \
+ rwlock_test@EXEEXT@ \
+ serial_test@EXEEXT@ \
+ shutdown_test@EXEEXT@ \
+ sig0_test@EXEEXT@ \
+ sock_test@EXEEXT@ \
+ sym_test@EXEEXT@ \
+ task_test@EXEEXT@ \
+ timer_test@EXEEXT@ \
+ zone_test@EXEEXT@
+
+SRCS = ${XSRCS}
+XSRCS = adb_test.c \
+ byaddr_test.c \
+ backtrace_test.c \
+ byname_test.c \
+ db_test.c \
+ dst_test.c \
+ entropy_test.c \
+ entropy2_test.c \
+ hash_test.c \
+ fsaccess_test.c \
+ gsstest.c \
+ gxba_test.c \
+ gxbn_test.c \
+ inter_test.c \
+ keyboard_test.c \
+ lex_test.c \
+ lfsr_test.c \
+ log_test.c \
+ lwres_test.c \
+ lwresconf_test.c \
+ master_test.c \
+ mempool_test.c \
+ name_test.c \
+ nsecify.c \
+ ratelimiter_test.c \
+ rbt_test.c \
+ rwlock_test.c \
+ serial_test.c \
+ shutdown_test.c \
+ sig0_test.c \
+ sock_test.c \
+ sym_test.c \
+ task_test.c \
+ timer_test.c \
+ zone_test.c
+
+@BIND9_MAKE_RULES@
+
+# disable optimization for backtrace test to get the expected result
+BTTEST_CFLAGS = ${BACKTRACECFLAGS} ${EXT_CFLAGS} ${ALL_CPPFLAGS} -g \
+ ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS}
+
+all_tests: ${XTARGETS}
+
+adb_test@EXEEXT@: adb_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ adb_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+backtrace_test_nosymtbl@EXEEXT@: ${srcdir}/backtrace_test.c ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} -o $@ \
+ ${srcdir}/backtrace_test.c ${ISCLIBS} ${LIBS}
+
+backtrace_test@EXEEXT@: ${srcdir}/backtrace_test.c backtrace_test_nosymtbl@EXEEXT@
+ #first step: create a first symbol table
+ rm -f symtbl.c
+ if test X${MKSYMTBL_PROGRAM} != X; then \
+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \
+ backtrace_test_nosymtbl@EXEEXT@; else \
+ cp ${top_srcdir}/lib/isc/backtrace-emptytbl.c symtbl.c; fi
+ #second step: build a binary with the first symbol table
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} \
+ -o $@0 ${srcdir}/backtrace_test.c symtbl.c \
+ ${ISCNOSYMLIBS} ${LIBS}
+ rm -f symtbl.c
+ #third step: create a second symbol table
+ if test X${MKSYMTBL_PROGRAM} != X; then \
+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl $@0; else \
+ cp ${top_srcdir}/lib/isc/backtrace-emptytbl.c symtbl.c; fi
+ #fourth step: build the final binary
+ rm -f $@0
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} \
+ -o $@ ${srcdir}/backtrace_test.c symtbl.c ${ISCNOSYMLIBS} ${LIBS}
+ rm -f symtbl.c
+
+nsecify@EXEEXT@: nsecify.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsecify.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+byaddr_test@EXEEXT@: byaddr_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byaddr_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+byname_test@EXEEXT@: byname_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byname_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+lex_test@EXEEXT@: lex_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lex_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+lfsr_test@EXEEXT@: lfsr_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lfsr_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+log_test@EXEEXT@: log_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ log_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+name_test@EXEEXT@: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ name_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+hash_test@EXEEXT@: hash_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ hash_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+entropy_test@EXEEXT@: entropy_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+entropy2_test@EXEEXT@: entropy2_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy2_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+sock_test@EXEEXT@: sock_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sock_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+sym_test@EXEEXT@: sym_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sym_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+task_test@EXEEXT@: task_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ task_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+shutdown_test@EXEEXT@: shutdown_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ shutdown_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+timer_test@EXEEXT@: timer_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ timer_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+ratelimiter_test@EXEEXT@: ratelimiter_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ratelimiter_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+master_test@EXEEXT@: master_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ master_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ db_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+mempool_test@EXEEXT@: mempool_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ mempool_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+serial_test@EXEEXT@: serial_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ serial_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+zone_test@EXEEXT@: zone_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zone_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+fsaccess_test@EXEEXT@: fsaccess_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ fsaccess_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+inter_test@EXEEXT@: inter_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ inter_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+keyboard_test@EXEEXT@: keyboard_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ keyboard_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+lwresconf_test@EXEEXT@: lwresconf_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwresconf_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+lwres_test@EXEEXT@: lwres_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwres_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxbn_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxba_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+sig0_test@EXEEXT@: sig0_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sig0_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+dst_test@EXEEXT@: dst_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+ -o $@ dst_test.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+gsstest@EXEEXT@: gsstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+ -o $@ gsstest.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS} ${XTARGETS}
+ rm -f backtrace_test_symtbl.c
+
+check: test
+
+test:
+ @for dir in $(TESTDIRS) ;\
+ do \
+ ( cd $$dir; $(MAKE) test ) ;\
+ done
diff --git a/bin/tests/optional/adb_test.c b/bin/tests/optional/adb_test.c
new file mode 100644
index 0000000..9cd96a4
--- /dev/null
+++ b/bin/tests/optional/adb_test.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/print.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/dispatch.h>
+#include <dns/db.h>
+#include <dns/log.h>
+#include <dns/rootns.h>
+#include <dns/result.h>
+
+typedef struct client client_t;
+struct client {
+ dns_name_t name;
+ const char *target;
+ ISC_LINK(client_t) link;
+ dns_adbfind_t *find;
+};
+
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+static isc_mempool_t *cmp;
+static isc_log_t *lctx;
+static isc_logconfig_t *lcfg;
+static isc_taskmgr_t *taskmgr;
+static isc_socketmgr_t *socketmgr;
+static isc_timermgr_t *timermgr;
+static dns_dispatchmgr_t *dispatchmgr;
+static isc_task_t *t1, *t2;
+static dns_view_t *view;
+static dns_db_t *rootdb;
+static ISC_LIST(client_t) clients;
+static isc_mutex_t client_lock;
+static isc_stdtime_t now;
+static dns_adb_t *adb;
+
+static void
+check_result(isc_result_t result, const char *format, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+static void
+check_result(isc_result_t result, const char *format, ...) {
+ va_list args;
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, ": %s\n", isc_result_totext(result));
+ exit(1);
+}
+
+static client_t *
+new_client(void) {
+ client_t *client;
+
+ client = isc_mempool_get(cmp);
+ INSIST(client != NULL);
+ dns_name_init(&client->name, NULL);
+ ISC_LINK_INIT(client, link);
+ client->find = NULL;
+
+ return (client);
+}
+
+static void
+free_client(client_t **c) {
+ client_t *client;
+
+ INSIST(c != NULL);
+ client = *c;
+ *c = NULL;
+ INSIST(client != NULL);
+ dns_name_free(&client->name, mctx);
+ INSIST(!ISC_LINK_LINKED(client, link));
+ INSIST(client->find == NULL);
+
+ isc_mempool_put(cmp, client);
+}
+
+static inline void
+CLOCK(void) {
+ RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS);
+}
+
+static inline void
+CUNLOCK(void) {
+ RUNTIME_CHECK(isc_mutex_unlock(&client_lock) == ISC_R_SUCCESS);
+}
+
+static void
+lookup_callback(isc_task_t *task, isc_event_t *ev) {
+ client_t *client;
+
+ client = ev->ev_arg;
+ INSIST(client->find == ev->ev_sender);
+
+ printf("NAME %s:\n\tTask %p got event %p type %08x from %p, client %p\n\terr4: %s err6: %s\n",
+ client->target,
+ task, ev, ev->ev_type, client->find, client,
+ isc_result_totext(client->find->result_v4),
+ isc_result_totext(client->find->result_v6));
+
+ isc_event_free(&ev);
+ ev = NULL;
+
+ CLOCK();
+
+ dns_adb_dumpfind(client->find, stderr);
+ dns_adb_destroyfind(&client->find);
+
+ ISC_LIST_UNLINK(clients, client, link);
+ free_client(&client);
+
+ CUNLOCK();
+}
+
+static void
+create_managers(void) {
+ isc_result_t result;
+
+ taskmgr = NULL;
+ result = isc_taskmgr_create(mctx, 5, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_create");
+
+ timermgr = NULL;
+ result = isc_timermgr_create(mctx, &timermgr);
+ check_result(result, "isc_timermgr_create");
+
+ socketmgr = NULL;
+ result = isc_socketmgr_create(mctx, &socketmgr);
+ check_result(result, "isc_socketmgr_create");
+
+ dispatchmgr = NULL;
+ result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr);
+ check_result(result, "dns_dispatchmgr_create");
+}
+
+static void
+create_view(void) {
+ dns_cache_t *cache;
+ isc_result_t result;
+
+ /*
+ * View.
+ */
+ view = NULL;
+ result = dns_view_create(mctx, dns_rdataclass_in, "_default", &view);
+ check_result(result, "dns_view_create");
+
+ /*
+ * Cache.
+ */
+ cache = NULL;
+ result = dns_cache_create(mctx, taskmgr, timermgr, dns_rdataclass_in,
+ "rbt", 0, NULL, &cache);
+ check_result(result, "dns_cache_create");
+ dns_view_setcache(view, cache);
+ dns_cache_detach(&cache);
+
+ {
+ unsigned int attrs;
+ isc_sockaddr_t any4, any6;
+ dns_dispatch_t *disp4 = NULL;
+ dns_dispatch_t *disp6 = NULL;
+
+ isc_sockaddr_any(&any4);
+ isc_sockaddr_any6(&any6);
+
+ attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr,
+ taskmgr, &any4,
+ 512, 6, 1024, 17, 19,
+ attrs, attrs, &disp4)
+ == ISC_R_SUCCESS);
+ INSIST(disp4 != NULL);
+
+ attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr,
+ taskmgr, &any6,
+ 512, 6, 1024, 17, 19,
+ attrs, attrs, &disp6)
+ == ISC_R_SUCCESS);
+ INSIST(disp6 != NULL);
+
+ RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
+ socketmgr,
+ timermgr, 0,
+ dispatchmgr,
+ disp4, disp6) ==
+ ISC_R_SUCCESS);
+ }
+
+ rootdb = NULL;
+ result = dns_rootns_create(mctx, dns_rdataclass_in, NULL, &rootdb);
+ check_result(result, "dns_rootns_create()");
+ dns_view_sethints(view, rootdb);
+ dns_db_detach(&rootdb);
+
+ dns_view_freeze(view);
+}
+
+static void
+lookup(const char *target) {
+ dns_name_t name;
+ unsigned char namedata[256];
+ client_t *client;
+ isc_buffer_t t, namebuf;
+ isc_result_t result;
+ unsigned int options;
+
+ INSIST(target != NULL);
+
+ client = new_client();
+ isc_buffer_constinit(&t, target, strlen(target));
+ isc_buffer_add(&t, strlen(target));
+ isc_buffer_init(&namebuf, namedata, sizeof(namedata));
+ dns_name_init(&name, NULL);
+ result = dns_name_fromtext(&name, &t, dns_rootname, 0, &namebuf);
+ check_result(result, "dns_name_fromtext %s", target);
+
+ result = dns_name_dup(&name, mctx, &client->name);
+ check_result(result, "dns_name_dup %s", target);
+
+ options = 0;
+ options |= DNS_ADBFIND_INET;
+ options |= DNS_ADBFIND_INET6;
+ options |= DNS_ADBFIND_WANTEVENT;
+ options |= DNS_ADBFIND_HINTOK;
+ options |= DNS_ADBFIND_GLUEOK;
+ result = dns_adb_createfind(adb, t2, lookup_callback, client,
+ &client->name, dns_rootname, 0, options,
+ now, NULL, view->dstport, &client->find);
+ if (result != ISC_R_SUCCESS)
+ printf("DNS_ADB_CREATEFIND -> %s\n", dns_result_totext(result));
+ dns_adb_dumpfind(client->find, stderr);
+
+ if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
+ client->target = target;
+ ISC_LIST_APPEND(clients, client, link);
+ } else {
+ printf("NAME %s: err4 %s, err6 %s\n",
+ target, isc_result_totext(client->find->result_v4),
+ isc_result_totext(client->find->result_v6));
+
+ dns_adb_destroyfind(&client->find);
+ free_client(&client);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ isc_logdestination_t destination;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ dns_result_register();
+ result = isc_app_start();
+ check_result(result, "isc_app_start()");
+
+ isc_stdtime_get(&now);
+
+ result = isc_mutex_init(&client_lock);
+ check_result(result, "isc_mutex_init(&client_lock)");
+ ISC_LIST_INIT(clients);
+
+ /*
+ * EVERYTHING needs a memory context.
+ */
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ cmp = NULL;
+ RUNTIME_CHECK(isc_mempool_create(mctx, sizeof(client_t), &cmp)
+ == ISC_R_SUCCESS);
+ isc_mempool_setname(cmp, "adb test clients");
+
+ result = isc_entropy_create(mctx, &ectx);
+ check_result(result, "isc_entropy_create()");
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ check_result(result, "isc_hash_create()");
+
+ result = isc_log_create(mctx, &lctx, &lcfg);
+ check_result(result, "isc_log_create()");
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME);
+ check_result(result, "isc_log_createchannel()");
+ result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
+ check_result(result, "isc_log_usechannel()");
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(lctx, 2);
+
+ create_managers();
+
+ t1 = NULL;
+ result = isc_task_create(taskmgr, 0, &t1);
+ check_result(result, "isc_task_create t1");
+ t2 = NULL;
+ result = isc_task_create(taskmgr, 0, &t2);
+ check_result(result, "isc_task_create t2");
+
+ printf("task 1 = %p\n", t1);
+ printf("task 2 = %p\n", t2);
+
+ create_view();
+
+ adb = view->adb;
+
+ /*
+ * Lock the entire client list here. This will cause all events
+ * for found names to block as well.
+ */
+ CLOCK();
+ lookup("f.root-servers.net."); /* Should be in hints */
+ lookup("www.iengines.com"); /* should fetch */
+ lookup("www.isc.org"); /* should fetch */
+ lookup("www.flame.org"); /* should fetch */
+ lookup("kechara.flame.org."); /* should fetch */
+ lookup("moghedien.flame.org."); /* should fetch */
+ lookup("mailrelay.flame.org."); /* should fetch */
+ lookup("ipv4v6.flame.org."); /* should fetch */
+ lookup("nonexistant.flame.org."); /* should fail to be found */
+ lookup("foobar.badns.flame.org."); /* should fail utterly (NS) */
+ lookup("i.root-servers.net."); /* Should be in hints */
+ lookup("www.firstcard.com.");
+ lookup("dns04.flame.org.");
+ CUNLOCK();
+
+ sleep(10);
+
+ dns_adb_dump(adb, stderr);
+
+ sleep(10);
+
+ CLOCK();
+ lookup("f.root-servers.net."); /* Should be in hints */
+ lookup("www.iengines.com"); /* should fetch */
+ lookup("www.isc.org"); /* should fetch */
+ lookup("www.flame.org"); /* should fetch */
+ lookup("kechara.flame.org."); /* should fetch */
+ lookup("moghedien.flame.org."); /* should fetch */
+ lookup("mailrelay.flame.org."); /* should fetch */
+ lookup("ipv4v6.flame.org."); /* should fetch */
+ lookup("nonexistant.flame.org."); /* should fail to be found */
+ lookup("foobar.badns.flame.org."); /* should fail utterly (NS) */
+ lookup("i.root-servers.net."); /* Should be in hints */
+ CUNLOCK();
+
+ sleep(20);
+
+ dns_adb_dump(adb, stderr);
+
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+
+ isc_mem_stats(mctx, stdout);
+ dns_adb_dump(adb, stderr);
+
+ isc_app_run();
+
+ dns_adb_dump(adb, stderr);
+
+ dns_view_detach(&view);
+ adb = NULL;
+
+ fprintf(stderr, "Destroying socket manager\n");
+ isc_socketmgr_destroy(&socketmgr);
+ fprintf(stderr, "Destroying timer manager\n");
+ isc_timermgr_destroy(&timermgr);
+
+ fprintf(stderr, "Destroying task manager\n");
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_log_destroy(&lctx);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mempool_destroy(&cmp);
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/optional/backtrace_test.c b/bin/tests/optional/backtrace_test.c
new file mode 100644
index 0000000..cd89a68
--- /dev/null
+++ b/bin/tests/optional/backtrace_test.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/backtrace.h>
+#include <isc/print.h>
+#include <isc/result.h>
+
+const char *expected_symbols[] = {
+ "func3",
+ "func2",
+ "func1",
+ "main"
+};
+
+static int
+func3() {
+ void *tracebuf[16];
+ int i, nframes;
+ int error = 0;
+ const char *fname;
+ isc_result_t result;
+ unsigned long offset;
+
+ result = isc_backtrace_gettrace(tracebuf, 16, &nframes);
+ if (result != ISC_R_SUCCESS) {
+ printf("isc_backtrace_gettrace failed: %s\n",
+ isc_result_totext(result));
+ return (1);
+ }
+
+ if (nframes < 4)
+ error++;
+
+ for (i = 0; i < 4 && i < nframes; i++) {
+ fname = NULL;
+ result = isc_backtrace_getsymbol(tracebuf[i], &fname, &offset);
+ if (result != ISC_R_SUCCESS) {
+ error++;
+ continue;
+ }
+ if (strcmp(fname, expected_symbols[i]) != 0)
+ error++;
+ }
+
+ if (error) {
+ printf("Unexpected result:\n");
+ printf(" # of frames: %d (expected: at least 4)\n", nframes);
+ printf(" symbols:\n");
+ for (i = 0; i < nframes; i++) {
+ fname = NULL;
+ result = isc_backtrace_getsymbol(tracebuf[i], &fname,
+ &offset);
+ if (result == ISC_R_SUCCESS)
+ printf(" [%d] %s\n", i, fname);
+ else {
+ printf(" [%d] %p getsymbol failed: %s\n", i,
+ tracebuf[i], isc_result_totext(result));
+ }
+ }
+ }
+
+ return (error);
+}
+
+static int
+func2() {
+ return (func3());
+}
+
+static int
+func1() {
+ return (func2());
+}
+
+int
+main() {
+ return (func1());
+}
diff --git a/bin/tests/optional/byaddr_test.c b/bin/tests/optional/byaddr_test.c
new file mode 100644
index 0000000..b1c1a7f
--- /dev/null
+++ b/bin/tests/optional/byaddr_test.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/cache.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+static void
+done(isc_task_t *task, isc_event_t *event) {
+ dns_byaddrevent_t *bevent;
+ dns_byaddr_t *byaddr;
+ dns_name_t *name;
+
+ REQUIRE(event->ev_type == DNS_EVENT_BYADDRDONE);
+ bevent = (dns_byaddrevent_t *)event;
+
+ UNUSED(task);
+
+ printf("byaddr event result = %s\n",
+ isc_result_totext(bevent->result));
+
+ if (bevent->result == ISC_R_SUCCESS) {
+ for (name = ISC_LIST_HEAD(bevent->names);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ char text[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, text, sizeof(text));
+ printf("%s\n", text);
+ }
+ }
+
+ byaddr = event->ev_sender;
+ dns_byaddr_destroy(&byaddr);
+ isc_event_free(&event);
+
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_mem_t *mctx;
+ bool verbose = false;
+ unsigned int workers = 2;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_timermgr_t *timermgr;
+ dns_view_t *view;
+ int ch;
+ isc_socketmgr_t *socketmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ isc_netaddr_t na;
+ dns_byaddr_t *byaddr;
+ isc_result_t result;
+ unsigned int options = 0;
+ dns_cache_t *cache;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "nvw:")) != -1) {
+ switch (ch) {
+ case 'n':
+ /*
+ * We only try nibbles, so do nothing for this option.
+ */
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'w':
+ workers = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ }
+ }
+
+ if (verbose) {
+ printf("%u workers\n", workers);
+ printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4()));
+ printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6()));
+ }
+
+ taskmgr = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr)
+ == ISC_R_SUCCESS);
+ task = NULL;
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task)
+ == ISC_R_SUCCESS);
+ isc_task_setname(task, "byaddr", NULL);
+
+ dispatchmgr = NULL;
+ RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)
+ == ISC_R_SUCCESS);
+
+ timermgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ cache = NULL;
+ RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr,
+ dns_rdataclass_in, "rbt", 0, NULL,
+ &cache) == ISC_R_SUCCESS);
+
+ view = NULL;
+ RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default",
+ &view) == ISC_R_SUCCESS);
+
+ {
+ unsigned int attrs;
+ dns_dispatch_t *disp4 = NULL;
+ dns_dispatch_t *disp6 = NULL;
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any4;
+
+ isc_sockaddr_any(&any4);
+
+ attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any4,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp4)
+ == ISC_R_SUCCESS);
+ INSIST(disp4 != NULL);
+ }
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any6;
+
+ isc_sockaddr_any6(&any6);
+
+ attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any6,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp6)
+ == ISC_R_SUCCESS);
+ INSIST(disp6 != NULL);
+ }
+
+ RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
+ socketmgr,
+ timermgr, 0,
+ dispatchmgr,
+ disp4, disp6) ==
+ ISC_R_SUCCESS);
+
+ if (disp4 != NULL)
+ dns_dispatch_detach(&disp4);
+ if (disp6 != NULL)
+ dns_dispatch_detach(&disp6);
+ }
+
+ {
+ struct in_addr ina;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t sal;
+
+ ISC_LIST_INIT(sal);
+ ina.s_addr = inet_addr("127.0.0.1");
+ isc_sockaddr_fromin(&sa, &ina, 53);
+ ISC_LIST_APPEND(sal, &sa, link);
+
+ RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname,
+ &sal, dns_fwdpolicy_only)
+ == ISC_R_SUCCESS);
+ }
+
+ dns_view_setcache(view, cache);
+ dns_view_freeze(view);
+
+ dns_cache_detach(&cache);
+
+ printf("address = %s\n", argv[isc_commandline_index]);
+ na.family = AF_INET;
+ if (inet_pton(AF_INET, argv[isc_commandline_index],
+ (char *)&na.type.in) != 1) {
+ na.family = AF_INET6;
+ if (inet_pton(AF_INET6, argv[isc_commandline_index],
+ (char *)&na.type.in6) != 1) {
+ printf("unknown address format\n");
+ exit(1);
+ }
+ }
+
+ result = dns_byaddr_create(mctx, &na, view, options, task,
+ done, NULL, &byaddr);
+ if (result != ISC_R_SUCCESS) {
+ printf("dns_byaddr_create() returned %s\n",
+ isc_result_totext(result));
+ RUNTIME_CHECK(0);
+ }
+
+ (void)isc_app_run();
+
+ /*
+ * XXXRTH if we get a control-C before we get to isc_app_run(),
+ * we're in trouble (because we might try to destroy things before
+ * they've been created.
+ */
+
+ dns_view_detach(&view);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ if (verbose)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/optional/byname_test.c b/bin/tests/optional/byname_test.c
new file mode 100644
index 0000000..4b255ba
--- /dev/null
+++ b/bin/tests/optional/byname_test.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/log.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+static isc_taskmgr_t *taskmgr;
+static dns_view_t *view = NULL;
+static dns_adbfind_t *find = NULL;
+static isc_task_t *task = NULL;
+static dns_fixedname_t fixed;
+static dns_fixedname_t target;
+static isc_log_t *lctx;
+static isc_logconfig_t *lcfg;
+static unsigned int level = 0;
+
+static void adb_callback(isc_task_t *task, isc_event_t *event);
+
+static void
+log_init(void) {
+ isc_logdestination_t destination;
+ unsigned int flags;
+
+ /*
+ * Setup a logging context.
+ */
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx, &lcfg) == ISC_R_SUCCESS);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ flags = ISC_LOG_PRINTTIME;
+ RUNTIME_CHECK(isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, flags) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL) ==
+ ISC_R_SUCCESS);
+ isc_log_setdebuglevel(lctx, level);
+}
+
+static void
+print_addresses(dns_adbfind_t *adbfind) {
+ dns_adbaddrinfo_t *address;
+
+ for (address = ISC_LIST_HEAD(adbfind->list);
+ address != NULL;
+ address = ISC_LIST_NEXT(address, publink)) {
+ isc_netaddr_t netaddr;
+ char text[ISC_NETADDR_FORMATSIZE];
+ isc_netaddr_fromsockaddr(&netaddr, &address->sockaddr);
+ isc_netaddr_format(&netaddr, text, sizeof(text));
+ printf("%s\n", text);
+ }
+}
+
+static void
+print_name(dns_name_t *name) {
+ char text[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, text, sizeof(text));
+ printf("%s\n", text);
+}
+
+static void
+do_find(bool want_event) {
+ isc_result_t result;
+ bool done = false;
+ unsigned int options;
+
+ options = DNS_ADBFIND_INET | DNS_ADBFIND_INET6;
+ if (want_event)
+ options |= DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
+ dns_fixedname_init(&target);
+ result = dns_adb_createfind(view->adb, task, adb_callback, NULL,
+ dns_fixedname_name(&fixed),
+ dns_rootname, 0, options, 0,
+ dns_fixedname_name(&target), 0,
+ &find);
+ if (result == ISC_R_SUCCESS) {
+ if (!ISC_LIST_EMPTY(find->list)) {
+ /*
+ * We have at least some of the addresses for the
+ * name.
+ */
+ INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
+ print_addresses(find);
+ done = true;
+ } else {
+ /*
+ * We don't know any of the addresses for this
+ * name.
+ */
+ if ((find->options & DNS_ADBFIND_WANTEVENT) == 0) {
+ /*
+ * And ADB isn't going to send us any events
+ * either. This query loses.
+ */
+ done = true;
+ }
+ /*
+ * If the DNS_ADBFIND_WANTEVENT flag was set, we'll
+ * get an event when something happens.
+ */
+ }
+ } else if (result == DNS_R_ALIAS) {
+ print_name(dns_fixedname_name(&target));
+ done = true;
+ } else {
+ printf("dns_adb_createfind() returned %s\n",
+ isc_result_totext(result));
+ done = true;
+ }
+
+ if (done) {
+ if (find != NULL)
+ dns_adb_destroyfind(&find);
+ isc_app_shutdown();
+ }
+}
+
+static void
+adb_callback(isc_task_t *etask, isc_event_t *event) {
+ unsigned int type = event->ev_type;
+
+ REQUIRE(etask == task);
+
+ isc_event_free(&event);
+ dns_adb_destroyfind(&find);
+
+ if (type == DNS_EVENT_ADBMOREADDRESSES)
+ do_find(false);
+ else if (type == DNS_EVENT_ADBNOMOREADDRESSES) {
+ printf("no more addresses\n");
+ isc_app_shutdown();
+ } else {
+ printf("unexpected ADB event type %u\n", type);
+ isc_app_shutdown();
+ }
+}
+
+static void
+run(isc_task_t *xtask, isc_event_t *event) {
+ UNUSED(xtask);
+ do_find(true);
+ isc_event_free(&event);
+}
+
+int
+main(int argc, char *argv[]) {
+ bool verbose = false;
+ unsigned int workers = 2;
+ isc_timermgr_t *timermgr;
+ int ch;
+ isc_socketmgr_t *socketmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_cache_t *cache;
+ isc_buffer_t b;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
+ == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "d:vw:")) != -1) {
+ switch (ch) {
+ case 'd':
+ level = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'w':
+ workers = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ }
+ }
+
+ log_init();
+
+ if (verbose) {
+ printf("%u workers\n", workers);
+ printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4()));
+ printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6()));
+ }
+
+ taskmgr = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ task = NULL;
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task) ==
+ ISC_R_SUCCESS);
+ isc_task_setname(task, "byname", NULL);
+
+ dispatchmgr = NULL;
+ RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)
+ == ISC_R_SUCCESS);
+
+ timermgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ cache = NULL;
+ RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr,
+ dns_rdataclass_in, "rbt", 0, NULL,
+ &cache) == ISC_R_SUCCESS);
+
+ view = NULL;
+ RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default",
+ &view) == ISC_R_SUCCESS);
+
+ {
+ unsigned int attrs;
+ dns_dispatch_t *disp4 = NULL;
+ dns_dispatch_t *disp6 = NULL;
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any4;
+ isc_sockaddr_any(&any4);
+
+ attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any4,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp4)
+ == ISC_R_SUCCESS);
+ INSIST(disp4 != NULL);
+ }
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any6;
+
+ isc_sockaddr_any6(&any6);
+
+ attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any6,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp6)
+ == ISC_R_SUCCESS);
+ INSIST(disp6 != NULL);
+ }
+
+ RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
+ socketmgr,
+ timermgr, 0,
+ dispatchmgr,
+ disp4, disp6) ==
+ ISC_R_SUCCESS);
+
+ if (disp4 != NULL)
+ dns_dispatch_detach(&disp4);
+ if (disp6 != NULL)
+ dns_dispatch_detach(&disp6);
+ }
+
+ {
+ struct in_addr ina;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t sal;
+
+ ISC_LIST_INIT(sal);
+ ina.s_addr = inet_addr("127.0.0.1");
+ isc_sockaddr_fromin(&sa, &ina, 53);
+ ISC_LIST_APPEND(sal, &sa, link);
+
+ RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname,
+ &sal, dns_fwdpolicy_only)
+ == ISC_R_SUCCESS);
+ }
+
+ dns_view_setcache(view, cache);
+ dns_view_freeze(view);
+
+ dns_cache_detach(&cache);
+
+ printf("name = %s\n", argv[isc_commandline_index]);
+ isc_buffer_init(&b, argv[isc_commandline_index],
+ strlen(argv[isc_commandline_index]));
+ isc_buffer_add(&b, strlen(argv[isc_commandline_index]));
+ dns_fixedname_init(&fixed);
+ dns_fixedname_init(&target);
+ RUNTIME_CHECK(dns_name_fromtext(dns_fixedname_name(&fixed), &b,
+ dns_rootname, 0, NULL) ==
+ ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_app_onrun(mctx, task, run, NULL) == ISC_R_SUCCESS);
+
+ (void)isc_app_run();
+
+ dns_view_detach(&view);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ isc_log_destroy(&lctx);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ if (verbose)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/optional/db_test.c b/bin/tests/optional/db_test.c
new file mode 100644
index 0000000..c69af66
--- /dev/null
+++ b/bin/tests/optional/db_test.c
@@ -0,0 +1,936 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/time.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dbtable.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+
+#define MAXHOLD 100
+#define MAXVERSIONS 100
+
+typedef struct dbinfo {
+ dns_db_t * db;
+ dns_dbversion_t * version;
+ dns_dbversion_t * wversion;
+ dns_dbversion_t * rversions[MAXVERSIONS];
+ int rcount;
+ dns_dbnode_t * hold_nodes[MAXHOLD];
+ int hold_count;
+ dns_dbiterator_t * dbiterator;
+ dns_dbversion_t * iversion;
+ int pause_every;
+ bool ascending;
+ ISC_LINK(struct dbinfo) link;
+} dbinfo;
+
+static isc_mem_t * mctx = NULL;
+static char dbtype[128];
+static dns_dbtable_t * dbtable;
+static ISC_LIST(dbinfo) dbs;
+static dbinfo * cache_dbi = NULL;
+static int pause_every = 0;
+static bool ascending = true;
+
+static void
+print_result(const char *message, isc_result_t result) {
+
+ if (message == NULL)
+ message = "";
+ printf("%s%sresult %08x: %s\n", message, (*message == '\0') ? "" : " ",
+ result, isc_result_totext(result));
+}
+
+static void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
+ isc_buffer_t text;
+ char t[1000];
+ isc_result_t result;
+ isc_region_t r;
+
+ isc_buffer_init(&text, t, sizeof(t));
+ result = dns_rdataset_totext(rdataset, name, false, false,
+ &text);
+ isc_buffer_usedregion(&text, &r);
+ if (result == ISC_R_SUCCESS)
+ printf("%.*s", (int)r.length, (char *)r.base);
+ else
+ print_result("", result);
+}
+
+static void
+print_rdatasets(dns_name_t *name, dns_rdatasetiter_t *rdsiter) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ print_rdataset(name, &rdataset);
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE)
+ print_result("", result);
+}
+
+static dbinfo *
+select_db(char *origintext) {
+ dns_fixedname_t forigin;
+ dns_name_t *origin;
+ isc_buffer_t source;
+ size_t len;
+ dbinfo *dbi;
+ isc_result_t result;
+
+ if (strcasecmp(origintext, "cache") == 0) {
+ if (cache_dbi == NULL)
+ printf("the cache does not exist\n");
+ return (cache_dbi);
+ }
+ len = strlen(origintext);
+ isc_buffer_init(&source, origintext, len);
+ isc_buffer_add(&source, len);
+ origin = dns_fixedname_initname(&forigin);
+ result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ print_result("bad name", result);
+ return (NULL);
+ }
+
+ for (dbi = ISC_LIST_HEAD(dbs);
+ dbi != NULL;
+ dbi = ISC_LIST_NEXT(dbi, link)) {
+ if (dns_name_compare(dns_db_origin(dbi->db), origin) == 0)
+ break;
+ }
+
+ return (dbi);
+}
+
+static void
+list(dbinfo *dbi, char *seektext) {
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *rdsiter;
+ isc_result_t result;
+ int i;
+ size_t len;
+ dns_fixedname_t fseekname;
+ dns_name_t *seekname;
+ isc_buffer_t source;
+
+ name = dns_fixedname_initname(&fname);
+
+ if (dbi->dbiterator == NULL) {
+ INSIST(dbi->iversion == NULL);
+ if (dns_db_iszone(dbi->db)) {
+ if (dbi->version != NULL)
+ dns_db_attachversion(dbi->db, dbi->version,
+ &dbi->iversion);
+ else
+ dns_db_currentversion(dbi->db, &dbi->iversion);
+ }
+
+ result = dns_db_createiterator(dbi->db, 0, &dbi->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ if (seektext != NULL) {
+ len = strlen(seektext);
+ isc_buffer_init(&source, seektext, len);
+ isc_buffer_add(&source, len);
+ seekname = dns_fixedname_initname(&fseekname);
+ result = dns_name_fromtext(seekname, &source,
+ dns_db_origin(
+ dbi->db),
+ 0, NULL);
+ if (result == ISC_R_SUCCESS)
+ result = dns_dbiterator_seek(
+ dbi->dbiterator,
+ seekname);
+ } else if (dbi->ascending)
+ result = dns_dbiterator_first(dbi->dbiterator);
+ else
+ result = dns_dbiterator_last(dbi->dbiterator);
+ }
+ } else
+ result = ISC_R_SUCCESS;
+
+ node = NULL;
+ rdsiter = NULL;
+ i = 0;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbi->dbiterator, &node, name);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ break;
+ result = dns_db_allrdatasets(dbi->db, node, dbi->iversion, 0,
+ &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(dbi->db, &node);
+ break;
+ }
+ print_rdatasets(name, rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(dbi->db, &node);
+ if (dbi->ascending)
+ result = dns_dbiterator_next(dbi->dbiterator);
+ else
+ result = dns_dbiterator_prev(dbi->dbiterator);
+ i++;
+ if (result == ISC_R_SUCCESS && i == dbi->pause_every) {
+ printf("[more...]\n");
+ result = dns_dbiterator_pause(dbi->dbiterator);
+ if (result == ISC_R_SUCCESS)
+ return;
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ print_result("", result);
+
+ dns_dbiterator_destroy(&dbi->dbiterator);
+ if (dbi->iversion != NULL)
+ dns_db_closeversion(dbi->db, &dbi->iversion, false);
+}
+
+static isc_result_t
+load(const char *filename, const char *origintext, bool cache) {
+ dns_fixedname_t forigin;
+ dns_name_t *origin;
+ isc_result_t result;
+ isc_buffer_t source;
+ size_t len;
+ dbinfo *dbi;
+ unsigned int i;
+
+ dbi = isc_mem_get(mctx, sizeof(*dbi));
+ if (dbi == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dbi->db = NULL;
+ dbi->version = NULL;
+ dbi->wversion = NULL;
+ for (i = 0; i < MAXVERSIONS; i++)
+ dbi->rversions[i] = NULL;
+ dbi->hold_count = 0;
+ for (i = 0; i < MAXHOLD; i++)
+ dbi->hold_nodes[i] = NULL;
+ dbi->dbiterator = NULL;
+ dbi->iversion = NULL;
+ dbi->pause_every = pause_every;
+ dbi->ascending = ascending;
+ ISC_LINK_INIT(dbi, link);
+
+ len = strlen(origintext);
+ isc_buffer_constinit(&source, origintext, len);
+ isc_buffer_add(&source, len);
+ origin = dns_fixedname_initname(&forigin);
+ result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+
+ result = dns_db_create(mctx, dbtype, origin,
+ cache ? dns_dbtype_cache : dns_dbtype_zone,
+ dns_rdataclass_in,
+ 0, NULL, &dbi->db);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+
+ printf("loading %s (%s)\n", filename, origintext);
+ result = dns_db_load(dbi->db, filename);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ dns_db_detach(&dbi->db);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+ printf("loaded\n");
+
+ if (cache) {
+ INSIST(cache_dbi == NULL);
+ dns_dbtable_adddefault(dbtable, dbi->db);
+ cache_dbi = dbi;
+ } else {
+ result = dns_dbtable_add(dbtable, dbi->db);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detach(&dbi->db);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+ }
+ ISC_LIST_APPEND(dbs, dbi, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+unload_all(void) {
+ dbinfo *dbi, *dbi_next;
+
+ for (dbi = ISC_LIST_HEAD(dbs); dbi != NULL; dbi = dbi_next) {
+ dbi_next = ISC_LIST_NEXT(dbi, link);
+ if (dns_db_iszone(dbi->db))
+ dns_dbtable_remove(dbtable, dbi->db);
+ else {
+ INSIST(dbi == cache_dbi);
+ dns_dbtable_removedefault(dbtable);
+ cache_dbi = NULL;
+ }
+ dns_db_detach(&dbi->db);
+ ISC_LIST_UNLINK(dbs, dbi, link);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ }
+}
+
+#define DBI_CHECK(dbi) \
+if ((dbi) == NULL) { \
+ printf("You must first select a database with !DB\n"); \
+ continue; \
+}
+
+int
+main(int argc, char *argv[]) {
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ isc_result_t result;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ size_t len;
+ isc_buffer_t source, target;
+ char s[1000];
+ char b[255];
+ dns_rdataset_t rdataset, sigrdataset;
+ int ch;
+ dns_rdatatype_t type = 1;
+ bool printnode = false;
+ bool addmode = false;
+ bool delmode = false;
+ bool holdmode = false;
+ bool verbose = false;
+ bool done = false;
+ bool quiet = false;
+ bool time_lookups = false;
+ bool found_as;
+ bool find_zonecut = false;
+ bool noexact_zonecut = false;
+ int i, v;
+ dns_rdatasetiter_t *rdsiter;
+ char t1[256];
+ char t2[256];
+ isc_buffer_t tb1, tb2;
+ isc_region_t r1, r2;
+ dns_fixedname_t foundname;
+ dns_name_t *fname;
+ unsigned int options = 0, zcoptions;
+ isc_time_t start, finish;
+ const char *origintext;
+ dbinfo *dbi;
+ dns_dbversion_t *version;
+ dns_name_t *origin;
+ size_t memory_quota = 0;
+ dns_trust_t trust = 0;
+ unsigned int addopts;
+ isc_log_t *lctx = NULL;
+ size_t n;
+
+ dns_result_register();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_dbtable_create(mctx, dns_rdataclass_in, &dbtable) ==
+ ISC_R_SUCCESS);
+
+ snprintf(dbtype, sizeof(dbtype), "rbt");
+ while ((ch = isc_commandline_parse(argc, argv, "c:d:t:z:P:Q:glpqvT"))
+ != -1) {
+ switch (ch) {
+ case 'c':
+ result = load(isc_commandline_argument, ".", true);
+ if (result != ISC_R_SUCCESS)
+ printf("cache load(%s) %08x: %s\n",
+ isc_commandline_argument, result,
+ isc_result_totext(result));
+ break;
+ case 'd':
+ n = strlcpy(dbtype, isc_commandline_argument,
+ sizeof(dbtype));
+ if (n >= sizeof(dbtype)) {
+ fprintf(stderr, "bad db type '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'g':
+ options |= (DNS_DBFIND_GLUEOK|DNS_DBFIND_VALIDATEGLUE);
+ break;
+ case 'l':
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx,
+ NULL) == ISC_R_SUCCESS);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+ break;
+ case 'q':
+ quiet = true;
+ verbose = false;
+ break;
+ case 'p':
+ printnode = true;
+ break;
+ case 'P':
+ pause_every = atoi(isc_commandline_argument);
+ break;
+ case 'Q':
+ memory_quota = atoi(isc_commandline_argument);
+ isc_mem_setquota(mctx, memory_quota);
+ break;
+ case 't':
+ type = atoi(isc_commandline_argument);
+ break;
+ case 'T':
+ time_lookups = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'z':
+ origintext = strrchr(isc_commandline_argument, '/');
+ if (origintext == NULL)
+ origintext = isc_commandline_argument;
+ else
+ origintext++; /* Skip '/'. */
+ result = load(isc_commandline_argument, origintext,
+ false);
+ if (result != ISC_R_SUCCESS)
+ printf("zone load(%s) %08x: %s\n",
+ isc_commandline_argument, result,
+ isc_result_totext(result));
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc != 0)
+ printf("ignoring trailing arguments\n");
+
+ /*
+ * Some final initialization...
+ */
+ fname = dns_fixedname_initname(&foundname);
+ dbi = NULL;
+ origin = dns_rootname;
+ version = NULL;
+
+ if (time_lookups) {
+ TIME_NOW(&start);
+ }
+
+ while (!done) {
+ if (!quiet)
+ printf("\n");
+ if (fgets(s, sizeof(s), stdin) == NULL) {
+ done = true;
+ continue;
+ }
+ len = strlen(s);
+ if (len > 0U && s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ len--;
+ }
+ if (verbose && dbi != NULL) {
+ if (dbi->wversion != NULL)
+ printf("future version (%p)\n", dbi->wversion);
+ for (i = 0; i < dbi->rcount; i++)
+ if (dbi->rversions[i] != NULL)
+ printf("open version %d (%p)\n", i,
+ dbi->rversions[i]);
+ }
+ dns_name_init(&name, offsets);
+ if (strcmp(s, "!R") == 0) {
+ DBI_CHECK(dbi);
+ if (dbi->rcount == MAXVERSIONS) {
+ printf("too many open versions\n");
+ continue;
+ }
+ dns_db_currentversion(dbi->db,
+ &dbi->rversions[dbi->rcount]);
+ printf("opened version %d\n", dbi->rcount);
+ dbi->version = dbi->rversions[dbi->rcount];
+ version = dbi->version;
+ dbi->rcount++;
+ continue;
+ } else if (strcmp(s, "!W") == 0) {
+ DBI_CHECK(dbi);
+ if (dbi->wversion != NULL) {
+ printf("using existing future version\n");
+ dbi->version = dbi->wversion;
+ version = dbi->version;
+ continue;
+ }
+ result = dns_db_newversion(dbi->db, &dbi->wversion);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ else
+ printf("newversion\n");
+ dbi->version = dbi->wversion;
+ version = dbi->version;
+ continue;
+ } else if (strcmp(s, "!C") == 0) {
+ DBI_CHECK(dbi);
+ addmode = false;
+ delmode = false;
+ if (dbi->version == NULL)
+ continue;
+ if (dbi->version == dbi->wversion) {
+ printf("closing future version\n");
+ dbi->wversion = NULL;
+ } else {
+ for (i = 0; i < dbi->rcount; i++) {
+ if (dbi->version ==
+ dbi->rversions[i]) {
+ dbi->rversions[i] = NULL;
+ printf("closing open version %d\n",
+ i);
+ break;
+ }
+ }
+ }
+ dns_db_closeversion(dbi->db, &dbi->version, true);
+ version = NULL;
+ continue;
+ } else if (strcmp(s, "!X") == 0) {
+ DBI_CHECK(dbi);
+ addmode = false;
+ delmode = false;
+ if (dbi->version == NULL)
+ continue;
+ if (dbi->version == dbi->wversion) {
+ printf("aborting future version\n");
+ dbi->wversion = NULL;
+ } else {
+ for (i = 0; i < dbi->rcount; i++) {
+ if (dbi->version ==
+ dbi->rversions[i]) {
+ dbi->rversions[i] = NULL;
+ printf("closing open version %d\n",
+ i);
+ break;
+ }
+ }
+ }
+ dns_db_closeversion(dbi->db, &dbi->version, false);
+ version = NULL;
+ continue;
+ } else if (strcmp(s, "!A") == 0) {
+ DBI_CHECK(dbi);
+ delmode = false;
+ if (addmode)
+ addmode = false;
+ else
+ addmode = true;
+ printf("addmode = %s\n", addmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!D") == 0) {
+ DBI_CHECK(dbi);
+ addmode = false;
+ if (delmode)
+ delmode = false;
+ else
+ delmode = true;
+ printf("delmode = %s\n", delmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!H") == 0) {
+ DBI_CHECK(dbi);
+ if (holdmode)
+ holdmode = false;
+ else
+ holdmode = true;
+ printf("holdmode = %s\n", holdmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!HR") == 0) {
+ DBI_CHECK(dbi);
+ for (i = 0; i < dbi->hold_count; i++)
+ dns_db_detachnode(dbi->db,
+ &dbi->hold_nodes[i]);
+ dbi->hold_count = 0;
+ holdmode = false;
+ printf("held nodes have been detached\n");
+ continue;
+ } else if (strcmp(s, "!VC") == 0) {
+ DBI_CHECK(dbi);
+ printf("switching to current version\n");
+ dbi->version = NULL;
+ version = NULL;
+ continue;
+ } else if (strstr(s, "!V") == s) {
+ DBI_CHECK(dbi);
+ v = atoi(&s[2]);
+ if (v >= dbi->rcount || v < 0) {
+ printf("unknown open version %d\n", v);
+ continue;
+ }
+ if (dbi->rversions[v] == NULL) {
+ printf("version %d is not open\n", v);
+ continue;
+ }
+ printf("switching to open version %d\n", v);
+ dbi->version = dbi->rversions[v];
+ version = dbi->version;
+ continue;
+ } else if (strstr(s, "!TR") == s) {
+ trust = (unsigned int)atoi(&s[3]);
+ printf("trust level is now %u\n", (unsigned int)trust);
+ continue;
+ } else if (strstr(s, "!T") == s) {
+ type = (unsigned int)atoi(&s[2]);
+ printf("now searching for type %u\n", type);
+ continue;
+ } else if (strcmp(s, "!G") == 0) {
+ if ((options & DNS_DBFIND_GLUEOK) != 0)
+ options &= ~DNS_DBFIND_GLUEOK;
+ else
+ options |= DNS_DBFIND_GLUEOK;
+ printf("glue ok = %s\n",
+ ((options & DNS_DBFIND_GLUEOK) != 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!GV") == 0) {
+ if ((options & DNS_DBFIND_VALIDATEGLUE) != 0)
+ options &= ~DNS_DBFIND_VALIDATEGLUE;
+ else
+ options |= DNS_DBFIND_VALIDATEGLUE;
+ printf("validate glue = %s\n",
+ ((options & DNS_DBFIND_VALIDATEGLUE) != 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!WC") == 0) {
+ if ((options & DNS_DBFIND_NOWILD) != 0)
+ options &= ~DNS_DBFIND_NOWILD;
+ else
+ options |= DNS_DBFIND_NOWILD;
+ printf("wildcard matching = %s\n",
+ ((options & DNS_DBFIND_NOWILD) == 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strstr(s, "!LS ") == s) {
+ DBI_CHECK(dbi);
+ list(dbi, &s[4]);
+ continue;
+ } else if (strcmp(s, "!LS") == 0) {
+ DBI_CHECK(dbi);
+ list(dbi, NULL);
+ continue;
+ } else if (strstr(s, "!DU ") == s) {
+ DBI_CHECK(dbi);
+ result = dns_db_dump(dbi->db, dbi->version, s+4);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n");
+ print_result("", result);
+ }
+ continue;
+ } else if (strcmp(s, "!PN") == 0) {
+ if (printnode)
+ printnode = false;
+ else
+ printnode = true;
+ printf("printnode = %s\n",
+ printnode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strstr(s, "!P") == s) {
+ DBI_CHECK(dbi);
+ v = atoi(&s[2]);
+ dbi->pause_every = v;
+ continue;
+ } else if (strcmp(s, "!+") == 0) {
+ DBI_CHECK(dbi);
+ dbi->ascending = true;
+ continue;
+ } else if (strcmp(s, "!-") == 0) {
+ DBI_CHECK(dbi);
+ dbi->ascending = false;
+ continue;
+ } else if (strcmp(s, "!DB") == 0) {
+ dbi = NULL;
+ origin = dns_rootname;
+ version = NULL;
+ printf("now searching all databases\n");
+ continue;
+ } else if (strncmp(s, "!DB ", 4) == 0) {
+ dbi = select_db(s+4);
+ if (dbi != NULL) {
+ db = dbi->db;
+ origin = dns_db_origin(dbi->db);
+ version = dbi->version;
+ addmode = false;
+ delmode = false;
+ holdmode = false;
+ } else {
+ db = NULL;
+ version = NULL;
+ origin = dns_rootname;
+ printf("database not found; "
+ "now searching all databases\n");
+ }
+ continue;
+ } else if (strcmp(s, "!ZC") == 0) {
+ if (find_zonecut)
+ find_zonecut = false;
+ else
+ find_zonecut = true;
+ printf("find_zonecut = %s\n",
+ find_zonecut ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!NZ") == 0) {
+ if (noexact_zonecut)
+ noexact_zonecut = false;
+ else
+ noexact_zonecut = true;
+ printf("noexact_zonecut = %s\n",
+ noexact_zonecut ? "TRUE" : "FALSE");
+ continue;
+ }
+
+ isc_buffer_init(&source, s, len);
+ isc_buffer_add(&source, len);
+ isc_buffer_init(&target, b, sizeof(b));
+ result = dns_name_fromtext(&name, &source, origin, 0, &target);
+ if (result != ISC_R_SUCCESS) {
+ print_result("bad name: ", result);
+ continue;
+ }
+
+ if (dbi == NULL) {
+ zcoptions = 0;
+ if (noexact_zonecut)
+ zcoptions |= DNS_DBTABLEFIND_NOEXACT;
+ db = NULL;
+ result = dns_dbtable_find(dbtable, &name, zcoptions,
+ &db);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_PARTIALMATCH) {
+ if (!quiet) {
+ printf("\n");
+ print_result("", result);
+ }
+ continue;
+ }
+ isc_buffer_init(&tb1, t1, sizeof(t1));
+ result = dns_name_totext(dns_db_origin(db), false,
+ &tb1);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n");
+ print_result("", result);
+ dns_db_detach(&db);
+ continue;
+ }
+ isc_buffer_usedregion(&tb1, &r1);
+ printf("\ndatabase = %.*s (%s)\n",
+ (int)r1.length, r1.base,
+ (dns_db_iszone(db)) ? "zone" : "cache");
+ }
+ node = NULL;
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigrdataset);
+
+ if (find_zonecut && dns_db_iscache(db)) {
+ zcoptions = options;
+ if (noexact_zonecut)
+ zcoptions |= DNS_DBFIND_NOEXACT;
+ result = dns_db_findzonecut(db, &name, zcoptions,
+ 0, &node, fname,
+ &rdataset, &sigrdataset);
+ } else {
+ result = dns_db_find(db, &name, version, type,
+ options, 0, &node, fname,
+ &rdataset, &sigrdataset);
+ }
+
+ if (!quiet) {
+ if (dbi != NULL)
+ printf("\n");
+ print_result("", result);
+ }
+
+ found_as = false;
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_GLUE:
+ case DNS_R_CNAME:
+ case DNS_R_ZONECUT:
+ break;
+ case DNS_R_DNAME:
+ case DNS_R_DELEGATION:
+ found_as = true;
+ break;
+ case DNS_R_NXRRSET:
+ if (dns_rdataset_isassociated(&rdataset))
+ break;
+ if (dbi != NULL) {
+ if (holdmode) {
+ RUNTIME_CHECK(dbi->hold_count <
+ MAXHOLD);
+ dbi->hold_nodes[dbi->hold_count++] =
+ node;
+ node = NULL;
+ } else
+ dns_db_detachnode(db, &node);
+ } else {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ continue;
+ case DNS_R_NXDOMAIN:
+ if (dns_rdataset_isassociated(&rdataset))
+ break;
+ /* FALLTHROUGH */
+ default:
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ if (quiet)
+ print_result("", result);
+ continue;
+ }
+ if (found_as && !quiet) {
+ isc_buffer_init(&tb1, t1, sizeof(t1));
+ isc_buffer_init(&tb2, t2, sizeof(t2));
+ result = dns_name_totext(&name, false, &tb1);
+ if (result != ISC_R_SUCCESS) {
+ print_result("", result);
+ dns_db_detachnode(db, &node);
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ continue;
+ }
+ result = dns_name_totext(fname, false, &tb2);
+ if (result != ISC_R_SUCCESS) {
+ print_result("", result);
+ dns_db_detachnode(db, &node);
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ continue;
+ }
+ isc_buffer_usedregion(&tb1, &r1);
+ isc_buffer_usedregion(&tb2, &r2);
+ printf("found %.*s as %.*s\n",
+ (int)r1.length, r1.base,
+ (int)r2.length, r2.base);
+ }
+
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+
+ if (!found_as && type == dns_rdatatype_any) {
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0,
+ &rdsiter);
+ if (result == ISC_R_SUCCESS) {
+ if (!quiet)
+ print_rdatasets(fname, rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ } else
+ print_result("", result);
+ } else {
+ if (!quiet)
+ print_rdataset(fname, &rdataset);
+ if (dns_rdataset_isassociated(&sigrdataset)) {
+ if (!quiet)
+ print_rdataset(fname, &sigrdataset);
+ dns_rdataset_disassociate(&sigrdataset);
+ }
+ if (dbi != NULL && addmode && !found_as) {
+ rdataset.ttl++;
+ rdataset.trust = trust;
+ if (dns_db_iszone(db))
+ addopts = DNS_DBADD_MERGE;
+ else
+ addopts = 0;
+ result = dns_db_addrdataset(db, node, version,
+ 0, &rdataset,
+ addopts, NULL);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+ } else if (dbi != NULL && delmode && !found_as) {
+ result = dns_db_deleterdataset(db, node,
+ version, type,
+ 0);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ if (dbi != NULL) {
+ if (holdmode) {
+ RUNTIME_CHECK(dbi->hold_count < MAXHOLD);
+ dbi->hold_nodes[dbi->hold_count++] = node;
+ node = NULL;
+ } else
+ dns_db_detachnode(db, &node);
+ } else {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ }
+
+ if (time_lookups) {
+ uint64_t usec;
+
+ TIME_NOW(&finish);
+
+ usec = isc_time_microdiff(&finish, &start);
+
+ printf("elapsed time: %lu.%06lu seconds\n",
+ (unsigned long)(usec / 1000000),
+ (unsigned long)(usec % 1000000));
+ }
+
+ unload_all();
+
+ dns_dbtable_detach(&dbtable);
+
+ if (lctx != NULL)
+ isc_log_destroy(&lctx);
+
+ if (!quiet)
+ isc_mem_stats(mctx, stdout);
+
+ return (0);
+}
diff --git a/bin/tests/optional/dst_test.c b/bin/tests/optional/dst_test.c
new file mode 100644
index 0000000..405a292
--- /dev/null
+++ b/bin/tests/optional/dst_test.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <unistd.h> /* XXX */
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+char *current;
+const char *tmp = "/tmp";
+
+static void
+use(dst_key_t *key, isc_mem_t *mctx) {
+ isc_result_t ret;
+ const char *data = "This is some data";
+ unsigned char sig[512];
+ isc_buffer_t databuf, sigbuf;
+ isc_region_t datareg, sigreg;
+ dst_context_t *ctx = NULL;
+
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+ /*
+ * Advance 1 byte for fun.
+ */
+ isc_buffer_add(&sigbuf, 1);
+
+ isc_buffer_constinit(&databuf, data, strlen(data));
+ isc_buffer_add(&databuf, strlen(data));
+ isc_buffer_usedregion(&databuf, &datareg);
+
+ ret = dst_context_create3(key, mctx,
+ DNS_LOGCATEGORY_GENERAL, true, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ printf("contextcreate(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ return;
+ }
+ ret = dst_context_adddata(ctx, &datareg);
+ if (ret != ISC_R_SUCCESS) {
+ printf("adddata(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+ return;
+ }
+ ret = dst_context_sign(ctx, &sigbuf);
+ printf("sign(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+
+ isc_buffer_forward(&sigbuf, 1);
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+ ret = dst_context_create3(key, mctx,
+ DNS_LOGCATEGORY_GENERAL, false, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ printf("contextcreate(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ return;
+ }
+ ret = dst_context_adddata(ctx, &datareg);
+ if (ret != ISC_R_SUCCESS) {
+ printf("adddata(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+ return;
+ }
+ ret = dst_context_verify(ctx, &sigreg);
+ printf("verify(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+}
+
+static void
+dns(dst_key_t *key, isc_mem_t *mctx) {
+ unsigned char buffer1[2048];
+ unsigned char buffer2[2048];
+ isc_buffer_t buf1, buf2;
+ isc_region_t r1, r2;
+ dst_key_t *newkey = NULL;
+ isc_result_t ret;
+ bool match;
+
+ isc_buffer_init(&buf1, buffer1, sizeof(buffer1));
+ ret = dst_key_todns(key, &buf1);
+ printf("todns(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+ ret = dst_key_fromdns(dst_key_name(key), dns_rdataclass_in,
+ &buf1, mctx, &newkey);
+ printf("fromdns(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+ isc_buffer_init(&buf2, buffer2, sizeof(buffer2));
+ ret = dst_key_todns(newkey, &buf2);
+ printf("todns2(%u) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+ isc_buffer_usedregion(&buf1, &r1);
+ isc_buffer_usedregion(&buf2, &r2);
+ match = (r1.length == r2.length &&
+ memcmp(r1.base, r2.base, r1.length) == 0);
+ printf("compare(%u): %s\n", dst_key_alg(key),
+ match ? "true" : "false");
+ dst_key_free(&newkey);
+}
+
+static void
+io(dns_name_t *name, int id, int alg, int type, isc_mem_t *mctx) {
+ dst_key_t *key = NULL;
+ isc_result_t ret;
+
+ ret = dst_key_fromfile(name, id, alg, type, current, mctx, &key);
+ printf("read(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ ret = dst_key_tofile(key, type, tmp);
+ printf("write(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ use(key, mctx);
+ dns(key, mctx);
+ dst_key_free(&key);
+}
+
+static void
+dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx) {
+ dst_key_t *key1 = NULL, *key2 = NULL;
+ isc_result_t ret;
+ isc_buffer_t b1, b2;
+ isc_region_t r1, r2;
+ unsigned char array1[1024], array2[1024];
+ int alg = DST_ALG_DH;
+ int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY;
+
+ ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1);
+ printf("read(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2);
+ printf("read(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ ret = dst_key_tofile(key1, type, tmp);
+ printf("write(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ ret = dst_key_tofile(key2, type, tmp);
+ printf("write(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ isc_buffer_init(&b1, array1, sizeof(array1));
+ ret = dst_key_computesecret(key1, key2, &b1);
+ printf("computesecret() returned: %s\n", isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ isc_buffer_init(&b2, array2, sizeof(array2));
+ ret = dst_key_computesecret(key2, key1, &b2);
+ printf("computesecret() returned: %s\n", isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ isc_buffer_usedregion(&b1, &r1);
+ isc_buffer_usedregion(&b2, &r2);
+
+ if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0)
+ {
+ int i;
+ printf("secrets don't match\n");
+ printf("secret 1: %u bytes\n", r1.length);
+ for (i = 0; i < (int) r1.length; i++)
+ printf("%02x ", r1.base[i]);
+ printf("\n");
+ printf("secret 2: %u bytes\n", r2.length);
+ for (i = 0; i < (int) r2.length; i++)
+ printf("%02x ", r2.base[i]);
+ printf("\n");
+ }
+ dst_key_free(&key1);
+ dst_key_free(&key2);
+}
+
+static void
+generate(int alg, isc_mem_t *mctx) {
+ isc_result_t ret;
+ dst_key_t *key = NULL;
+
+ ret = dst_key_generate(dns_rootname, alg, 512, 0, 0, 0,
+ dns_rdataclass_in, mctx, &key);
+ printf("generate(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+
+ if (alg != DST_ALG_DH)
+ use(key, mctx);
+
+ dst_key_free(&key);
+}
+
+int
+main(void) {
+ isc_mem_t *mctx = NULL;
+ isc_entropy_t *ectx = NULL;
+ isc_buffer_t b;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+
+ current = isc_mem_get(mctx, 256);
+ if (current == NULL)
+ return (1);
+ if (getcwd(current, 256) == NULL) {
+ perror("getcwd");
+ return (1);
+ }
+
+ dns_result_register();
+
+ result = isc_entropy_create(mctx, &ectx);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ result = isc_entropy_createfilesource(ectx, "randomfile");
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING|ISC_ENTROPY_GOODONLY);
+
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_constinit(&b, "test.", 5);
+ isc_buffer_add(&b, 5);
+ result = dns_name_fromtext(name, &b, NULL, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
+ io(name, 54622, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx);
+
+ io(name, 49667, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
+ io(name, 2, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
+
+ isc_buffer_constinit(&b, "dh.", 3);
+ isc_buffer_add(&b, 3);
+ result = dns_name_fromtext(name, &b, NULL, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ dh(name, 18602, name, 48957, mctx);
+
+ generate(DST_ALG_RSAMD5, mctx);
+ generate(DST_ALG_DH, mctx);
+ generate(DST_ALG_DSA, mctx);
+ generate(DST_ALG_HMACMD5, mctx);
+
+ dst_lib_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_put(mctx, current, 256);
+/* isc_mem_stats(mctx, stdout);*/
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/entropy2_test.c b/bin/tests/optional/entropy2_test.c
new file mode 100644
index 0000000..b7b2b70
--- /dev/null
+++ b/bin/tests/optional/entropy2_test.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/keyboard.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+static void
+hex_dump(const char *msg, void *data, unsigned int length) {
+ unsigned int len;
+ unsigned char *base;
+ bool first = true;
+
+ base = data;
+
+ printf("DUMP of %u bytes: %s\n\t", length, msg);
+ for (len = 0; len < length; len++) {
+ if (len % 16 == 0 && !first)
+ printf("\n\t");
+ printf("%02x ", base[len]);
+ first = false;
+ }
+ printf("\n");
+}
+
+static void
+CHECK(const char *msg, isc_result_t result) {
+ if (result != ISC_R_SUCCESS) {
+ printf("FAILURE: %s: %s\n", msg, isc_result_totext(result));
+ exit(1);
+ }
+}
+
+static isc_result_t
+start(isc_entropysource_t *source, void *arg, bool blocking) {
+ isc_keyboard_t *kbd = (isc_keyboard_t *)arg;
+
+ UNUSED(source);
+
+ if (blocking)
+ printf("start called, blocking mode.\n");
+ else
+ printf("start called, non-blocking mode.\n");
+
+ return (isc_keyboard_open(kbd));
+}
+
+static void
+stop(isc_entropysource_t *source, void *arg) {
+ isc_keyboard_t *kbd = (isc_keyboard_t *)arg;
+
+ UNUSED(source);
+
+ printf("ENOUGH! Stop typing, please.\r\n");
+
+ (void)isc_keyboard_close(kbd, 3);
+ printf("stop called\n");
+}
+
+static isc_result_t
+get(isc_entropysource_t *source, void *arg, bool blocking) {
+ isc_keyboard_t *kbd = (isc_keyboard_t *)arg;
+ isc_result_t result;
+ isc_time_t t;
+ uint32_t sample;
+ uint32_t extra;
+ unsigned char c;
+
+ if (!blocking)
+ return (ISC_R_NOENTROPY);
+
+ result = isc_keyboard_getchar(kbd, &c);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ TIME_NOW(&t);
+
+ sample = isc_time_nanoseconds(&t);
+ extra = c;
+
+ result = isc_entropy_addcallbacksample(source, sample, extra);
+ if (result != ISC_R_SUCCESS) {
+ printf("\r\n");
+ return (result);
+ }
+
+ printf(".");
+ fflush(stdout);
+
+ return (result);
+}
+
+int
+main(int argc, char **argv) {
+ isc_mem_t *mctx;
+ unsigned char buffer[512];
+ isc_entropy_t *ent;
+ isc_entropysource_t *source;
+ unsigned int returned;
+ unsigned int flags;
+ isc_result_t result;
+ isc_keyboard_t kbd;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ mctx = NULL;
+ CHECK("isc_mem_create()",
+ isc_mem_create(0, 0, &mctx));
+
+ ent = NULL;
+ CHECK("isc_entropy_create()",
+ isc_entropy_create(mctx, &ent));
+
+ isc_entropy_stats(ent, stderr);
+
+ source = NULL;
+ result = isc_entropy_createcallbacksource(ent, start, get, stop, &kbd,
+ &source);
+ CHECK("isc_entropy_createcallbacksource()", result);
+
+ fprintf(stderr,
+ "Reading 32 bytes of GOOD random data only, partial OK\n");
+
+ flags = 0;
+ flags |= ISC_ENTROPY_GOODONLY;
+ flags |= ISC_ENTROPY_PARTIAL;
+ flags |= ISC_ENTROPY_BLOCKING;
+ returned = 0;
+ result = isc_entropy_getdata(ent, buffer, 32, &returned, flags);
+ if (result == ISC_R_NOENTROPY) {
+ fprintf(stderr, "No entropy.\r\n");
+ }
+
+ isc_entropy_stopcallbacksources(ent);
+
+ hex_dump("good data only:", buffer, returned);
+
+ isc_entropy_stats(ent, stderr);
+
+ isc_entropy_destroysource(&source);
+ isc_entropy_detach(&ent);
+
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/entropy_test.c b/bin/tests/optional/entropy_test.c
new file mode 100644
index 0000000..67ec640
--- /dev/null
+++ b/bin/tests/optional/entropy_test.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+static void
+hex_dump(const char *msg, void *data, unsigned int length) {
+ unsigned int len;
+ unsigned char *base;
+ bool first = true;
+
+ base = data;
+
+ printf("DUMP of %u bytes: %s\n\t", length, msg);
+ for (len = 0; len < length; len++) {
+ if (len % 16 == 0 && !first)
+ printf("\n\t");
+ printf("%02x ", base[len]);
+ first = false;
+ }
+ printf("\n");
+}
+
+static void
+CHECK(const char *msg, isc_result_t result) {
+ if (result != ISC_R_SUCCESS) {
+ printf("FAILURE: %s: %s\n", msg, isc_result_totext(result));
+ exit(1);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_mem_t *mctx;
+ unsigned char buffer[512];
+ isc_entropy_t *ent;
+ unsigned int returned;
+ unsigned int flags;
+ isc_result_t result;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ mctx = NULL;
+ CHECK("isc_mem_create()",
+ isc_mem_create(0, 0, &mctx));
+
+ ent = NULL;
+ CHECK("isc_entropy_create()",
+ isc_entropy_create(mctx, &ent));
+
+ isc_entropy_stats(ent, stderr);
+
+#if 1
+ CHECK("isc_entropy_createfilesource() 1",
+ isc_entropy_createfilesource(ent, "/dev/random"));
+ CHECK("isc_entropy_createfilesource() 2",
+ isc_entropy_createfilesource(ent, "/dev/random"));
+#else
+ CHECK("isc_entropy_createfilesource() 3",
+ isc_entropy_createfilesource(ent, "/tmp/foo"));
+#endif
+
+ fprintf(stderr,
+ "Reading 32 bytes of GOOD random data only, partial OK\n");
+
+ flags = 0;
+ flags |= ISC_ENTROPY_GOODONLY;
+ flags |= ISC_ENTROPY_PARTIAL;
+ result = isc_entropy_getdata(ent, buffer, 32, &returned, flags);
+ if (result == ISC_R_NOENTROPY) {
+ fprintf(stderr, "No entropy.\n");
+ goto any;
+ }
+ hex_dump("good data only:", buffer, returned);
+
+ any:
+ isc_entropy_stats(ent, stderr);
+ CHECK("isc_entropy_getdata() pseudorandom",
+ isc_entropy_getdata(ent, buffer, 128, NULL, 0));
+ hex_dump("pseudorandom data", buffer, 128);
+
+ isc_entropy_stats(ent, stderr);
+ flags = 0;
+ flags |= ISC_ENTROPY_GOODONLY;
+ flags |= ISC_ENTROPY_BLOCKING;
+ result = isc_entropy_getdata(ent, buffer, sizeof(buffer), &returned,
+ flags);
+ CHECK("good data only, blocking mode", result);
+ hex_dump("blocking mode data", buffer, sizeof(buffer));
+
+ {
+ isc_entropy_t *entcopy1 = NULL;
+ isc_entropy_t *entcopy2 = NULL;
+ isc_entropy_t *entcopy3 = NULL;
+
+ isc_entropy_attach(ent, &entcopy1);
+ isc_entropy_attach(ent, &entcopy2);
+ isc_entropy_attach(ent, &entcopy3);
+
+ isc_entropy_stats(ent, stderr);
+
+ isc_entropy_detach(&entcopy1);
+ isc_entropy_detach(&entcopy2);
+ isc_entropy_detach(&entcopy3);
+ }
+
+ isc_entropy_detach(&ent);
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/fsaccess_test.c b/bin/tests/optional/fsaccess_test.c
new file mode 100644
index 0000000..f2e4c24
--- /dev/null
+++ b/bin/tests/optional/fsaccess_test.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/types.h> /* Non-portable. */
+#include <sys/stat.h> /* Non-portable. */
+
+#include <isc/fsaccess.h>
+#include <isc/print.h>
+#include <isc/result.h>
+
+#define PATH "/tmp/fsaccess"
+
+int
+main(void) {
+ isc_fsaccess_t access;
+ isc_result_t result;
+ FILE *fp;
+ int n;
+
+ n = remove(PATH);
+ if (n != 0 && errno != ENOENT) {
+ fprintf(stderr, "unable to remove(%s)\n", PATH);
+ exit(1);
+ }
+ fp = fopen(PATH, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "unable to fopen(%s)\n", PATH);
+ exit(1);
+ }
+ n = chmod(PATH, 0);
+ if (n != 0) {
+ fprintf(stderr, "unable chmod(%s, 0)\n", PATH);
+ exit(1);
+ }
+
+ access = 0;
+
+ isc_fsaccess_add(ISC_FSACCESS_OWNER | ISC_FSACCESS_GROUP,
+ ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
+ &access);
+
+ printf("fsaccess=%u\n", access);
+
+ isc_fsaccess_add(ISC_FSACCESS_OTHER, ISC_FSACCESS_READ, &access);
+
+ printf("fsaccess=%u\n", access);
+
+ result = isc_fsaccess_set(PATH, access);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "result = %s\n", isc_result_totext(result));
+ (void)fclose(fp);
+
+ return (0);
+}
diff --git a/bin/tests/optional/gsstest.c b/bin/tests/optional/gsstest.c
new file mode 100644
index 0000000..90059d2
--- /dev/null
+++ b/bin/tests/optional/gsstest.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.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>
+
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/masterdump.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/types.h>
+
+#include <dst/result.h>
+
+#ifdef GSSAPI
+#include ISC_PLATFORM_GSSAPIHEADER
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \
+ goto end; \
+ } \
+}
+
+static dns_fixedname_t servername, gssname;
+
+static isc_mem_t *mctx;
+static dns_requestmgr_t *requestmgr;
+static isc_sockaddr_t address;
+
+static dns_tsig_keyring_t *ring;
+static dns_tsigkey_t *tsigkey = NULL;
+static gss_ctx_id_t gssctx;
+static gss_ctx_id_t *gssctxp = &gssctx;
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define PORT 53
+#define TIMEOUT 30
+
+static void initctx1(isc_task_t *task, isc_event_t *event);
+static void sendquery(isc_task_t *task, isc_event_t *event);
+static void setup();
+
+static void
+console(isc_task_t *task, isc_event_t *event)
+{
+ char buf[32];
+ int c;
+
+ isc_event_t *ev = NULL;
+
+ isc_event_free(&event);
+
+ for (;;) {
+ printf("\nCommand => ");
+ c = scanf("%31s", buf);
+
+ if (c == EOF || strcmp(buf, "quit") == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ if (strcmp(buf, "initctx") == 0) {
+ ev = isc_event_allocate(mctx, (void *)1, 1, initctx1,
+ NULL, sizeof(*event));
+ isc_task_send(task, &ev);
+ return;
+ }
+
+ if (strcmp(buf, "query") == 0) {
+ ev = isc_event_allocate(mctx, (void *)1, 1, sendquery,
+ NULL, sizeof(*event));
+ isc_task_send(task, &ev);
+ return;
+ }
+
+ printf("Unknown command\n");
+ }
+}
+
+static void
+recvresponse(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result, result2;
+ dns_message_t *query = NULL, *response = NULL;
+ isc_buffer_t outtoken;
+ isc_buffer_t outbuf;
+ char output[10 * 1024];
+
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ isc_buffer_init(&outtoken, array, sizeof(array));
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ query = reqev->ev_arg;
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ goto end;
+ }
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ printf("\nReceived Response:\n");
+
+ result2 = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(response, &dns_master_style_debug, 0,
+ &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ CHECK("dns_request_getresponse", result2);
+
+ if (response != NULL)
+ dns_message_destroy(&response);
+
+ end:
+ if (query != NULL)
+ dns_message_destroy(&query);
+
+ if (reqev->request != NULL)
+ dns_request_destroy(&reqev->request);
+
+ isc_event_free(&event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);
+ return;
+}
+
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event)
+{
+ 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;
+ isc_buffer_t outbuf;
+ char output[10 * 1024];
+ static char host[256];
+ int c;
+
+ isc_event_free(&event);
+
+ printf("Query => ");
+ c = scanf("%255s", host);
+ if (c == EOF)
+ return;
+
+ 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);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ message->opcode = dns_opcode_query;
+ message->rdclass = dns_rdataclass_in;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ result = dns_message_gettempname(message, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ dns_name_init(qname, NULL);
+ 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, &address, 0, tsigkey,
+ TIMEOUT, task, recvresponse,
+ message, &request);
+ CHECK("dns_request_create", result);
+
+ printf("Submitting query:\n");
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(message, &dns_master_style_debug, 0,
+ &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ return;
+
+ end:
+ if (qname != NULL)
+ dns_message_puttempname(message, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(message, &qrdataset);
+ if (message != NULL)
+ dns_message_destroy(&message);
+}
+
+static void
+initctx2(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;
+ isc_buffer_t outtoken;
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t qtype;
+ dns_name_t *question_name;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ query = reqev->ev_arg;
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ goto end;
+ }
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ goto end;
+ }
+
+ printf("Received token from server, calling gss_init_sec_context()\n");
+ isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1);
+ result = dns_tkey_processgssresponse(query, response,
+ dns_fixedname_name(&gssname),
+ &gssctx, &outtoken,
+ &tsigkey, ring, NULL);
+ gssctx = *gssctxp;
+ CHECK("dns_tkey_processgssresponse", result);
+ printf("Context accepted\n");
+
+ question_name = NULL;
+ dns_message_currentname(response, DNS_SECTION_ANSWER, &question_name);
+ rdataset = ISC_LIST_HEAD(question_name->list);
+ INSIST(rdataset != NULL);
+ qtype = rdataset->type;
+ if (qtype == dns_rdatatype_tkey) {
+ printf("Received TKEY response from server\n");
+ printf("Context completed\n");
+ } else {
+ printf("Did not receive TKEY response from server\n");
+ printf("Context not completed\n");
+ dns_tsigkey_detach(&tsigkey);
+ tsigkey = NULL;
+ }
+
+ dns_message_destroy(&response);
+
+ end:
+ if (query != NULL)
+ dns_message_destroy(&query);
+
+ if (reqev->request != NULL)
+ dns_request_destroy(&reqev->request);
+
+ isc_event_free(&event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);
+ return;
+}
+
+static void
+initctx1(isc_task_t *task, isc_event_t *event) {
+ char gssid[512];
+ char contextname[512];
+ isc_result_t result;
+ isc_buffer_t buf;
+ dns_message_t *query;
+ dns_request_t *request;
+ int c;
+
+ isc_event_free(&event);
+
+ printf("Initctx - GSS name => ");
+ c = scanf("%511s", gssid);
+ if (c == EOF)
+ return;
+
+ snprintf(contextname, sizeof(contextname),
+ "gsstest.context.%d.", (int)time(NULL));
+
+ printf("Initctx - context name we're using: %s\n", contextname);
+
+ printf("Negotiating GSSAPI context: ");
+ printf("%s", gssid);
+ printf("\n");
+
+ /*
+ * Setup a GSSAPI context with the server
+ */
+ dns_fixedname_init(&servername);
+ isc_buffer_init(&buf, contextname, strlen(contextname));
+ isc_buffer_add(&buf, strlen(contextname));
+ result = dns_name_fromtext(dns_fixedname_name(&servername), &buf,
+ dns_rootname, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ /* Make name happen */
+ dns_fixedname_init(&gssname);
+ isc_buffer_init(&buf, gssid, strlen(gssid));
+ isc_buffer_add(&buf, strlen(gssid));
+ result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf,
+ dns_rootname, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ printf("Calling gss_init_sec_context()\n");
+ gssctx = GSS_C_NO_CONTEXT;
+ result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername),
+ dns_fixedname_name(&gssname),
+ NULL, 36000, &gssctx, true,
+ mctx, NULL);
+ CHECK("dns_tkey_buildgssquery", result);
+
+ printf("Sending context token to server\n");
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address, 0, NULL,
+ TIMEOUT, task, initctx2, query, &request);
+ CHECK("dns_request_create", result);
+
+ return;
+ end:
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);return;
+}
+
+static void
+setup(void)
+{
+ for (;;) {
+ char serveraddress[512];
+ struct in_addr inaddr;
+ int c;
+
+ printf("Server IP => ");
+ c = scanf("%511s", serveraddress);
+
+ if (c == EOF || strcmp(serveraddress, "quit") == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ if (inet_pton(AF_INET, serveraddress, &inaddr) == 1) {
+ isc_sockaddr_fromin(&address, &inaddr, PORT);
+ return;
+ }
+
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ isc_task_t *task;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_logdestination_t destination;
+
+ UNUSED(argv);
+ UNUSED(argc);
+
+ RUNCHECK(isc_app_start());
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ RUNCHECK(isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME));
+ RUNCHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL));
+
+ isc_log_setdebuglevel(lctx, 9);
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "/dev/urandom"));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ setup();
+
+ RUNCHECK(isc_app_onrun(mctx, task, console, NULL));
+
+ (void)isc_app_run();
+
+ if (tsigkey)
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_timermgr_destroy(&timermgr);
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+
+ isc_mem_stats(mctx, stdout);
+
+ dns_view_detach(&view);
+
+ dst_lib_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
+#else
+int
+main(int argc, char *argv[]) {
+ UNUSED(argc);
+ UNUSED(argv);
+ fprintf(stderr, "R:GSSAPIONLY\n");
+ return (0);
+}
+#endif
diff --git a/bin/tests/optional/gxba_test.c b/bin/tests/optional/gxba_test.c
new file mode 100644
index 0000000..61c6a34
--- /dev/null
+++ b/bin/tests/optional/gxba_test.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#include <lwres/netdb.h>
+
+static void
+print_he(struct hostent *he, int error, const char *fun, const char *name) {
+ char **c;
+ int i;
+
+ if (he != NULL) {
+ printf("%s(%s):\n", fun, name);
+ printf("\tname = %s\n", he->h_name);
+ printf("\taddrtype = %d\n", he->h_addrtype);
+ printf("\tlength = %d\n", he->h_length);
+ c = he->h_aliases;
+ i = 1;
+ while (*c != NULL) {
+ printf("\talias[%d] = %s\n", i, *c);
+ i++;
+ c++;
+ }
+ c = he->h_addr_list;
+ i = 1;
+ while (*c != NULL) {
+ char buf[128];
+ inet_ntop(he->h_addrtype, *c, buf, sizeof(buf));
+ printf("\taddress[%d] = %s\n", i, buf);
+ c++;
+ i++;
+ }
+ } else {
+ printf("%s(%s): error = %d (%s)\n", fun, name, error,
+ hstrerror(error));
+ }
+}
+
+int
+main(int argc, char **argv) {
+ struct hostent *he;
+ int error;
+ struct in_addr in_addr;
+ struct in6_addr in6_addr;
+ void *addr;
+ int af;
+ size_t len;
+
+ (void)argc;
+
+ while (argv[1] != NULL) {
+ if (inet_pton(AF_INET, argv[1], &in_addr) == 1) {
+ af = AF_INET;
+ addr = &in_addr;
+ len = sizeof(in_addr);
+ } else if (inet_pton(AF_INET6, argv[1], &in6_addr) == 1) {
+ af = AF_INET6;
+ addr = &in6_addr;
+ len = sizeof(in6_addr);
+ } else {
+ printf("unable to convert \"%s\" to an address\n",
+ argv[1]);
+ argv++;
+ continue;
+ }
+ he = gethostbyaddr(addr, len, af);
+ print_he(he, h_errno, "gethostbyaddr", argv[1]);
+
+ he = getipnodebyaddr(addr, len, af, &error);
+ print_he(he, error, "getipnodebyaddr", argv[1]);
+ if (he != NULL)
+ freehostent(he);
+ argv++;
+ }
+ return (0);
+}
diff --git a/bin/tests/optional/gxbn_test.c b/bin/tests/optional/gxbn_test.c
new file mode 100644
index 0000000..68f4204
--- /dev/null
+++ b/bin/tests/optional/gxbn_test.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#include <lwres/netdb.h>
+
+static void
+print_he(struct hostent *he, int error, const char *fun, const char *name) {
+ char **c;
+ int i;
+
+ if (he != NULL) {
+ printf("%s(%s):\n", fun, name);
+ printf("\tname = %s\n", he->h_name);
+ printf("\taddrtype = %d\n", he->h_addrtype);
+ printf("\tlength = %d\n", he->h_length);
+ c = he->h_aliases;
+ i = 1;
+ while (*c != NULL) {
+ printf("\talias[%d] = %s\n", i, *c);
+ i++;
+ c++;
+ }
+ c = he->h_addr_list;
+ i = 1;
+ while (*c != NULL) {
+ char buf[128];
+ inet_ntop(he->h_addrtype, *c, buf, sizeof(buf));
+ printf("\taddress[%d] = %s\n", i, buf);
+ c++;
+ i++;
+ }
+ } else {
+ printf("%s(%s): error = %d (%s)\n", fun, name, error,
+ hstrerror(error));
+ }
+}
+
+int
+main(int argc, char **argv) {
+ struct hostent *he;
+ int error;
+
+ (void)argc;
+
+ while (argv[1] != NULL) {
+ he = gethostbyname(argv[1]);
+ print_he(he, h_errno, "gethostbyname", argv[1]);
+
+ he = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT|AI_ALL,
+ &error);
+ print_he(he, error, "getipnodebyname", argv[1]);
+ if (he != NULL)
+ freehostent(he);
+
+ he = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT,
+ &error);
+ print_he(he, error, "getipnodebyname", argv[1]);
+ if (he != NULL)
+ freehostent(he);
+ argv++;
+ }
+ return (0);
+}
diff --git a/bin/tests/optional/hash_test.c b/bin/tests/optional/hash_test.c
new file mode 100644
index 0000000..bf2891a
--- /dev/null
+++ b/bin/tests/optional/hash_test.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/util.h>
+#include <isc/print.h>
+#include <isc/string.h>
+
+#include <pk11/site.h>
+
+static void
+print_digest(const char *s, const char *hash, unsigned char *d,
+ unsigned int words)
+{
+ unsigned int i, j;
+
+ printf("hash (%s) %s:\n\t", hash, s);
+ for (i = 0; i < words; i++) {
+ printf(" ");
+ for (j = 0; j < 4; j++)
+ printf("%02x", d[i * 4 + j]);
+ }
+ printf("\n");
+}
+
+int
+main(int argc, char **argv) {
+ isc_sha1_t sha1;
+ isc_sha224_t sha224;
+#ifndef PK11_MD5_DISABLE
+ isc_md5_t md5;
+ isc_hmacmd5_t hmacmd5;
+#endif
+ isc_hmacsha1_t hmacsha1;
+ isc_hmacsha224_t hmacsha224;
+ isc_hmacsha256_t hmacsha256;
+ isc_hmacsha384_t hmacsha384;
+ isc_hmacsha512_t hmacsha512;
+ unsigned char digest[ISC_SHA512_DIGESTLENGTH];
+ unsigned char buffer[1024];
+ const char *s;
+ unsigned char key[20];
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ s = "abc";
+ isc_sha1_init(&sha1);
+ memmove(buffer, s, strlen(s));
+ isc_sha1_update(&sha1, buffer, strlen(s));
+ isc_sha1_final(&sha1, digest);
+ print_digest(s, "sha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ isc_sha1_init(&sha1);
+ memmove(buffer, s, strlen(s));
+ isc_sha1_update(&sha1, buffer, strlen(s));
+ isc_sha1_final(&sha1, digest);
+ print_digest(s, "sha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "abc";
+ isc_sha224_init(&sha224);
+ memmove(buffer, s, strlen(s));
+ isc_sha224_update(&sha224, buffer, strlen(s));
+ isc_sha224_final(digest, &sha224);
+ print_digest(s, "sha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ isc_sha224_init(&sha224);
+ memmove(buffer, s, strlen(s));
+ isc_sha224_update(&sha224, buffer, strlen(s));
+ isc_sha224_final(digest, &sha224);
+ print_digest(s, "sha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+#ifndef PK11_MD5_DISABLE
+ s = "abc";
+ isc_md5_init(&md5);
+ memmove(buffer, s, strlen(s));
+ isc_md5_update(&md5, buffer, strlen(s));
+ isc_md5_final(&md5, digest);
+ print_digest(s, "md5", digest, 4);
+
+ /*
+ * The 3 HMAC-MD5 examples from RFC2104
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 16);
+ isc_hmacmd5_init(&hmacmd5, key, 16);
+ memmove(buffer, s, strlen(s));
+ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s));
+ isc_hmacmd5_sign(&hmacmd5, digest);
+ print_digest(s, "hmacmd5", digest, 4);
+
+ s = "what do ya want for nothing?";
+ strlcpy((char *)key, "Jefe", sizeof(key));
+ isc_hmacmd5_init(&hmacmd5, key, 4);
+ memmove(buffer, s, strlen(s));
+ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s));
+ isc_hmacmd5_sign(&hmacmd5, digest);
+ print_digest(s, "hmacmd5", digest, 4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 16);
+ isc_hmacmd5_init(&hmacmd5, key, 16);
+ memmove(buffer, s, strlen(s));
+ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s));
+ isc_hmacmd5_sign(&hmacmd5, digest);
+ print_digest(s, "hmacmd5", digest, 4);
+#endif
+
+ /*
+ * The 3 HMAC-SHA1 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha1_init(&hmacsha1, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha1_update(&hmacsha1, buffer, strlen(s));
+ isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+ print_digest(s, "hmacsha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strlcpy((char *)key, "Jefe", sizeof(key));
+ isc_hmacsha1_init(&hmacsha1, key, 4);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha1_update(&hmacsha1, buffer, strlen(s));
+ isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+ print_digest(s, "hmacsha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha1_init(&hmacsha1, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha1_update(&hmacsha1, buffer, strlen(s));
+ isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+ print_digest(s, "hmacsha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA224 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha224_init(&hmacsha224, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha224_update(&hmacsha224, buffer, strlen(s));
+ isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+ print_digest(s, "hmacsha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strlcpy((char *)key, "Jefe", sizeof(key));
+ isc_hmacsha224_init(&hmacsha224, key, 4);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha224_update(&hmacsha224, buffer, strlen(s));
+ isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+ print_digest(s, "hmacsha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha224_init(&hmacsha224, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha224_update(&hmacsha224, buffer, strlen(s));
+ isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+ print_digest(s, "hmacsha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA256 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha256_init(&hmacsha256, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha256_update(&hmacsha256, buffer, strlen(s));
+ isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+ print_digest(s, "hmacsha256", digest, ISC_SHA256_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strlcpy((char *)key, "Jefe", sizeof(key));
+ isc_hmacsha256_init(&hmacsha256, key, 4);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha256_update(&hmacsha256, buffer, strlen(s));
+ isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+ print_digest(s, "hmacsha256", digest, ISC_SHA256_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha256_init(&hmacsha256, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha256_update(&hmacsha256, buffer, strlen(s));
+ isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+ print_digest(s, "hmacsha256", digest, ISC_SHA256_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA384 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha384_init(&hmacsha384, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha384_update(&hmacsha384, buffer, strlen(s));
+ isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+ print_digest(s, "hmacsha384", digest, ISC_SHA384_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strlcpy((char *)key, "Jefe", sizeof(key));
+ isc_hmacsha384_init(&hmacsha384, key, 4);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha384_update(&hmacsha384, buffer, strlen(s));
+ isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+ print_digest(s, "hmacsha384", digest, ISC_SHA384_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha384_init(&hmacsha384, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha384_update(&hmacsha384, buffer, strlen(s));
+ isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+ print_digest(s, "hmacsha384", digest, ISC_SHA384_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA512 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha512_init(&hmacsha512, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha512_update(&hmacsha512, buffer, strlen(s));
+ isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+ print_digest(s, "hmacsha512", digest, ISC_SHA512_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strlcpy((char *)key, "Jefe", sizeof(key));
+ isc_hmacsha512_init(&hmacsha512, key, 4);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha512_update(&hmacsha512, buffer, strlen(s));
+ isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+ print_digest(s, "hmacsha512", digest, ISC_SHA512_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha512_init(&hmacsha512, key, 20);
+ memmove(buffer, s, strlen(s));
+ isc_hmacsha512_update(&hmacsha512, buffer, strlen(s));
+ isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+ print_digest(s, "hmacsha512", digest, ISC_SHA512_DIGESTLENGTH/4);
+
+ return (0);
+}
diff --git a/bin/tests/optional/inter_test.c b/bin/tests/optional/inter_test.c
new file mode 100644
index 0000000..42a4ec5
--- /dev/null
+++ b/bin/tests/optional/inter_test.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+int
+main(int argc, char **argv) {
+ isc_mem_t *mctx = NULL;
+ isc_interfaceiter_t *iter = NULL;
+ isc_interface_t ifdata;
+ isc_result_t result;
+ const char * res;
+ char buf[128];
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ result = isc_interfaceiter_create(mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_interfaceiter_first(iter);
+ while (result == ISC_R_SUCCESS) {
+ result = isc_interfaceiter_current(iter, &ifdata);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "isc_interfaceiter_current: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ fprintf(stdout, "%s %u %x\n", ifdata.name, ifdata.af,
+ ifdata.flags);
+ INSIST(ifdata.af == AF_INET || ifdata.af == AF_INET6);
+ res = inet_ntop(ifdata.af, &ifdata.address.type, buf,
+ sizeof(buf));
+ if (ifdata.address.zone != 0)
+ fprintf(stdout, "address = %s (zone %u)\n",
+ res == NULL ? "BAD" : res,
+ ifdata.address.zone);
+ else
+ fprintf(stdout, "address = %s\n",
+ res == NULL ? "BAD" : res);
+ INSIST(ifdata.address.family == ifdata.af);
+ res = inet_ntop(ifdata.af, &ifdata.netmask.type, buf,
+ sizeof(buf));
+ fprintf(stdout, "netmask = %s\n", res == NULL ? "BAD" : res);
+ INSIST(ifdata.netmask.family == ifdata.af);
+ if ((ifdata.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ res = inet_ntop(ifdata.af, &ifdata.dstaddress.type,
+ buf, sizeof(buf));
+ fprintf(stdout, "dstaddress = %s\n",
+ res == NULL ? "BAD" : res);
+
+ INSIST(ifdata.dstaddress.family == ifdata.af);
+ }
+ result = isc_interfaceiter_next(iter);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
+ fprintf(stdout, "isc_interfaceiter_next: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ }
+ isc_interfaceiter_destroy(&iter);
+
+ fprintf(stdout, "\nPass 2\n\n");
+
+ result = isc_interfaceiter_create(mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_interfaceiter_first(iter);
+ while (result == ISC_R_SUCCESS) {
+ result = isc_interfaceiter_current(iter, &ifdata);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "isc_interfaceiter_current: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ fprintf(stdout, "%s %u %x\n", ifdata.name, ifdata.af,
+ ifdata.flags);
+ INSIST(ifdata.af == AF_INET || ifdata.af == AF_INET6);
+ res = inet_ntop(ifdata.af, &ifdata.address.type, buf,
+ sizeof(buf));
+ if (ifdata.address.zone != 0)
+ fprintf(stdout, "address = %s (zone %u)\n",
+ res == NULL ? "BAD" : res,
+ ifdata.address.zone);
+ else
+ fprintf(stdout, "address = %s\n",
+ res == NULL ? "BAD" : res);
+ INSIST(ifdata.address.family == ifdata.af);
+ res = inet_ntop(ifdata.af, &ifdata.netmask.type, buf,
+ sizeof(buf));
+ fprintf(stdout, "netmask = %s\n", res == NULL ? "BAD" : res);
+ INSIST(ifdata.netmask.family == ifdata.af);
+ if ((ifdata.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ res = inet_ntop(ifdata.af, &ifdata.dstaddress.type,
+ buf, sizeof(buf));
+ fprintf(stdout, "dstaddress = %s\n",
+ res == NULL ? "BAD" : res);
+
+ INSIST(ifdata.dstaddress.family == ifdata.af);
+ }
+ result = isc_interfaceiter_next(iter);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
+ fprintf(stdout, "isc_interfaceiter_next: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ }
+ isc_interfaceiter_destroy(&iter);
+ cleanup:
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/keyboard_test.c b/bin/tests/optional/keyboard_test.c
new file mode 100644
index 0000000..085b314
--- /dev/null
+++ b/bin/tests/optional/keyboard_test.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/keyboard.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+static void
+CHECK(const char *msg, isc_result_t result) {
+ if (result != ISC_R_SUCCESS) {
+ printf("FAILURE: %s: %s\n", msg, isc_result_totext(result));
+ exit(1);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_keyboard_t kbd;
+ unsigned char c;
+ isc_result_t res;
+ unsigned int count;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ printf("Type Q to exit.\n");
+
+ res = isc_keyboard_open(&kbd);
+ CHECK("isc_keyboard_open()", res);
+
+ c = 'x';
+ count = 0;
+ while (res == ISC_R_SUCCESS && c != 'Q') {
+ res = isc_keyboard_getchar(&kbd, &c);
+ printf(".");
+ fflush(stdout);
+ count++;
+ if (count % 64 == 0)
+ printf("\r\n");
+ }
+ printf("\r\n");
+ if (res != ISC_R_SUCCESS) {
+ printf("FAILURE: keyboard getchar failed: %s\r\n",
+ isc_result_totext(res));
+ goto errout;
+ }
+
+ errout:
+ res = isc_keyboard_close(&kbd, 3);
+ CHECK("isc_keyboard_close()", res);
+
+ return (0);
+}
diff --git a/bin/tests/optional/lex_test.c b/bin/tests/optional/lex_test.c
new file mode 100644
index 0000000..4631242
--- /dev/null
+++ b/bin/tests/optional/lex_test.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <isc/commandline.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+isc_lex_t *lex;
+
+isc_lexspecials_t specials;
+
+static void
+print_token(isc_token_t *tokenp, FILE *stream) {
+ switch (tokenp->type) {
+ case isc_tokentype_unknown:
+ fprintf(stream, "UNKNOWN");
+ break;
+ case isc_tokentype_string:
+ fprintf(stream, "STRING %.*s",
+ (int)tokenp->value.as_region.length,
+ tokenp->value.as_region.base);
+ break;
+ case isc_tokentype_number:
+ fprintf(stream, "NUMBER %lu", tokenp->value.as_ulong);
+ break;
+ case isc_tokentype_qstring:
+ fprintf(stream, "QSTRING \"%.*s\"",
+ (int)tokenp->value.as_region.length,
+ tokenp->value.as_region.base);
+ break;
+ case isc_tokentype_eol:
+ fprintf(stream, "EOL");
+ break;
+ case isc_tokentype_eof:
+ fprintf(stream, "EOF");
+ break;
+ case isc_tokentype_initialws:
+ fprintf(stream, "INITIALWS");
+ break;
+ case isc_tokentype_special:
+ fprintf(stream, "SPECIAL %c", tokenp->value.as_char);
+ break;
+ case isc_tokentype_nomore:
+ fprintf(stream, "NOMORE");
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__, "Unexpected type %d",
+ tokenp->type);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_token_t token;
+ isc_result_t result;
+ int quiet = 0;
+ int c;
+ int masterfile = 1;
+ int stats = 0;
+ unsigned int options = 0;
+ int done = 0;
+
+ while ((c = isc_commandline_parse(argc, argv, "qmcs")) != -1) {
+ switch (c) {
+ case 'q':
+ quiet = 1;
+ break;
+ case 'm':
+ masterfile = 1;
+ break;
+ case 'c':
+ masterfile = 0;
+ break;
+ case 's':
+ stats = 1;
+ break;
+ }
+ }
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS);
+
+ if (masterfile) {
+ /* Set up to lex DNS master file. */
+
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE |
+ ISC_LEXOPT_EOF |
+ ISC_LEXOPT_QSTRING | ISC_LEXOPT_NOMORE;
+ isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+ } else {
+ /* Set up to lex DNS config file. */
+
+ specials['{'] = 1;
+ specials['}'] = 1;
+ specials[';'] = 1;
+ specials['/'] = 1;
+ specials['"'] = 1;
+ specials['!'] = 1;
+ specials['*'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_EOF |
+ ISC_LEXOPT_QSTRING |
+ ISC_LEXOPT_NUMBER | ISC_LEXOPT_NOMORE;
+ isc_lex_setcomments(lex, (ISC_LEXCOMMENT_C|
+ ISC_LEXCOMMENT_CPLUSPLUS|
+ ISC_LEXCOMMENT_SHELL));
+ }
+
+ RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS);
+
+ while ((result = isc_lex_gettoken(lex, options, &token)) ==
+ ISC_R_SUCCESS && !done) {
+ if (!quiet) {
+ char *name = isc_lex_getsourcename(lex);
+ print_token(&token, stdout);
+ printf(" line = %lu file = %s\n",
+ isc_lex_getsourceline(lex),
+ (name == NULL) ? "<none>" : name);
+ }
+ if (token.type == isc_tokentype_eof)
+ isc_lex_close(lex);
+ if (token.type == isc_tokentype_nomore)
+ done = 1;
+ }
+ if (result != ISC_R_SUCCESS)
+ printf("Result: %s\n", isc_result_totext(result));
+
+ isc_lex_close(lex);
+ isc_lex_destroy(&lex);
+ if (!quiet && stats)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/lfsr_test.c b/bin/tests/optional/lfsr_test.c
new file mode 100644
index 0000000..28303e0
--- /dev/null
+++ b/bin/tests/optional/lfsr_test.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <isc/lfsr.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+uint32_t state[1024 * 64];
+
+int
+main(int argc, char **argv) {
+ isc_lfsr_t lfsr1, lfsr2;
+ int i;
+ uint32_t temp;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ /*
+ * Verify that returned values are reproducable.
+ */
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &state[i], 4);
+ printf("lfsr1: state[%2d] = %08x\n", i, state[i]);
+ }
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &temp, 4);
+ if (state[i] != temp)
+ printf("lfsr1: state[%2d] = %08x, "
+ "but new state is %08x\n",
+ i, state[i], temp);
+ }
+
+ /*
+ * Now do the same with skipping.
+ */
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &state[i], 4);
+ isc_lfsr_skip(&lfsr1, 32);
+ printf("lfsr1: state[%2d] = %08x\n", i, state[i]);
+ }
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &temp, 4);
+ isc_lfsr_skip(&lfsr1, 32);
+ if (state[i] != temp)
+ printf("lfsr1: state[%2d] = %08x, "
+ "but new state is %08x\n",
+ i, state[i], temp);
+ }
+
+ /*
+ * Try to find the period of the LFSR.
+ *
+ * x^16 + x^5 + x^3 + x^2 + 1
+ */
+ isc_lfsr_init(&lfsr2, 0, 16, 0x00008016U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr2, &state[i], 4);
+ printf("lfsr2: state[%2d] = %08x\n", i, state[i]);
+ }
+ isc_lfsr_init(&lfsr2, 0, 16, 0x00008016U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr2, &temp, 4);
+ if (state[i] != temp)
+ printf("lfsr2: state[%2d] = %08x, "
+ "but new state is %08x\n",
+ i, state[i], temp);
+ }
+
+ return (0);
+}
diff --git a/bin/tests/optional/log_test.c b/bin/tests/optional/log_test.c
new file mode 100644
index 0000000..1120753
--- /dev/null
+++ b/bin/tests/optional/log_test.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/log.h>
+
+#define TEST_FILE "/tmp/test_log"
+#define SYSLOG_FILE "/var/log/daemon.log"
+#define FILE_VERSIONS 10
+
+char usage[] = "Usage: %s [-m] [-s syslog_logfile] [-r file_versions]\n";
+
+#define CHECK(expr) result = expr; \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s: " #expr "%s: exiting\n", \
+ progname, isc_result_totext(result)); \
+ }
+
+int
+main(int argc, char **argv) {
+ const char *progname, *syslog_file, *message;
+ int ch, i, file_versions, stderr_line;
+ bool show_final_mem = false;
+ isc_log_t *lctx;
+ isc_logconfig_t *lcfg;
+ isc_mem_t *mctx;
+ isc_result_t result;
+ isc_logdestination_t destination;
+ const isc_logcategory_t *category;
+ const isc_logmodule_t *module;
+
+ progname = strrchr(*argv, '/');
+ if (progname != NULL)
+ progname++;
+ else
+ progname = *argv;
+
+ syslog_file = SYSLOG_FILE;
+ file_versions = FILE_VERSIONS;
+
+ while ((ch = isc_commandline_parse(argc, argv, "ms:r:")) != -1) {
+ switch (ch) {
+ case 'm':
+ show_final_mem = true;
+ break;
+ case 's':
+ syslog_file = isc_commandline_argument;
+ break;
+ case 'r':
+ file_versions = atoi(isc_commandline_argument);
+ if (file_versions < 0 &&
+ file_versions != ISC_LOG_ROLLNEVER &&
+ file_versions != ISC_LOG_ROLLINFINITE) {
+ fprintf(stderr, "%s: file rotations must be "
+ "%d (ISC_LOG_ROLLNEVER),\n\t"
+ "%d (ISC_LOG_ROLLINFINITE) "
+ "or > 0\n", progname,
+ ISC_LOG_ROLLNEVER,
+ ISC_LOG_ROLLINFINITE);
+ exit(1);
+ }
+ break;
+ case '?':
+ fprintf(stderr, usage, progname);
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc > 0) {
+ fprintf(stderr, usage, progname);
+ exit(1);
+ }
+
+ fprintf(stderr, "EXPECT:\n%s%d%s%s%s",
+ "8 lines to stderr (first 4 numbered, #3 repeated)\n",
+ file_versions == 0 || file_versions == ISC_LOG_ROLLNEVER ? 1 :
+ file_versions > 0 ? file_versions + 1 : FILE_VERSIONS + 1,
+ " " TEST_FILE " files, and\n",
+ "2 lines to syslog\n",
+ "lines ending with exclamation marks are errors\n\n");
+
+ isc_log_opensyslog(progname, LOG_PID, LOG_DAEMON);
+
+ mctx = NULL;
+ lctx = NULL;
+ lcfg = NULL;
+
+ CHECK(isc_mem_create(0, 0, &mctx));
+ CHECK(isc_log_create(mctx, &lctx, &lcfg));
+
+ CHECK(isc_log_settag(lcfg, progname));
+
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Test isc_log_categorybyname and isc_log_modulebyname.
+ */
+ category = isc_log_categorybyname(lctx, "notify");
+ if (category != NULL)
+ fprintf(stderr, "%s category found. (expected)\n",
+ category->name);
+ else
+ fprintf(stderr, "notify category not found!\n");
+
+ module = isc_log_modulebyname(lctx, "xyzzy");
+ if (module != NULL)
+ fprintf(stderr, "%s module found!\n", module->name);
+ else
+ fprintf(stderr, "xyzzy module not found. (expected)\n");
+
+ /*
+ * Create a file channel to test file opening, size limiting and
+ * version rolling.
+ */
+
+ destination.file.name = TEST_FILE;
+ destination.file.maximum_size = 1;
+ destination.file.versions = file_versions;
+
+ CHECK(isc_log_createchannel(lcfg, "file_test", ISC_LOG_TOFILE,
+ ISC_LOG_INFO, &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_PRINTTAG|
+ ISC_LOG_PRINTLEVEL|
+ ISC_LOG_PRINTCATEGORY|
+ ISC_LOG_PRINTMODULE));
+
+ /*
+ * Create a dynamic debugging channel to a file descriptor.
+ */
+ destination.file.stream = stderr;
+
+ CHECK(isc_log_createchannel(lcfg, "debug_test", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_PRINTLEVEL|
+ ISC_LOG_DEBUGONLY));
+
+ /*
+ * Test the usability of the four predefined logging channels.
+ */
+ CHECK(isc_log_usechannel(lcfg, "default_syslog",
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE));
+ CHECK(isc_log_usechannel(lcfg, "default_stderr",
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE));
+ CHECK(isc_log_usechannel(lcfg, "default_debug",
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE));
+ CHECK(isc_log_usechannel(lcfg, "null",
+ DNS_LOGCATEGORY_DATABASE,
+ NULL));
+
+ /*
+ * Use the custom channels.
+ */
+ CHECK(isc_log_usechannel(lcfg, "file_test",
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB));
+
+ CHECK(isc_log_usechannel(lcfg, "debug_test",
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_RBTDB));
+
+ fprintf(stderr, "\n==> stderr begin\n");
+
+ /*
+ * Write to the internal default by testing both a category for which
+ * no channel has been specified and a category which was specified
+ * but not with the named module.
+ */
+ stderr_line = 1;
+
+ isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
+ ISC_LOG_CRITICAL, "%s (%d)",
+ "Unspecified category and unspecified module to stderr",
+ stderr_line++);
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBT,
+ ISC_LOG_CRITICAL, "%s (%d)",
+ "Specified category and unspecified module to stderr",
+ stderr_line++);
+
+ /*
+ * Write to default_syslog, default_stderr and default_debug.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING, "%s (%d twice)",
+ "Using the predefined channels to syslog+stderr",
+ stderr_line++);
+
+ /*
+ * Write to predefined null channel.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_INFO, "This is to null and should not appear!");
+
+ /*
+ * Reset the internal default to use syslog instead of stderr,
+ * and test it.
+ */
+ CHECK(isc_log_usechannel(lcfg, "default_syslog",
+ ISC_LOGCATEGORY_DEFAULT, NULL));
+ isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
+ ISC_LOG_ERROR, "%s%s",
+ "This message to the redefined default category should ",
+ "be second in syslog");
+ /*
+ * Write to the file channel.
+ */
+ if (file_versions >= 0 || file_versions == ISC_LOG_ROLLINFINITE) {
+
+ /*
+ * If file_versions is 0 or ISC_LOG_ROLLINFINITE, write
+ * the "should not appear" and "should be in file" messages
+ * to ensure they get rolled.
+ */
+ if (file_versions <= 0)
+ file_versions = FILE_VERSIONS;
+
+ else
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "This should be rolled over "
+ "and not appear!");
+
+ for (i = file_versions - 1; i >= 0; i--)
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "should be in file %d/%d", i,
+ file_versions - 1);
+
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "should be in base file");
+ } else {
+ file_versions = FILE_VERSIONS;
+ for (i = 1; i <= file_versions; i++)
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "This is message %d in the log file", i);
+ }
+
+
+ /*
+ * Write a debugging message to a category that has no
+ * debugging channels for the named module.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DB,
+ ISC_LOG_DEBUG(1),
+ "This debug message should not appear!");
+
+ /*
+ * Write debugging messages to a dynamic debugging channel.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "This critical message should "
+ "not appear because the debug level is 0!");
+
+ isc_log_setdebuglevel(lctx, 3);
+
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_DEBUG(1), "%s (%d)",
+ "Dynamic debugging to stderr", stderr_line++);
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_DEBUG(5),
+ "This debug level is too high and should not appear!");
+
+ /*
+ * Test out the duplicate filtering using the debug_test channel.
+ */
+ isc_log_setduplicateinterval(lcfg, 10);
+ message = "This message should appear only once on stderr";
+
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "%s", message);
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "%s", message);
+
+ isc_log_setduplicateinterval(lcfg, 1);
+ message = "This message should appear twice on stderr";
+
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "%s", message);
+ sleep(2);
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "%s", message);
+
+ /*
+ * Review where everything went.
+ * XXXDCL NT
+ */
+ fputc('\n', stderr);
+ if (system("head " TEST_FILE "*; rm -f " TEST_FILE "*") != 0) {
+ fprintf(stderr, "system(\"head " TEST_FILE "*; rm -f "
+ TEST_FILE "*\") failed\n");
+ goto cleanup;
+ }
+
+ /* This is highly system specific. */
+ if (freopen(syslog_file, "r", stdin) == NULL) {
+ fprintf(stderr, "freopen(%s, \"r\", stdin) failed\n",
+ syslog_file);
+ goto cleanup;
+ }
+ fprintf(stderr, "\n==> %s <==\n", syslog_file);
+ if (system("tail -2") != 0) {
+ fprintf(stderr, "system(\"tail -2\") failed\n");
+ goto cleanup;
+ }
+ fputc('\n', stderr);
+
+ cleanup:
+ isc_log_destroy(&lctx);
+
+ if (show_final_mem)
+ isc_mem_stats(mctx, stderr);
+
+ return (0);
+}
diff --git a/bin/tests/optional/lwres_test.c b/bin/tests/optional/lwres_test.c
new file mode 100644
index 0000000..44e1cb0
--- /dev/null
+++ b/bin/tests/optional/lwres_test.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+
+#define USE_ISC_MEM
+
+static inline void
+CHECK(int val, const char *msg) {
+ if (val != 0) {
+ fprintf(stderr, "%s returned %d\n", msg, val);
+ exit(1);
+ }
+}
+
+static void
+hexdump(const char *msg, void *base, size_t len) {
+ unsigned char *p;
+ unsigned int cnt;
+
+ p = base;
+ cnt = 0;
+
+ printf("*** %s (%lu bytes @ %p)\n", msg, (unsigned long)len, base);
+
+ while (cnt < len) {
+ if (cnt % 16 == 0)
+ printf("%p: ", p);
+ else if (cnt % 8 == 0)
+ printf(" |");
+ printf(" %02x", *p++);
+ cnt++;
+
+ if (cnt % 16 == 0)
+ printf("\n");
+ }
+
+ if (cnt % 16 != 0)
+ printf("\n");
+}
+
+static const char *TESTSTRING = "This is a test. This is only a test. !!!";
+static lwres_context_t *ctx;
+
+static void
+test_noop(void) {
+ int ret;
+ lwres_lwpacket_t pkt, pkt2;
+ lwres_nooprequest_t nooprequest, *nooprequest2;
+ lwres_noopresponse_t noopresponse, *noopresponse2;
+ lwres_buffer_t b;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0;
+
+ nooprequest.datalength = strlen(TESTSTRING);
+ /* XXXDCL maybe "nooprequest.data" should be const. */
+ DE_CONST(TESTSTRING, nooprequest.data);
+ ret = lwres_nooprequest_render(ctx, &nooprequest, &pkt, &b);
+ CHECK(ret, "lwres_nooprequest_render");
+
+ hexdump("rendered noop request", b.base, b.used);
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ hexdump("parsed pkt2", &pkt2, sizeof(pkt2));
+
+ nooprequest2 = NULL;
+ ret = lwres_nooprequest_parse(ctx, &b, &pkt2, &nooprequest2);
+ CHECK(ret, "lwres_nooprequest_parse");
+
+ assert(nooprequest.datalength == nooprequest2->datalength);
+ assert(memcmp(nooprequest.data, nooprequest2->data,
+ nooprequest.datalength) == 0);
+
+ lwres_nooprequest_free(ctx, &nooprequest2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0xdeadbeef;
+
+ noopresponse.datalength = strlen(TESTSTRING);
+ /* XXXDCL maybe "noopresponse.data" should be const. */
+ DE_CONST(TESTSTRING, noopresponse.data);
+ ret = lwres_noopresponse_render(ctx, &noopresponse, &pkt, &b);
+ CHECK(ret, "lwres_noopresponse_render");
+
+ hexdump("rendered noop response", b.base, b.used);
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ hexdump("parsed pkt2", &pkt2, sizeof(pkt2));
+
+ noopresponse2 = NULL;
+ ret = lwres_noopresponse_parse(ctx, &b, &pkt2, &noopresponse2);
+ CHECK(ret, "lwres_noopresponse_parse");
+
+ assert(noopresponse.datalength == noopresponse2->datalength);
+ assert(memcmp(noopresponse.data, noopresponse2->data,
+ noopresponse.datalength) == 0);
+
+ lwres_noopresponse_free(ctx, &noopresponse2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+}
+
+static void
+test_gabn(const char *target) {
+ lwres_gabnresponse_t *res;
+ lwres_addr_t *addr;
+ int ret;
+ unsigned int i;
+ char outbuf[64];
+
+ res = NULL;
+ ret = lwres_getaddrsbyname(ctx, target,
+ LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6,
+ &res);
+ printf("gabn %s ret == %d\n", target, ret);
+ if (ret != 0) {
+ printf("FAILURE!\n");
+ if (res != NULL)
+ lwres_gabnresponse_free(ctx, &res);
+ return;
+ }
+
+ printf("Returned real name: (%u, %s)\n",
+ res->realnamelen, res->realname);
+ printf("%u aliases:\n", res->naliases);
+ for (i = 0; i < res->naliases; i++)
+ printf("\t(%u, %s)\n", res->aliaslen[i], res->aliases[i]);
+ printf("%u addresses:\n", res->naddrs);
+ addr = LWRES_LIST_HEAD(res->addrs);
+ for (i = 0; i < res->naddrs; i++) {
+ INSIST(addr != NULL);
+
+ if (addr->family == LWRES_ADDRTYPE_V4)
+ (void)inet_ntop(AF_INET, addr->address,
+ outbuf, sizeof(outbuf));
+ else
+ (void)inet_ntop(AF_INET6, addr->address,
+ outbuf, sizeof(outbuf));
+ printf("\tAddr len %u family %08x %s\n",
+ addr->length, addr->family, outbuf);
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+
+ lwres_gabnresponse_free(ctx, &res);
+}
+
+static void
+test_gnba(const char *target, uint32_t af) {
+ lwres_gnbaresponse_t *res;
+ int ret;
+ unsigned int i;
+ unsigned char addrbuf[16];
+ unsigned int len;
+
+ if (af == LWRES_ADDRTYPE_V4) {
+ len = 4;
+ ret = inet_pton(AF_INET, target, addrbuf);
+ assert(ret == 1);
+ } else {
+ len = 16;
+ ret = inet_pton(AF_INET6, target, addrbuf);
+ assert(ret == 1);
+ }
+
+ res = NULL;
+ ret = lwres_getnamebyaddr(ctx, af, len, addrbuf, &res);
+ printf("gnba %s ret == %d\n", target, ret);
+ assert(ret == 0);
+ assert(res != NULL);
+
+ printf("Returned real name: (%u, %s)\n",
+ res->realnamelen, res->realname);
+ printf("%u aliases:\n", res->naliases);
+ for (i = 0; i < res->naliases; i++)
+ printf("\t(%u, %s)\n", res->aliaslen[i], res->aliases[i]);
+
+ lwres_gnbaresponse_free(ctx, &res);
+}
+
+#ifdef USE_ISC_MEM
+/*
+ * Wrappers around our memory management stuff, for the lwres functions.
+ */
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ int ret;
+#ifdef USE_ISC_MEM
+ isc_mem_t *mem;
+ isc_result_t result;
+#endif
+
+ (void)argc;
+ (void)argv;
+
+#ifdef USE_ISC_MEM
+ mem = NULL;
+ result = isc_mem_create(0, 0, &mem);
+ INSIST(result == ISC_R_SUCCESS);
+#endif
+
+ ctx = NULL;
+#ifdef USE_ISC_MEM
+ ret = lwres_context_create(&ctx, mem, mem_alloc, mem_free, 0);
+#else
+ ret = lwres_context_create(&ctx, NULL, NULL, NULL, 0);
+#endif
+
+ CHECK(ret, "lwres_context_create");
+
+ ret = lwres_conf_parse(ctx, "/etc/resolv.conf");
+ CHECK(ret, "lwres_conf_parse");
+
+ lwres_conf_print(ctx, stdout);
+
+ test_noop();
+
+ /*
+ * The following comments about tests all assume your search path is
+ * nominum.com isc.org flame.org
+ * and ndots is the default of 1.
+ */
+ test_gabn("alias-05.test"); /* exact, then search. */
+ test_gabn("f.root-servers.net.");
+ test_gabn("poofball.flame.org.");
+ test_gabn("foo.ip6.int.");
+ test_gabn("notthereatall.flame.org"); /* exact, then search (!found)*/
+ test_gabn("shell"); /* search (found in nominum.com), then exact */
+ test_gabn("kechara"); /* search (found in flame.org), then exact */
+ test_gabn("lkasdjlaksjdlkasjdlkasjdlkasjd"); /* search, exact(!found)*/
+
+ test_gnba("198.133.199.1", LWRES_ADDRTYPE_V4);
+ test_gnba("204.152.184.79", LWRES_ADDRTYPE_V4);
+ test_gnba("3ffe:8050:201:1860:42::1", LWRES_ADDRTYPE_V6);
+
+ lwres_conf_clear(ctx);
+ lwres_context_destroy(&ctx);
+
+#ifdef USE_ISC_MEM
+ isc_mem_stats(mem, stdout);
+ isc_mem_destroy(&mem);
+#endif
+
+ return (0);
+}
diff --git a/bin/tests/optional/lwresconf_test.c b/bin/tests/optional/lwresconf_test.c
new file mode 100644
index 0000000..a72b08a
--- /dev/null
+++ b/bin/tests/optional/lwresconf_test.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+
+#define USE_ISC_MEM
+
+static inline void
+CHECK(int val, const char *msg) {
+ if (val != 0) {
+ fprintf(stderr, "%s returned %d\n", msg, val);
+ exit(1);
+ }
+}
+
+#ifdef USE_ISC_MEM
+/*
+ * Wrappers around our memory management stuff, for the lwres functions.
+ */
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ lwres_context_t *ctx;
+ const char *file = "/etc/resolv.conf";
+ int ret;
+#ifdef USE_ISC_MEM
+ isc_mem_t *mem;
+ isc_result_t result;
+#endif
+
+ if (argc > 1) {
+ file = argv[1];
+ }
+
+#ifdef USE_ISC_MEM
+ mem = NULL;
+ result = isc_mem_create(0, 0, &mem);
+ INSIST(result == ISC_R_SUCCESS);
+#endif
+
+ ctx = NULL;
+#ifdef USE_ISC_MEM
+ ret = lwres_context_create(&ctx, mem, mem_alloc, mem_free, 0);
+#else
+ ret = lwres_context_create(&ctx, NULL, NULL, NULL, 0);
+#endif
+ CHECK(ret, "lwres_context_create");
+
+ lwres_conf_init(ctx);
+ if (lwres_conf_parse(ctx, file) == 0) {
+ lwres_conf_print(ctx, stderr);
+ } else {
+ perror("lwres_conf_parse");
+ }
+
+ lwres_conf_clear(ctx);
+ lwres_context_destroy(&ctx);
+
+#ifdef USE_ISC_MEM
+ isc_mem_stats(mem, stdout);
+ isc_mem_destroy(&mem);
+#endif
+
+ return (0);
+}
diff --git a/bin/tests/optional/master_test.c b/bin/tests/optional/master_test.c
new file mode 100644
index 0000000..9c1a059
--- /dev/null
+++ b/bin/tests/optional/master_test.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+
+isc_mem_t *mctx;
+
+static isc_result_t
+print_dataset(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) {
+ char buf[64*1024];
+ isc_buffer_t target;
+ isc_result_t result;
+
+ UNUSED(arg);
+
+ isc_buffer_init(&target, buf, 64*1024);
+ result = dns_rdataset_totext(dataset, owner, false, false,
+ &target);
+ if (result == ISC_R_SUCCESS)
+ fprintf(stdout, "%.*s\n", (int)target.used,
+ (char*)target.base);
+ else
+ fprintf(stdout, "dns_rdataset_totext: %s\n",
+ dns_result_totext(result));
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ dns_name_t origin;
+ isc_buffer_t source;
+ isc_buffer_t target;
+ unsigned char name_buf[255];
+ dns_rdatacallbacks_t callbacks;
+
+ UNUSED(argc);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ if (argv[1]) {
+ isc_buffer_init(&source, argv[1], strlen(argv[1]));
+ isc_buffer_add(&source, strlen(argv[1]));
+ isc_buffer_setactive(&source, strlen(argv[1]));
+ isc_buffer_init(&target, name_buf, 255);
+ dns_name_init(&origin, NULL);
+ result = dns_name_fromtext(&origin, &source, dns_rootname,
+ 0, &target);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "dns_name_fromtext: %s\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+
+ dns_rdatacallbacks_init_stdio(&callbacks);
+ callbacks.add = print_dataset;
+
+ result = dns_master_loadfile(argv[1], &origin, &origin,
+ dns_rdataclass_in, 0,
+ &callbacks, mctx);
+ fprintf(stdout, "dns_master_loadfile: %s\n",
+ dns_result_totext(result));
+ }
+ return (0);
+}
diff --git a/bin/tests/optional/mempool_test.c b/bin/tests/optional/mempool_test.c
new file mode 100644
index 0000000..6a878f4
--- /dev/null
+++ b/bin/tests/optional/mempool_test.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+
+int
+main(int argc, char *argv[]) {
+ void *items1[50];
+ void *items2[50];
+ void *tmp;
+ isc_mempool_t *mp1, *mp2;
+ unsigned int i, j;
+ isc_mutex_t lock;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ mp1 = NULL;
+ RUNTIME_CHECK(isc_mempool_create(mctx, 24, &mp1) == ISC_R_SUCCESS);
+
+ mp2 = NULL;
+ RUNTIME_CHECK(isc_mempool_create(mctx, 31, &mp2) == ISC_R_SUCCESS);
+
+ isc_mempool_associatelock(mp1, &lock);
+ isc_mempool_associatelock(mp2, &lock);
+
+ isc_mem_stats(mctx, stderr);
+
+ isc_mempool_setfreemax(mp1, 10);
+ isc_mempool_setfillcount(mp1, 10);
+ isc_mempool_setmaxalloc(mp1, 30);
+
+ /*
+ * Allocate 30 items from the pool. This is our max.
+ */
+ for (i = 0; i < 30; i++) {
+ items1[i] = isc_mempool_get(mp1);
+ RUNTIME_CHECK(items1[i] != NULL);
+ }
+
+ /*
+ * Try to allocate one more. This should fail.
+ */
+ tmp = isc_mempool_get(mp1);
+ RUNTIME_CHECK(tmp == NULL);
+
+ /*
+ * Free the first 11 items. Verify that there are 10 free items on
+ * the free list (which is our max).
+ */
+
+ for (i = 0; i < 11; i++) {
+ isc_mempool_put(mp1, items1[i]);
+ items1[i] = NULL;
+ }
+
+ RUNTIME_CHECK(isc_mempool_getfreecount(mp1) == 10);
+ RUNTIME_CHECK(isc_mempool_getallocated(mp1) == 19);
+
+ isc_mem_stats(mctx, stderr);
+
+ /*
+ * Now, beat up on mp2 for a while. Allocate 50 items, then free
+ * them, then allocate 50 more, etc.
+ */
+ isc_mempool_setfreemax(mp2, 25);
+ isc_mempool_setfillcount(mp2, 25);
+ for (j = 0; j < 5000; j++) {
+ for (i = 0; i < 50; i++) {
+ items2[i] = isc_mempool_get(mp2);
+ RUNTIME_CHECK(items2[i] != NULL);
+ }
+ for (i = 0; i < 50; i++) {
+ isc_mempool_put(mp2, items2[i]);
+ items2[i] = NULL;
+ }
+ }
+
+ /*
+ * Free all the other items and blow away this pool.
+ */
+ for (i = 11; i < 30; i++) {
+ isc_mempool_put(mp1, items1[i]);
+ items1[i] = NULL;
+ }
+
+ isc_mempool_destroy(&mp1);
+
+ isc_mem_stats(mctx, stderr);
+
+ isc_mempool_destroy(&mp2);
+
+ isc_mem_stats(mctx, stderr);
+
+ isc_mem_destroy(&mctx);
+
+ DESTROYLOCK(&lock);
+
+ return (0);
+}
diff --git a/bin/tests/optional/name_test.c b/bin/tests/optional/name_test.c
new file mode 100644
index 0000000..4ab0dfc
--- /dev/null
+++ b/bin/tests/optional/name_test.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/result.h>
+
+static void
+print_wirename(isc_region_t *name) {
+ unsigned char *ccurr, *cend;
+
+ if (name->length == 0) {
+ printf("<empty wire name>\n");
+ return;
+ }
+ ccurr = name->base;
+ cend = ccurr + name->length;
+ while (ccurr != cend)
+ printf("%02x ", *ccurr++);
+ printf("\n");
+}
+
+static void
+print_name(dns_name_t *name) {
+ isc_result_t result;
+ isc_buffer_t source;
+ isc_region_t r;
+ char s[1000];
+
+ isc_buffer_init(&source, s, sizeof(s));
+ if (dns_name_countlabels(name) > 0)
+ result = dns_name_totext(name, false, &source);
+ else
+ result = ISC_R_SUCCESS;
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(&source, &r);
+ if (r.length > 0)
+ printf("%.*s\n", (int)r.length, r.base);
+ else
+ printf("<empty text name>\n");
+ } else
+ printf("error: %s\n", dns_result_totext(result));
+}
+
+int
+main(int argc, char *argv[]) {
+ char s[1000];
+ isc_result_t result;
+ dns_fixedname_t wname, wname2, oname, compname, downname;
+ isc_buffer_t source;
+ isc_region_t r;
+ dns_name_t *name, *origin, *comp, *down;
+ unsigned int downcase = 0;
+ size_t len;
+ bool quiet = false;
+ bool concatenate = false;
+ bool got_name = false;
+ bool check_absolute = false;
+ bool check_wildcard = false;
+ bool test_downcase = false;
+ bool inplace = false;
+ bool want_split = false;
+ unsigned int labels, split_label = 0;
+ dns_fixedname_t fprefix, fsuffix;
+ dns_name_t *prefix, *suffix;
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, "acdiqs:w")) != -1) {
+ switch (ch) {
+ case 'a':
+ check_absolute = true;
+ break;
+ case 'c':
+ concatenate = true;
+ break;
+ case 'd':
+ test_downcase = true;
+ break;
+ case 'i':
+ inplace = true;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 's':
+ want_split = true;
+ split_label = atoi(isc_commandline_argument);
+ break;
+ case 'w':
+ check_wildcard = true;
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 0) {
+ if (strcasecmp("none", argv[0]) == 0)
+ origin = NULL;
+ else {
+ len = strlen(argv[0]);
+ isc_buffer_init(&source, argv[0], len);
+ isc_buffer_add(&source, len);
+ origin = dns_fixedname_initname(&oname);
+ result = dns_name_fromtext(origin, &source,
+ dns_rootname, 0, NULL);
+ if (result != 0) {
+ fprintf(stderr,
+ "dns_name_fromtext() failed: %s\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+ }
+ } else if (concatenate)
+ origin = NULL;
+ else
+ origin = dns_rootname;
+
+ if (argc >= 1) {
+ if (strcasecmp("none", argv[1]) == 0)
+ comp = NULL;
+ else {
+ len = strlen(argv[1]);
+ isc_buffer_init(&source, argv[1], len);
+ isc_buffer_add(&source, len);
+ comp = dns_fixedname_initname(&compname);
+ result = dns_name_fromtext(comp, &source, origin,
+ 0, NULL);
+ if (result != 0) {
+ fprintf(stderr,
+ "dns_name_fromtext() failed: %s\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+ }
+ } else
+ comp = NULL;
+
+ name = dns_fixedname_initname(&wname);
+ dns_fixedname_init(&wname2);
+ while (fgets(s, sizeof(s), stdin) != NULL) {
+ len = strlen(s);
+ if (len > 0U && s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ len--;
+ }
+ isc_buffer_init(&source, s, len);
+ isc_buffer_add(&source, len);
+
+ if (len > 0U)
+ result = dns_name_fromtext(name, &source, origin,
+ downcase, NULL);
+ else {
+ if (name == dns_fixedname_name(&wname))
+ dns_fixedname_init(&wname);
+ else
+ dns_fixedname_init(&wname2);
+ result = ISC_R_SUCCESS;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("%s\n", dns_result_totext(result));
+ if (name == dns_fixedname_name(&wname))
+ dns_fixedname_init(&wname);
+ else
+ dns_fixedname_init(&wname2);
+ continue;
+ }
+
+ if (check_absolute && dns_name_countlabels(name) > 0) {
+ if (dns_name_isabsolute(name))
+ printf("absolute\n");
+ else
+ printf("relative\n");
+ }
+ if (check_wildcard && dns_name_countlabels(name) > 0) {
+ if (dns_name_iswildcard(name))
+ printf("wildcard\n");
+ else
+ printf("not wildcard\n");
+ }
+ dns_name_toregion(name, &r);
+ if (!quiet) {
+ print_wirename(&r);
+ printf("%u labels, %u bytes.\n",
+ dns_name_countlabels(name), r.length);
+ }
+
+ if (concatenate) {
+ if (got_name) {
+ printf("Concatenating.\n");
+ result = dns_name_concatenate(
+ dns_fixedname_name(&wname),
+ dns_fixedname_name(&wname2),
+ dns_fixedname_name(&wname2),
+ NULL);
+ name = dns_fixedname_name(&wname2);
+ if (result == ISC_R_SUCCESS) {
+ if (check_absolute &&
+ dns_name_countlabels(name) > 0) {
+ if (dns_name_isabsolute(name))
+ printf("absolute\n");
+ else
+ printf("relative\n");
+ }
+ if (check_wildcard &&
+ dns_name_countlabels(name) > 0) {
+ if (dns_name_iswildcard(name))
+ printf("wildcard\n");
+ else
+ printf("not "
+ "wildcard\n");
+ }
+ dns_name_toregion(name, &r);
+ if (!quiet) {
+ print_wirename(&r);
+ printf("%u labels, "
+ "%u bytes.\n",
+ dns_name_countlabels(name),
+ r.length);
+ }
+ } else
+ printf("%s\n",
+ dns_result_totext(result));
+ got_name = false;
+ } else
+ got_name = true;
+ }
+ isc_buffer_init(&source, s, sizeof(s));
+ if (dns_name_countlabels(name) > 0)
+ result = dns_name_totext(name, false, &source);
+ else
+ result = ISC_R_SUCCESS;
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(&source, &r);
+ if (r.length > 0)
+ printf("%.*s\n", (int)r.length, r.base);
+ else
+ printf("<empty text name>\n");
+ if (!quiet) {
+ printf("%u bytes.\n", source.used);
+ }
+ } else
+ printf("%s\n", dns_result_totext(result));
+
+ if (test_downcase) {
+ if (inplace) {
+ down = name;
+ } else {
+ down = dns_fixedname_initname(&downname);
+ }
+ result = dns_name_downcase(name, down, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ if (!quiet) {
+ dns_name_toregion(down, &r);
+ print_wirename(&r);
+ printf("%u labels, %u bytes.\n",
+ dns_name_countlabels(down),
+ r.length);
+ }
+ isc_buffer_init(&source, s, sizeof(s));
+ print_name(down);
+ }
+
+ if (comp != NULL && dns_name_countlabels(name) > 0) {
+ int order;
+ unsigned int nlabels;
+ dns_namereln_t namereln;
+
+ namereln = dns_name_fullcompare(name, comp, &order,
+ &nlabels);
+ if (!quiet) {
+ if (order < 0)
+ printf("<");
+ else if (order > 0)
+ printf(">");
+ else
+ printf("=");
+ switch (namereln) {
+ case dns_namereln_contains:
+ printf(", contains");
+ break;
+ case dns_namereln_subdomain:
+ printf(", subdomain");
+ break;
+ case dns_namereln_commonancestor:
+ printf(", common ancestor");
+ break;
+ default:
+ break;
+ }
+ if (namereln != dns_namereln_none &&
+ namereln != dns_namereln_equal)
+ printf(", nlabels = %u", nlabels);
+ printf("\n");
+ }
+ printf("dns_name_equal() returns %s\n",
+ dns_name_equal(name, comp) ? "TRUE" : "FALSE");
+ }
+
+ labels = dns_name_countlabels(name);
+ if (want_split && split_label < labels) {
+ prefix = dns_fixedname_initname(&fprefix);
+ suffix = dns_fixedname_initname(&fsuffix);
+ printf("splitting at label %u: ", split_label);
+ dns_name_split(name, split_label, prefix, suffix);
+ printf("\n prefix = ");
+ print_name(prefix);
+ printf(" suffix = ");
+ print_name(suffix);
+ }
+
+ if (concatenate) {
+ if (got_name)
+ name = dns_fixedname_name(&wname2);
+ else
+ name = dns_fixedname_name(&wname);
+ }
+ }
+
+ return (0);
+}
diff --git a/bin/tests/optional/nsecify.c b/bin/tests/optional/nsecify.c
new file mode 100644
index 0000000..ac3a306
--- /dev/null
+++ b/bin/tests/optional/nsecify.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/nsec.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+
+static isc_mem_t *mctx = NULL;
+
+static inline void
+fatal(const char *message) {
+ fprintf(stderr, "%s\n", message);
+ exit(1);
+}
+
+static inline void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s: %s\n", message,
+ isc_result_totext(result));
+ exit(1);
+ }
+}
+
+static inline bool
+active_node(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter;
+ bool active = false;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 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)
+ 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");
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ if (!active) {
+ /*
+ * Make sure there is no NSEC record for this node.
+ */
+ result = dns_db_deleterdataset(db, node, version,
+ dns_rdatatype_nsec, 0);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_deleterdataset");
+ }
+
+ return (active);
+}
+
+static inline isc_result_t
+next_active(dns_db_t *db, dns_dbversion_t *version, dns_dbiterator_t *dbiter,
+ dns_name_t *name, dns_dbnode_t **nodep)
+{
+ isc_result_t result;
+ bool active;
+
+ do {
+ active = false;
+ result = dns_dbiterator_current(dbiter, nodep, name);
+ if (result == ISC_R_SUCCESS) {
+ active = active_node(db, version, *nodep);
+ if (!active) {
+ dns_db_detachnode(db, nodep);
+ result = dns_dbiterator_next(dbiter);
+ }
+ }
+ } while (result == ISC_R_SUCCESS && !active);
+
+ return (result);
+}
+
+static void
+nsecify(char *filename) {
+ isc_result_t result;
+ dns_db_t *db;
+ dns_dbversion_t *wversion;
+ dns_dbnode_t *node, *nextnode;
+ const char *origintext;
+ dns_fixedname_t fname, fnextname;
+ dns_name_t *name, *nextname, *target;
+ isc_buffer_t b;
+ size_t len;
+ dns_dbiterator_t *dbiter;
+ char newfilename[1024];
+
+ name = dns_fixedname_initname(&fname);
+ nextname = dns_fixedname_initname(&fnextname);
+
+ origintext = strrchr(filename, '/');
+ if (origintext == NULL)
+ origintext = filename;
+ else
+ origintext++; /* Skip '/'. */
+ len = strlen(origintext);
+ isc_buffer_constinit(&b, origintext, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ check_result(result, "dns_name_fromtext()");
+
+ db = NULL;
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, &db);
+ check_result(result, "dns_db_create()");
+ result = dns_db_load(db, filename);
+ if (result == DNS_R_SEENINCLUDE)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_load()");
+ wversion = NULL;
+ result = dns_db_newversion(db, &wversion);
+ check_result(result, "dns_db_newversion()");
+ dbiter = NULL;
+ result = dns_db_createiterator(db, 0, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+ node = NULL;
+ result = next_active(db, wversion, dbiter, name, &node);
+ while (result == ISC_R_SUCCESS) {
+ nextnode = NULL;
+ result = dns_dbiterator_next(dbiter);
+ if (result == ISC_R_SUCCESS)
+ result = next_active(db, wversion, dbiter, nextname,
+ &nextnode);
+ if (result == ISC_R_SUCCESS)
+ target = nextname;
+ else if (result == ISC_R_NOMORE)
+ target = dns_db_origin(db);
+ else {
+ target = NULL; /* Make compiler happy. */
+ fatal("db iteration failed");
+ }
+ dns_nsec_build(db, wversion, node, target, 3600); /* XXX BEW */
+ dns_db_detachnode(db, &node);
+ node = nextnode;
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("db iteration failed");
+ dns_dbiterator_destroy(&dbiter);
+ /*
+ * XXXRTH For now, we don't increment the SOA serial.
+ */
+ dns_db_closeversion(db, &wversion, true);
+ len = strlen(filename);
+ if (len + 4 + 1 > sizeof(newfilename))
+ fatal("filename too long");
+ snprintf(newfilename, sizeof(newfilename), "%s.new", filename);
+ result = dns_db_dump(db, NULL, newfilename);
+ check_result(result, "dns_db_dump");
+ dns_db_detach(&db);
+}
+
+int
+main(int argc, char *argv[]) {
+ int i;
+ isc_result_t result;
+
+ dns_result_register();
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create()");
+
+ argc--;
+ argv++;
+
+ for (i = 0; i < argc; i++)
+ nsecify(argv[i]);
+
+ /* isc_mem_stats(mctx, stdout); */
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/ratelimiter_test.c b/bin/tests/optional/ratelimiter_test.c
new file mode 100644
index 0000000..02eadac
--- /dev/null
+++ b/bin/tests/optional/ratelimiter_test.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <isc/app.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/ratelimiter.h>
+#include <isc/util.h>
+
+isc_ratelimiter_t *rlim = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_task_t *g_task = NULL;
+isc_mem_t *mctx = NULL;
+
+static void utick(isc_task_t *task, isc_event_t *event);
+static void shutdown_rl(isc_task_t *task, isc_event_t *event);
+static void shutdown_all(isc_task_t *task, isc_event_t *event);
+
+typedef struct {
+ int milliseconds;
+ void (*fun)(isc_task_t *, isc_event_t *);
+} schedule_t;
+
+schedule_t schedule[] = {
+ { 100, utick },
+ { 200, utick },
+ { 300, utick },
+ { 3000, utick },
+ { 3100, utick },
+ { 3200, utick },
+ { 3300, shutdown_rl },
+ { 5000, utick },
+ { 6000, shutdown_all }
+};
+
+#define NEVENTS (int)(sizeof(schedule)/sizeof(schedule[0]))
+
+isc_timer_t *timers[NEVENTS];
+
+static void
+ltick(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ printf("** ltick%s **\n",
+ (event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ?
+ " (canceled)" : "");
+ isc_event_free(&event);
+}
+
+static void
+utick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ UNUSED(task);
+ event->ev_action = ltick;
+ event->ev_sender = NULL;
+ result = isc_ratelimiter_enqueue(rlim, g_task, &event);
+ printf("enqueue: %s\n",
+ result == ISC_R_SUCCESS ? "ok" : "failed");
+}
+
+static void
+shutdown_rl(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ UNUSED(event);
+ printf("shutdown ratelimiter\n");
+ isc_ratelimiter_shutdown(rlim);
+}
+
+static void
+shutdown_all(isc_task_t *task, isc_event_t *event) {
+ int i;
+ UNUSED(task);
+ UNUSED(event);
+ printf("shutdown all\n");
+ for (i = 0; i < NEVENTS; i++) {
+ isc_timer_detach(&timers[i]);
+ }
+
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_interval_t linterval;
+ int i;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ isc_app_start();
+ isc_interval_set(&linterval, 1, 0);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, 3, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &g_task) ==
+ ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_ratelimiter_create(mctx, timermgr, g_task,
+ &rlim) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_ratelimiter_setinterval(rlim, &linterval) ==
+ ISC_R_SUCCESS);
+
+ for (i = 0; i < NEVENTS; i++) {
+ isc_interval_t uinterval;
+ int ms = schedule[i].milliseconds;
+ isc_interval_set(&uinterval, ms / 1000,
+ (ms % 1000) * 1000000);
+ timers[i] = NULL;
+ RUNTIME_CHECK(isc_timer_create(timermgr,
+ isc_timertype_once, NULL,
+ &uinterval,
+ g_task, schedule[i].fun, NULL,
+ &timers[i]) == ISC_R_SUCCESS);
+ }
+
+ isc_app_run();
+
+ isc_task_destroy(&g_task);
+
+ isc_ratelimiter_detach(&rlim);
+
+ isc_timermgr_destroy(&timermgr);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_mem_stats(mctx, stdout);
+
+ isc_app_finish();
+ return (0);
+}
diff --git a/bin/tests/optional/rbt_test.c b/bin/tests/optional/rbt_test.c
new file mode 100644
index 0000000..0d41dc2
--- /dev/null
+++ b/bin/tests/optional/rbt_test.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/rbt.h>
+#include <dns/fixedname.h>
+#include <dns/result.h>
+
+const char *progname;
+isc_mem_t *mctx;
+
+#define DNSNAMELEN 255
+
+static dns_name_t *
+create_name(char *s) {
+ int length;
+ isc_result_t result;
+ isc_buffer_t source, target;
+ static dns_name_t *name;
+
+ if (s == NULL || *s == '\0') {
+ printf("missing name argument\n");
+ return (NULL);
+ }
+
+ length = strlen(s);
+
+ isc_buffer_init(&source, s, length);
+ isc_buffer_add(&source, length);
+
+ /*
+ * It isn't really necessary in this program to create individual
+ * memory spaces for each name structure and its associated character
+ * string. It is done here to provide a relatively easy way to test
+ * the callback from dns_rbt_deletename that is supposed to free the
+ * data associated with a node.
+ *
+ * The buffer for the actual name will immediately follow the
+ * name structure.
+ */
+ name = isc_mem_get(mctx, sizeof(*name) + DNSNAMELEN);
+ if (name == NULL) {
+ printf("out of memory!\n");
+ return (NULL);
+ }
+
+ dns_name_init(name, NULL);
+ isc_buffer_init(&target, name + 1, DNSNAMELEN);
+
+ result = dns_name_fromtext(name, &source, dns_rootname, 0, &target);
+
+ if (result != ISC_R_SUCCESS) {
+ printf("dns_name_fromtext(%s) failed: %s\n",
+ s, dns_result_totext(result));
+ return (NULL);
+ }
+
+ return (name);
+}
+
+static void
+delete_name(void *data, void *arg) {
+ dns_name_t *name;
+
+ UNUSED(arg);
+ name = data;
+ isc_mem_put(mctx, name, sizeof(*name) + DNSNAMELEN);
+}
+
+static void
+print_name(dns_name_t *name) {
+ isc_buffer_t target;
+ char buffer[1024];
+
+ isc_buffer_init(&target, buffer, sizeof(buffer));
+
+ /*
+ * false means absolute names have the final dot added.
+ */
+ dns_name_totext(name, false, &target);
+
+ printf("%.*s", (int)target.used, (char *)target.base);
+}
+
+static void
+detail(dns_rbt_t *rbt, dns_name_t *name) {
+ dns_name_t *foundname, *origin, *fullname;
+ dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
+ dns_rbtnode_t *node1, *node2;
+ dns_rbtnodechain_t chain;
+ isc_result_t result;
+ bool nodes_should_match = false;
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ origin = dns_fixedname_initname(&fixedorigin);
+ fullname = dns_fixedname_initname(&fixedfullname);
+ foundname = dns_fixedname_initname(&fixedfoundname);
+
+ node1 = node2 = NULL;
+
+ printf("checking chain information for ");
+ print_name(name);
+ printf("\n");
+
+ result = dns_rbt_findnode(rbt, name, foundname, &node1, &chain,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ printf(" found exact.");
+ nodes_should_match = true;
+ break;
+ case DNS_R_PARTIALMATCH:
+ printf(" found parent.");
+ break;
+ case ISC_R_NOTFOUND:
+ printf(" name not found.");
+ break;
+ default:
+ printf(" unexpected result: %s\n", dns_result_totext(result));
+ return;
+ }
+
+ if (node1 != NULL && node1->data != NULL) {
+ printf(" data at node: ");
+ print_name(node1->data);
+ } else
+ printf(" no data at node.");
+
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ printf("\n name from dns_rbt_findnode: ");
+ print_name(foundname);
+ }
+
+ result = dns_rbtnodechain_current(&chain, foundname, origin, &node2);
+
+ if (result == ISC_R_SUCCESS) {
+ printf("\n name from dns_rbtnodechain_current: ");
+
+ result = dns_name_concatenate(foundname, origin,
+ fullname, NULL);
+ if (result == ISC_R_SUCCESS)
+ print_name(fullname);
+ else
+ printf("%s\n", dns_result_totext(result));
+ printf("\n (foundname = ");
+ print_name(foundname);
+ printf(", origin = ");
+ print_name(origin);
+ printf(")\n");
+ if (nodes_should_match && node1 != node2)
+ printf(" nodes returned from each function "
+ "DO NOT match!\n");
+
+ } else
+ printf("\n result from dns_rbtnodechain_current: %s\n",
+ dns_result_totext(result));
+
+ printf(" level_matches = %u, level_count = %u\n",
+ chain.level_matches, chain.level_count);
+}
+
+static void
+iterate(dns_rbt_t *rbt, bool forward) {
+ dns_name_t foundname, *origin;
+ dns_rbtnodechain_t chain;
+ dns_fixedname_t fixedorigin;
+ isc_result_t result;
+ isc_result_t (*move)(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin);
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ dns_name_init(&foundname, NULL);
+ origin = dns_fixedname_initname(&fixedorigin);
+
+ if (forward) {
+ printf("iterating forward\n" );
+ move = dns_rbtnodechain_next;
+
+ result = dns_rbtnodechain_first(&chain, rbt, &foundname,
+ origin);
+
+ } else {
+ printf("iterating backward\n" );
+ move = dns_rbtnodechain_prev;
+
+ result = dns_rbtnodechain_last(&chain, rbt, &foundname,
+ origin);
+ }
+
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ printf("start not found!\n");
+
+ else {
+ for (;;) {
+ if (result == DNS_R_NEWORIGIN) {
+ printf(" new origin: ");
+ print_name(origin);
+ printf("\n");
+ }
+
+ if (result == ISC_R_SUCCESS ||
+ result == DNS_R_NEWORIGIN) {
+ print_name(&foundname);
+ printf("\n");
+
+ } else {
+ if (result != ISC_R_NOMORE)
+ printf("UNEXEPCTED ITERATION ERROR: %s",
+ dns_result_totext(result));
+ break;
+ }
+
+ result = move(&chain, &foundname, origin);
+ }
+ }
+}
+
+
+#define CMDCHECK(s) (strncasecmp(command, (s), length) == 0)
+#define PRINTERR(r) if (r != ISC_R_SUCCESS) \
+ printf("... %s\n", dns_result_totext(r));
+
+int
+main(int argc, char **argv) {
+ char *command, *arg, buffer[1024];
+ const char *whitespace;
+ dns_name_t *name, *foundname;
+ dns_fixedname_t fixedname;
+ dns_rbt_t *rbt = NULL;
+ int length, ch;
+ bool show_final_mem = false;
+ isc_result_t result;
+ void *data;
+
+ progname = strrchr(*argv, '/');
+ if (progname != NULL)
+ progname++;
+ else
+ progname = *argv;
+
+ while ((ch = isc_commandline_parse(argc, argv, "m")) != -1) {
+ switch (ch) {
+ case 'm':
+ show_final_mem = true;
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc > 1) {
+ printf("Usage: %s [-m]\n", progname);
+ exit(1);
+ }
+
+ setbuf(stdout, NULL);
+
+ /*
+ * So isc_mem_stats() can report any allocation leaks.
+ */
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("isc_mem_create: %s: exiting\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+
+ result = dns_rbt_create(mctx, delete_name, NULL, &rbt);
+ if (result != ISC_R_SUCCESS) {
+ printf("dns_rbt_create: %s: exiting\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+
+ whitespace = " \t";
+
+ while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
+ length = strlen(buffer);
+
+ if (buffer[length - 1] != '\n') {
+ printf("line to long (%lu max), ignored\n",
+ (unsigned long)sizeof(buffer) - 2);
+ continue;
+ }
+
+ buffer[length - 1] = '\0';
+
+ command = buffer + strspn(buffer, whitespace);
+
+ if (*command == '#')
+ continue;
+
+ arg = strpbrk(command, whitespace);
+ if (arg != NULL) {
+ *arg++ = '\0';
+ arg += strspn(arg, whitespace);
+ }
+
+ length = strlen(command);
+ if (*command != '\0') {
+ if (CMDCHECK("add")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("adding name %s\n", arg);
+ result = dns_rbt_addname(rbt,
+ name, name);
+ PRINTERR(result);
+ }
+
+ } else if (CMDCHECK("delete")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("deleting name %s\n", arg);
+ result = dns_rbt_deletename(rbt, name,
+ false);
+ PRINTERR(result);
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("nuke")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("nuking name %s "
+ "and its descendants\n", arg);
+ result = dns_rbt_deletename(rbt, name,
+ true);
+ PRINTERR(result);
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("search")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("searching for name %s ... ",
+ arg);
+
+ foundname =
+ dns_fixedname_initname(&fixedname);
+ data = NULL;
+
+ result = dns_rbt_findname(rbt, name, 0,
+ foundname,
+ &data);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ printf("found exact: ");
+ print_name(data);
+ putchar('\n');
+ break;
+ case DNS_R_PARTIALMATCH:
+ printf("found parent: ");
+ print_name(data);
+ printf("\n\t(foundname: ");
+ print_name(foundname);
+ printf(")\n");
+ break;
+ case ISC_R_NOTFOUND:
+ printf("NOT FOUND!\n");
+ break;
+ case ISC_R_NOMEMORY:
+ printf("OUT OF MEMORY!\n");
+ break;
+ default:
+ printf("UNEXPECTED RESULT\n");
+ }
+
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("check")) {
+ /*
+ * Or "chain". I know, I know. Lame name.
+ * I was having a hard time thinking of a
+ * name (especially one that did not have
+ * a conflicting first letter with another
+ * command) that would differentiate this
+ * from the search command.
+ *
+ * But it is just a test program, eh?
+ */
+ name = create_name(arg);
+ if (name != NULL) {
+ detail(rbt, name);
+
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("forward")) {
+ iterate(rbt, true);
+
+ } else if (CMDCHECK("backward")) {
+ iterate(rbt, false);
+
+ } else if (CMDCHECK("print")) {
+ if (arg == NULL || *arg == '\0')
+ dns_rbt_printtext(rbt, NULL, stdout);
+ else
+ printf("usage: print\n");
+
+ } else if (CMDCHECK("quit")) {
+ if (arg == NULL || *arg == '\0')
+ break;
+ else
+ printf("usage: quit\n");
+ } else {
+ printf("a(dd) NAME, d(elete) NAME, "
+ "s(earch) NAME, p(rint), or q(uit)\n");
+
+ }
+ }
+
+ }
+
+ dns_rbt_destroy(&rbt);
+
+ if (show_final_mem)
+ isc_mem_stats(mctx, stderr);
+
+ return (0);
+}
diff --git a/bin/tests/optional/rbt_test.out b/bin/tests/optional/rbt_test.out
new file mode 100644
index 0000000..95bf4f9
--- /dev/null
+++ b/bin/tests/optional/rbt_test.out
@@ -0,0 +1,395 @@
+adding name a.vix.com
+adding name b.vix.com
+adding name c.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name a.b.c.d.e.f.vix.com
+adding name b.b.c.d.e.f.vix.com
+adding name c.b.c.d.e.f.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ c (black from b)
+ NULL
+ b.c.d.e.f (RED from c)
+ ++ BEG down from b.c.d.e.f
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from b.c.d.e.f
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name a.d.e.f.vix.com
+adding name q.d.e.f.vix.com
+adding name d.e.f.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ c (black from b)
+ NULL
+ d.e.f (RED from c)
+ ++ BEG down from d.e.f
+ b.c (black)
+ ++ BEG down from b.c
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from b.c
+ a (RED from b.c)
+ NULL
+ NULL
+ q (RED from b.c)
+ NULL
+ NULL
+ -- END down from d.e.f
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name g.h.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ d.e.f (black from b)
+ ++ BEG down from d.e.f
+ b.c (black)
+ ++ BEG down from b.c
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from b.c
+ a (RED from b.c)
+ NULL
+ NULL
+ q (RED from b.c)
+ NULL
+ NULL
+ -- END down from d.e.f
+ c (RED from d.e.f)
+ NULL
+ NULL
+ g.h (RED from d.e.f)
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+searching for name q.d.e.f.vix.com ... found exact: q.d.e.f.vix.com.
+searching for name just-parent.a.vix.com ... found parent: a.vix.com.
+ (foundname: a.vix.com.)
+searching for name no-real-parent.vix.com ... NOT FOUND!
+searching for name does.not.exist.at.all ... NOT FOUND!
+iterating forward
+ new origin: .
+vix.com
+ new origin: vix.com.
+a
+b
+c
+d.e.f
+ new origin: d.e.f.vix.com.
+a
+b.c
+ new origin: b.c.d.e.f.vix.com.
+a
+b
+c
+ new origin: d.e.f.vix.com.
+q
+ new origin: vix.com.
+g.h
+iterating backward
+ new origin: vix.com.
+g.h
+ new origin: d.e.f.vix.com.
+q
+ new origin: b.c.d.e.f.vix.com.
+c
+b
+a
+ new origin: d.e.f.vix.com.
+b.c
+a
+ new origin: vix.com.
+d.e.f
+c
+b
+a
+ new origin: .
+vix.com
+checking chain information for vix.com.
+ found exact. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: vix.com.
+ (foundname = vix.com, origin = .)
+ level_matches = 0, level_count = 0
+checking chain information for zzz.com.
+ name not found. no data at node.
+ name from dns_rbtnodechain_current: g.h.vix.com.
+ (foundname = g.h, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for 0.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: vix.com.
+ (foundname = vix.com, origin = .)
+ level_matches = 0, level_count = 0
+checking chain information for d.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for f.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for a.e.f.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for z.e.f.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: q.d.e.f.vix.com.
+ (foundname = q, origin = d.e.f.vix.com.)
+ level_matches = 0, level_count = 2
+checking chain information for g.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: q.d.e.f.vix.com.
+ (foundname = q, origin = d.e.f.vix.com.)
+ level_matches = 0, level_count = 2
+checking chain information for i.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: g.h.vix.com.
+ (foundname = g.h, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for b.c.vix.com.
+ found parent. data at node: c.vix.com.
+ name from dns_rbt_findnode: c.vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 1, level_count = 1
+nuking name d.e.f.vix.com and its descendants
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ g.h (black from b)
+ c (RED from g.h)
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name x.a.vix.com
+adding name y.x.a.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ ++ BEG down from a
+ x (black)
+ ++ BEG down from x
+ y (black)
+ NULL
+ NULL
+ -- END down from x
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ g.h (black from b)
+ c (RED from g.h)
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name a.vix.com
+deleting name x.a.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ ++ BEG down from a
+ x (black)
+ ++ BEG down from x
+ y (black)
+ NULL
+ NULL
+ -- END down from x
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ g.h (black from b)
+ c (RED from g.h)
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name b.vix.com
+deleting name c.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ g.h (black)
+ a (RED from g.h)
+ ++ BEG down from a
+ x (black)
+ ++ BEG down from x
+ y (black)
+ NULL
+ NULL
+ -- END down from x
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name y.x.a.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ g.h (black)
+ a (RED from g.h)
+ ++ BEG down from a
+ x (black)
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name g.h.vix.com.
+adding name \[b100000].vix.com.
+adding name \[b010000].vix.com.
+adding name \[b001000].vix.com.
+adding name \[b000100].vix.com.
+adding name \[b000010].vix.com.
+adding name \[b000001].vix.com.
+vix.com. (black)
+ ++ BEG down from vix.com.
+ \[x80/6] (black)
+ \[x0/1] (RED from \[x80/6])
+ ++ BEG down from \[x0/1]
+ \[x80/5] (black)
+ \[x0/1] (RED from \[x80/5])
+ ++ BEG down from \[x0/1]
+ \[x8/4] (black)
+ \[x0/1] (RED from \[x8/4])
+ ++ BEG down from \[x0/1]
+ \[x8/3] (black)
+ \[x0/1] (RED from \[x8/3])
+ ++ BEG down from \[x0/1]
+ \[x8/2] (black)
+ \[x4/2] (RED from \[x8/2])
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ a (RED from \[x80/6])
+ ++ BEG down from a
+ x (black)
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+searching for name \[b000100].vix.com. ... found exact: \[x10/6].vix.com.
+adding name vix.com.
+nuking name vix.com. and its descendants
+adding name 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+adding name 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w. (black)
+ ++ BEG down from 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+ a (black)
+ NULL
+ NULL
+ -- END down from 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+ NULL
+ NULL
+adding name .
+nuking name . and its descendants
+adding name \[xFFFF/16].\[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/256].com
+adding name \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com
+\[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com. (black)
+ ++ BEG down from \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com.
+ \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/144] (black)
+ NULL
+ NULL
+ -- END down from \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com.
+ NULL
+ NULL
diff --git a/bin/tests/optional/rbt_test.txt b/bin/tests/optional/rbt_test.txt
new file mode 100644
index 0000000..4821c34
--- /dev/null
+++ b/bin/tests/optional/rbt_test.txt
@@ -0,0 +1,85 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+add a.vix.com
+add b.vix.com
+add c.vix.com
+print
+add a.b.c.d.e.f.vix.com
+add b.b.c.d.e.f.vix.com
+add c.b.c.d.e.f.vix.com
+print
+add a.d.e.f.vix.com
+add q.d.e.f.vix.com
+add d.e.f.vix.com
+print
+add g.h.vix.com
+print
+search q.d.e.f.vix.com
+search just-parent.a.vix.com
+search no-real-parent.vix.com
+search does.not.exist.at.all
+forward
+backward
+# existing name
+check vix.com.
+# greater than stop node, which has down pointer
+check zzz.com.
+# less than lowest in level (would be left link from stop node)
+check 0.vix.com
+# greater than stop node, no down pointer
+check d.vix.com
+# superdomain stored in existing node
+check f.vix.com
+# common ancestor stored in existing node; existing is successor
+check a.e.f.vix.com
+# common ancestor stored in existing node; existing is less but not predecessor
+check z.e.f.vix.com
+#
+check g.vix.com
+#
+check i.vix.com
+#
+check b.c.vix.com
+nuke d.e.f.vix.com
+print
+add x.a.vix.com
+add y.x.a.vix.com
+print
+delete a.vix.com
+delete x.a.vix.com
+print
+delete b.vix.com
+delete c.vix.com
+print
+delete y.x.a.vix.com
+print
+delete g.h.vix.com.
+add \[b100000].vix.com.
+add \[b010000].vix.com.
+add \[b001000].vix.com.
+add \[b000100].vix.com.
+add \[b000010].vix.com.
+add \[b000001].vix.com.
+p
+search \[b000100].vix.com.
+# zap the entire tree
+add vix.com.
+nuke vix.com.
+add 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+add 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+print
+add .
+# zap it again
+nuke .
+# test splitting of maximal bitstring
+add \[xFFFF/16].\[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/256].com
+add \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com
+print
+quit
diff --git a/bin/tests/optional/rwlock_test.c b/bin/tests/optional/rwlock_test.c
new file mode 100644
index 0000000..a540e3c
--- /dev/null
+++ b/bin/tests/optional/rwlock_test.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/print.h>
+#include <isc/thread.h>
+#include <isc/rwlock.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#ifdef WIN32
+#define sleep(x) Sleep(1000 * x)
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+isc_rwlock_t lock;
+
+static isc_threadresult_t
+#ifdef WIN32
+WINAPI
+#endif
+run1(void *arg) {
+ char *message = arg;
+
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ printf("%s got READ lock\n", message);
+ sleep(1);
+ printf("%s giving up READ lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ printf("%s got READ lock\n", message);
+ sleep(1);
+ printf("%s giving up READ lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ printf("%s got WRITE lock\n", message);
+ sleep(1);
+ printf("%s giving up WRITE lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ return ((isc_threadresult_t)0);
+}
+
+static isc_threadresult_t
+#ifdef WIN32
+WINAPI
+#endif
+run2(void *arg) {
+ char *message = arg;
+
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ printf("%s got WRITE lock\n", message);
+ sleep(1);
+ printf("%s giving up WRITE lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ printf("%s got WRITE lock\n", message);
+ sleep(1);
+ printf("%s giving up WRITE lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ printf("%s got READ lock\n", message);
+ sleep(1);
+ printf("%s giving up READ lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ return ((isc_threadresult_t)0);
+}
+
+int
+main(int argc, char *argv[]) {
+ unsigned int nworkers;
+ unsigned int i;
+ isc_thread_t workers[100];
+ char name[100];
+ void *dupname;
+
+ if (argc > 1)
+ nworkers = atoi(argv[1]);
+ else
+ nworkers = 2;
+ if (nworkers > 100)
+ nworkers = 100;
+ printf("%u workers\n", nworkers);
+
+ RUNTIME_CHECK(isc_rwlock_init(&lock, 5, 10) == ISC_R_SUCCESS);
+
+ for (i = 0; i < nworkers; i++) {
+ snprintf(name, sizeof(name), "%02u", i);
+ dupname = strdup(name);
+ RUNTIME_CHECK(dupname != NULL);
+ if (i != 0 && i % 3 == 0)
+ RUNTIME_CHECK(isc_thread_create(run1, dupname,
+ &workers[i]) ==
+ ISC_R_SUCCESS);
+ else
+ RUNTIME_CHECK(isc_thread_create(run2, dupname,
+ &workers[i]) ==
+ ISC_R_SUCCESS);
+ }
+
+ for (i = 0; i < nworkers; i++)
+ (void)isc_thread_join(workers[i], NULL);
+
+ isc_rwlock_destroy(&lock);
+
+ return (0);
+}
+
+#else
+
+int
+main(int argc, char *argv[]) {
+ UNUSED(argc);
+ UNUSED(argv);
+ fprintf(stderr, "This test requires threads.\n");
+ return(1);
+}
+
+#endif
diff --git a/bin/tests/optional/serial_test.c b/bin/tests/optional/serial_test.c
new file mode 100644
index 0000000..3ecb147
--- /dev/null
+++ b/bin/tests/optional/serial_test.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <isc/print.h>
+#include <isc/serial.h>
+#include <isc/stdlib.h>
+
+int
+main() {
+ uint32_t a, b;
+ char buf[1024];
+ char *s, *e;
+
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ buf[sizeof(buf) - 1] = '\0';
+ s = buf;
+ a = strtoul(s, &e, 0);
+ if (s == e)
+ continue;
+ s = e;
+ b = strtoul(s, &e, 0);
+ if (s == e)
+ continue;
+ fprintf(stdout, "%u %u gt:%d lt:%d ge:%d le:%d eq:%d ne:%d\n",
+ a, b,
+ isc_serial_gt(a,b), isc_serial_lt(a,b),
+ isc_serial_ge(a,b), isc_serial_le(a,b),
+ isc_serial_eq(a,b), isc_serial_ne(a,b));
+ }
+ return (0);
+}
diff --git a/bin/tests/optional/shutdown_test.c b/bin/tests/optional/shutdown_test.c
new file mode 100644
index 0000000..1eeaf07
--- /dev/null
+++ b/bin/tests/optional/shutdown_test.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+typedef struct {
+ isc_mem_t * mctx;
+ isc_task_t * task;
+ isc_timer_t * timer;
+ unsigned int ticks;
+ char name[16];
+ bool exiting;
+ isc_task_t * peer;
+} t_info;
+
+#define MAX_TASKS 3
+#define T2_SHUTDOWNOK (ISC_EVENTCLASS(1024) + 0)
+#define T2_SHUTDOWNDONE (ISC_EVENTCLASS(1024) + 1)
+#define FOO_EVENT (ISC_EVENTCLASS(1024) + 2)
+
+static t_info tasks[MAX_TASKS];
+static unsigned int task_count;
+static isc_taskmgr_t * task_manager;
+static isc_timermgr_t * timer_manager;
+
+static void
+t1_shutdown(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+
+ printf("task %s (%p) t1_shutdown\n", info->name, task);
+ isc_task_detach(&info->task);
+ isc_event_free(&event);
+}
+
+static void
+t2_shutdown(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+
+ printf("task %s (%p) t2_shutdown\n", info->name, task);
+ info->exiting = true;
+ isc_event_free(&event);
+}
+
+static void
+shutdown_action(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+ isc_event_t *nevent;
+
+ INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
+
+ printf("task %s (%p) shutdown\n", info->name, task);
+ if (strcmp(info->name, "0") == 0) {
+ isc_timer_detach(&info->timer);
+ nevent = isc_event_allocate(info->mctx, info, T2_SHUTDOWNOK,
+ t2_shutdown, &tasks[1],
+ sizeof(*event));
+ RUNTIME_CHECK(nevent != NULL);
+ info->exiting = true;
+ isc_task_sendanddetach(&info->peer, &nevent);
+ }
+ isc_event_free(&event);
+}
+
+static void
+foo_event(isc_task_t *task, isc_event_t *event) {
+ printf("task(%p) foo\n", task);
+ isc_event_free(&event);
+}
+
+static void
+tick(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+ isc_event_t *nevent;
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
+
+ printf("task %s (%p) tick\n", info->name, task);
+
+ info->ticks++;
+ if (strcmp(info->name, "1") == 0) {
+ if (info->ticks == 10) {
+ RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
+ } else if (info->ticks >= 15 && info->exiting) {
+ isc_timer_detach(&info->timer);
+ isc_task_detach(&info->task);
+ nevent = isc_event_allocate(info->mctx, info,
+ T2_SHUTDOWNDONE,
+ t1_shutdown, &tasks[0],
+ sizeof(*event));
+ RUNTIME_CHECK(nevent != NULL);
+ isc_task_send(info->peer, &nevent);
+ isc_task_detach(&info->peer);
+ }
+ } else if (strcmp(info->name, "foo") == 0) {
+ isc_timer_detach(&info->timer);
+ nevent = isc_event_allocate(info->mctx, info,
+ FOO_EVENT,
+ foo_event, task,
+ sizeof(*event));
+ RUNTIME_CHECK(nevent != NULL);
+ isc_task_sendanddetach(&task, &nevent);
+ }
+
+ isc_event_free(&event);
+}
+
+static t_info *
+new_task(isc_mem_t *mctx, const char *name) {
+ t_info *ti;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ RUNTIME_CHECK(task_count < MAX_TASKS);
+ ti = &tasks[task_count];
+ ti->mctx = mctx;
+ ti->task = NULL;
+ ti->timer = NULL;
+ ti->ticks = 0;
+ if (name != NULL) {
+ INSIST(strlen(name) < sizeof(ti->name));
+ strlcpy(ti->name, name, sizeof(ti->name));
+ } else {
+ snprintf(ti->name, sizeof(ti->name), "%u", task_count);
+ }
+ RUNTIME_CHECK(isc_task_create(task_manager, 0, &ti->task) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(ti->task, shutdown_action, ti) ==
+ ISC_R_SUCCESS);
+
+ isc_time_settoepoch(&expires);
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timer_manager, isc_timertype_ticker,
+ &expires, &interval, ti->task,
+ tick, ti, &ti->timer) ==
+ ISC_R_SUCCESS);
+
+ task_count++;
+
+ return (ti);
+}
+
+int
+main(int argc, char *argv[]) {
+ unsigned int workers;
+ t_info *t1, *t2;
+ isc_task_t *task;
+ isc_mem_t *mctx, *mctx2;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ if (argc > 1) {
+ workers = atoi(argv[1]);
+ if (workers < 1)
+ workers = 1;
+ if (workers > 8192)
+ workers = 8192;
+ } else
+ workers = 2;
+ printf("%u workers\n", workers);
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ mctx2 = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &task_manager) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timer_manager) ==
+ ISC_R_SUCCESS);
+
+ t1 = new_task(mctx, NULL);
+ t2 = new_task(mctx2, NULL);
+ isc_task_attach(t2->task, &t1->peer);
+ isc_task_attach(t1->task, &t2->peer);
+
+ /*
+ * Test run-triggered shutdown.
+ */
+ (void)new_task(mctx2, "foo");
+
+ /*
+ * Test implicit shutdown.
+ */
+ task = NULL;
+ RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
+ ISC_R_SUCCESS);
+ isc_task_detach(&task);
+
+ /*
+ * Test anti-zombie code.
+ */
+ RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
+ ISC_R_SUCCESS);
+ isc_task_detach(&task);
+
+ RUNTIME_CHECK(isc_app_run() == ISC_R_SUCCESS);
+
+ isc_taskmgr_destroy(&task_manager);
+ isc_timermgr_destroy(&timer_manager);
+
+ printf("Statistics for mctx:\n");
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+ printf("Statistics for mctx2:\n");
+ isc_mem_stats(mctx2, stdout);
+ isc_mem_destroy(&mctx2);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/optional/sig0_test.c b/bin/tests/optional/sig0_test.c
new file mode 100644
index 0000000..dcf64ba
--- /dev/null
+++ b/bin/tests/optional/sig0_test.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/assertions.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/error.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/socket.h>
+#include <isc/util.h>
+
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#include <dst/result.h>
+#include <dst/dst.h>
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ printf("%s: %s\n", (str), isc_result_totext(x)); \
+ exit(-1); \
+ } \
+}
+
+isc_mutex_t lock;
+dst_key_t *key;
+isc_mem_t *mctx;
+unsigned char qdata[1024], rdata[1024];
+isc_buffer_t qbuffer, rbuffer;
+isc_taskmgr_t *taskmgr;
+isc_entropy_t *ent = NULL;
+isc_task_t *task1;
+isc_log_t *lctx = NULL;
+isc_logconfig_t *logconfig = NULL;
+isc_socket_t *s;
+isc_sockaddr_t address;
+char output[10 * 1024];
+isc_buffer_t outbuf;
+static const dns_master_style_t *style = &dns_master_style_debug;
+
+static void
+senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+
+ REQUIRE(sevent != NULL);
+ REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
+ REQUIRE(task == task1);
+
+ printf("senddone\n");
+
+ isc_event_free(&event);
+}
+
+static void
+recvdone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_buffer_t source;
+ isc_result_t result;
+ dns_message_t *response;
+
+ REQUIRE(sevent != NULL);
+ REQUIRE(sevent->ev_type == ISC_SOCKEVENT_RECVDONE);
+ REQUIRE(task == task1);
+
+ printf("recvdone\n");
+ if (sevent->result != ISC_R_SUCCESS) {
+ printf("failed\n");
+ exit(-1);
+ }
+
+ isc_buffer_init(&source, sevent->region.base, sevent->region.length);
+ isc_buffer_add(&source, sevent->n);
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+ result = dns_message_parse(response, &source, 0);
+ CHECK("dns_message_parse", result);
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(response, style, 0, &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ dns_message_destroy(&response);
+ isc_event_free(&event);
+
+ isc_app_shutdown();
+}
+
+static void
+buildquery(void) {
+ isc_result_t result;
+ dns_rdataset_t *question = NULL;
+ dns_name_t *qname = NULL;
+ isc_region_t r, inr;
+ dns_message_t *query;
+ char nametext[] = "host.example";
+ isc_buffer_t namesrc, namedst;
+ unsigned char namedata[256];
+ isc_sockaddr_t sa;
+ dns_compress_t cctx;
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+ result = dns_message_setsig0key(query, key);
+ CHECK("dns_message_setsig0key", result);
+
+ result = dns_message_gettemprdataset(query, &question);
+ CHECK("dns_message_gettemprdataset", result);
+ dns_rdataset_makequestion(question, dns_rdataclass_in,
+ dns_rdatatype_a);
+ result = dns_message_gettempname(query, &qname);
+ CHECK("dns_message_gettempname", result);
+ isc_buffer_init(&namesrc, nametext, strlen(nametext));
+ isc_buffer_add(&namesrc, strlen(nametext));
+ isc_buffer_init(&namedst, namedata, sizeof(namedata));
+ dns_name_init(qname, NULL);
+ result = dns_name_fromtext(qname, &namesrc, dns_rootname, 0, &namedst);
+ CHECK("dns_name_fromtext", result);
+ ISC_LIST_APPEND(qname->list, question, link);
+ dns_message_addname(query, qname, DNS_SECTION_QUESTION);
+
+ isc_buffer_init(&qbuffer, qdata, sizeof(qdata));
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ CHECK("dns_compress_init", result);
+ result = dns_message_renderbegin(query, &cctx, &qbuffer);
+ CHECK("dns_message_renderbegin", result);
+ result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
+ CHECK("dns_message_rendersection(question)", result);
+ result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
+ CHECK("dns_message_rendersection(answer)", result);
+ result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
+ CHECK("dns_message_rendersection(auth)", result);
+ result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
+ CHECK("dns_message_rendersection(add)", result);
+ result = dns_message_renderend(query);
+ CHECK("dns_message_renderend", result);
+ dns_compress_invalidate(&cctx);
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(query, style, 0, &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ isc_buffer_usedregion(&qbuffer, &r);
+ isc_sockaddr_any(&sa);
+ result = isc_socket_bind(s, &sa, 0);
+ CHECK("isc_socket_bind", result);
+ result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
+ NULL);
+ CHECK("isc_socket_sendto", result);
+
+ inr.base = rdata;
+ inr.length = sizeof(rdata);
+ result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
+ CHECK("isc_socket_recv", result);
+ dns_message_destroy(&query);
+}
+
+int
+main(int argc, char *argv[]) {
+ bool verbose = false;
+ isc_socketmgr_t *socketmgr;
+ isc_timermgr_t *timermgr;
+ struct in_addr inaddr;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+ int ch;
+ isc_result_t result;
+ in_port_t port = 53;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "vp:")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = true;
+ break;
+ case 'p':
+ port = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ }
+ }
+
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ent) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dst_lib_init(mctx, ent, 0) == ISC_R_SUCCESS);
+
+ dns_result_register();
+ dst_result_register();
+
+ taskmgr = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ task1 = NULL;
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task1) == ISC_R_SUCCESS);
+
+ timermgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx, &logconfig) == ISC_R_SUCCESS);
+
+ s = NULL;
+ RUNTIME_CHECK(isc_socket_create(socketmgr, PF_INET,
+ isc_sockettype_udp, &s) ==
+ ISC_R_SUCCESS);
+
+ inaddr.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&address, &inaddr, port);
+
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_constinit(&b, "child.example.", strlen("child.example."));
+ isc_buffer_add(&b, strlen("child.example."));
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ key = NULL;
+ result = dst_key_fromfile(name, 4017, DNS_KEYALG_DSA,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ NULL, mctx, &key);
+ CHECK("dst_key_fromfile", result);
+
+ buildquery();
+
+ (void)isc_app_run();
+
+ isc_task_shutdown(task1);
+ isc_task_detach(&task1);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socket_detach(&s);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ dst_key_free(&key);
+
+ dst_lib_destroy();
+
+ isc_entropy_detach(&ent);
+
+ isc_log_destroy(&lctx);
+
+ if (verbose)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ DESTROYLOCK(&lock);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/optional/sock_test.c b/bin/tests/optional/sock_test.c
new file mode 100644
index 0000000..f13a3ff
--- /dev/null
+++ b/bin/tests/optional/sock_test.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+isc_taskmgr_t *manager;
+
+static void
+my_shutdown(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("shutdown %s (%p)\n", name, task);
+ fflush(stdout);
+ isc_event_free(&event);
+}
+
+static void
+my_send(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socketevent_t *dev;
+
+ sock = event->ev_sender;
+ dev = (isc_socketevent_t *)event;
+
+ printf("my_send: %s task %p\n\t(sock %p, base %p, length %u, n %u, "
+ "result %u)\n",
+ (char *)(event->ev_arg), task, sock,
+ dev->region.base, dev->region.length,
+ dev->n, dev->result);
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ }
+
+ if (dev->region.base != NULL)
+ isc_mem_put(mctx, dev->region.base, dev->region.length);
+
+ isc_event_free(&event);
+}
+
+static void
+my_recv(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socketevent_t *dev;
+ isc_region_t region;
+ char buf[1024];
+ char host[256];
+
+ sock = event->ev_sender;
+ dev = (isc_socketevent_t *)event;
+
+ printf("Socket %s (sock %p, base %p, length %u, n %u, result %u)\n",
+ (char *)(event->ev_arg), sock,
+ dev->region.base, dev->region.length,
+ dev->n, dev->result);
+ if (dev->address.type.sa.sa_family == AF_INET6) {
+ inet_ntop(AF_INET6, &dev->address.type.sin6.sin6_addr,
+ host, sizeof(host));
+ printf("\tFrom: %s port %d\n", host,
+ ntohs(dev->address.type.sin6.sin6_port));
+ } else {
+ inet_ntop(AF_INET, &dev->address.type.sin.sin_addr,
+ host, sizeof(host));
+ printf("\tFrom: %s port %d\n", host,
+ ntohs(dev->address.type.sin.sin_port));
+ }
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+
+ if (dev->region.base != NULL)
+ isc_mem_put(mctx, dev->region.base, dev->region.length);
+ isc_event_free(&event);
+
+ isc_task_shutdown(task);
+ return;
+ }
+
+ /*
+ * Echo the data back.
+ */
+ if (strcmp(event->ev_arg, "so2") != 0) {
+ region = dev->region;
+ snprintf(buf, sizeof(buf), "\r\nReceived: %.*s\r\n\r\n",
+ (int)dev->n, (char *)region.base);
+ region.base = isc_mem_get(mctx, strlen(buf) + 1);
+ if (region.base != NULL) {
+ region.length = strlen(buf) + 1;
+ strlcpy((char *)region.base, buf, region.length);
+ } else
+ region.length = 0;
+ isc_socket_send(sock, &region, task, my_send, event->ev_arg);
+ } else {
+ region = dev->region;
+ printf("\r\nReceived: %.*s\r\n\r\n",
+ (int)dev->n, (char *)region.base);
+ }
+
+ isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);
+
+ isc_event_free(&event);
+}
+
+static void
+my_http_get(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socketevent_t *dev;
+
+ sock = event->ev_sender;
+ dev = (isc_socketevent_t *)event;
+
+ printf("my_http_get: %s task %p\n\t(sock %p, base %p, length %u, "
+ "n %u, result %u)\n",
+ (char *)(event->ev_arg), task, sock,
+ dev->region.base, dev->region.length,
+ dev->n, dev->result);
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ if (dev->region.base != NULL)
+ isc_mem_put(mctx, dev->region.base, dev->region.length);
+ isc_event_free(&event);
+ return;
+ }
+
+ isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);
+
+ isc_event_free(&event);
+}
+
+static void
+my_connect(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socket_connev_t *dev;
+ isc_region_t region;
+ char buf[1024];
+
+ sock = event->ev_sender;
+ dev = (isc_socket_connev_t *)event;
+
+ printf("%s: Connection result: %u\n", (char *)(event->ev_arg),
+ dev->result);
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+ return;
+ }
+
+ /*
+ * Send a GET string, and set up to receive (and just display)
+ * the result.
+ */
+ snprintf(buf, sizeof(buf),
+ "GET / HTTP/1.1\r\nHost: www.flame.org\r\n"
+ "Connection: Close\r\n\r\n");
+ region.base = isc_mem_get(mctx, strlen(buf) + 1);
+ if (region.base != NULL) {
+ region.length = strlen(buf) + 1;
+ strlcpy((char *)region.base, buf, region.length);
+ } else {
+ region.length = 0;
+ }
+
+ isc_socket_send(sock, &region, task, my_http_get, event->ev_arg);
+
+ isc_event_free(&event);
+}
+
+static void
+my_listen(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+ isc_socket_newconnev_t *dev;
+ isc_region_t region;
+ isc_socket_t *oldsock;
+ isc_task_t *newtask;
+
+ dev = (isc_socket_newconnev_t *)event;
+
+ printf("newcon %s (task %p, oldsock %p, newsock %p, result %u)\n",
+ name, task, event->ev_sender, dev->newsocket, dev->result);
+ fflush(stdout);
+
+ if (dev->result == ISC_R_SUCCESS) {
+ /*
+ * Queue another listen on this socket.
+ */
+ RUNTIME_CHECK(isc_socket_accept(event->ev_sender, task,
+ my_listen, event->ev_arg)
+ == ISC_R_SUCCESS);
+
+ region.base = isc_mem_get(mctx, 20);
+ region.length = 20;
+
+ /*
+ * Create a new task for this socket, and queue up a
+ * recv on it.
+ */
+ newtask = NULL;
+ RUNTIME_CHECK(isc_task_create(manager, 0, &newtask)
+ == ISC_R_SUCCESS);
+ isc_socket_recv(dev->newsocket, &region, 1,
+ newtask, my_recv, event->ev_arg);
+ isc_task_detach(&newtask);
+ } else {
+ printf("detaching from socket %p\n", event->ev_sender);
+ oldsock = event->ev_sender;
+
+ isc_socket_detach(&oldsock);
+
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+ return;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+timeout(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock = event->ev_arg;
+
+ printf("Timeout, canceling IO on socket %p (task %p)\n", sock, task);
+
+ isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_ALL);
+ isc_timer_detach((isc_timer_t **)&event->ev_sender);
+ isc_event_free(&event);
+}
+
+static char one[] = "1";
+static char two[] = "2";
+static char xso1[] = "so1";
+static char xso2[] = "so2";
+
+int
+main(int argc, char *argv[]) {
+ isc_task_t *t1, *t2;
+ isc_timermgr_t *timgr;
+ isc_time_t expires;
+ isc_interval_t interval;
+ isc_timer_t *ti1;
+ unsigned int workers;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *so1, *so2;
+ isc_sockaddr_t sockaddr;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ isc_result_t result;
+ int pf;
+
+ if (argc > 1) {
+ workers = atoi(argv[1]);
+ if (workers < 1)
+ workers = 1;
+ if (workers > 8192)
+ workers = 8192;
+ } else
+ workers = 2;
+ printf("%u workers\n", workers);
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ pf = PF_INET6;
+ else
+ pf = PF_INET;
+
+ /*
+ * EVERYTHING needs a memory context.
+ */
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ /*
+ * The task manager is independent (other than memory context)
+ */
+ manager = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) ==
+ ISC_R_SUCCESS);
+
+ /*
+ * Timer manager depends only on the memory context as well.
+ */
+ timgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);
+
+ t1 = NULL;
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS);
+ t2 = NULL;
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, one) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, two) ==
+ ISC_R_SUCCESS);
+
+ printf("task 1 = %p\n", t1);
+ printf("task 2 = %p\n", t2);
+
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ /*
+ * Open up a listener socket.
+ */
+ so1 = NULL;
+
+ if (pf == PF_INET6) {
+ in6a = in6addr_any;
+ isc_sockaddr_fromin6(&sockaddr, &in6a, 5544);
+ } else {
+ ina.s_addr = INADDR_ANY;
+ isc_sockaddr_fromin(&sockaddr, &ina, 5544);
+ }
+ RUNTIME_CHECK(isc_socket_create(socketmgr, pf, isc_sockettype_tcp,
+ &so1) == ISC_R_SUCCESS);
+ result = isc_socket_bind(so1, &sockaddr, ISC_SOCKET_REUSEADDRESS);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_socket_listen(so1, 0) == ISC_R_SUCCESS);
+
+ /*
+ * Queue up the first accept event.
+ */
+ RUNTIME_CHECK(isc_socket_accept(so1, t1, my_listen, xso1)
+ == ISC_R_SUCCESS);
+ isc_time_settoepoch(&expires);
+ isc_interval_set(&interval, 10, 0);
+ ti1 = NULL;
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires,
+ &interval, t1, timeout, so1, &ti1) ==
+ ISC_R_SUCCESS);
+
+ /*
+ * Open up a socket that will connect to www.flame.org, port 80.
+ * Why not. :)
+ */
+ so2 = NULL;
+ ina.s_addr = inet_addr("204.152.184.97");
+ if (0 && pf == PF_INET6)
+ isc_sockaddr_v6fromin(&sockaddr, &ina, 80);
+ else
+ isc_sockaddr_fromin(&sockaddr, &ina, 80);
+ RUNTIME_CHECK(isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr),
+ isc_sockettype_tcp,
+ &so2) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_socket_connect(so2, &sockaddr, t2,
+ my_connect, xso2) == ISC_R_SUCCESS);
+
+ /*
+ * Detaching these is safe, since the socket will attach to the
+ * task for any outstanding requests.
+ */
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+
+ /*
+ * Wait a short while.
+ */
+#ifndef WIN32
+ sleep(10);
+#else
+ Sleep(10000);
+#endif
+
+ fprintf(stderr, "Destroying socket manager\n");
+ isc_socketmgr_destroy(&socketmgr);
+
+ fprintf(stderr, "Destroying timer manager\n");
+ isc_timermgr_destroy(&timgr);
+
+ fprintf(stderr, "Destroying task manager\n");
+ isc_taskmgr_destroy(&manager);
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/sym_test.c b/bin/tests/optional/sym_test.c
new file mode 100644
index 0000000..4eeac18
--- /dev/null
+++ b/bin/tests/optional/sym_test.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/symtab.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+isc_symtab_t *st;
+
+static void
+undefine_action(char *key, unsigned int type, isc_symvalue_t value, void *arg)
+{
+ UNUSED(arg);
+
+ INSIST(type == 1);
+ isc_mem_free(mctx, key);
+ isc_mem_free(mctx, value.as_pointer);
+}
+
+int
+main(int argc, char *argv[]) {
+ char s[1000], *cp, *key;
+ size_t len;
+ isc_result_t result;
+ isc_symvalue_t value;
+ int trace = 0;
+ int c;
+ isc_symexists_t exists_policy = isc_symexists_reject;
+ bool case_sensitive = false;
+
+ while ((c = isc_commandline_parse(argc, argv, "tarc")) != -1) {
+ switch (c) {
+ case 't':
+ trace = 1;
+ break;
+ case 'a':
+ exists_policy = isc_symexists_add;
+ break;
+ case 'r':
+ exists_policy = isc_symexists_replace;
+ break;
+ case 'c':
+ case_sensitive = true;
+ break;
+ }
+ }
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_symtab_create(mctx, 691, undefine_action, NULL,
+ case_sensitive, &st) == ISC_R_SUCCESS);
+
+ while (fgets(s, sizeof(s), stdin) != NULL) {
+ len = strlen(s);
+ if (len > 0U && s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ len--;
+ }
+
+ cp = s;
+
+ if (cp[0] == '!') {
+ cp++;
+ result = isc_symtab_undefine(st, cp, 1);
+ if (trace || result != ISC_R_SUCCESS)
+ printf("undefine('%s'): %s\n", cp,
+ isc_result_totext(result));
+ } else {
+ key = cp;
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ if (*cp == '\0') {
+ result = isc_symtab_lookup(st, key, 0, &value);
+ if (trace || result != ISC_R_SUCCESS) {
+ printf("lookup('%s'): %s", key,
+ isc_result_totext(result));
+ if (result == ISC_R_SUCCESS) {
+ cp = value.as_pointer;
+ printf(", value == '%s'", cp);
+ }
+ printf("\n");
+ }
+ } else {
+ *cp++ = '\0';
+ key = isc_mem_strdup(mctx, key);
+ value.as_pointer = isc_mem_strdup(mctx, cp);
+ result = isc_symtab_define(st, key, 1, value,
+ exists_policy);
+ if (trace || result != ISC_R_SUCCESS) {
+ printf("define('%s', '%s'): %s\n",
+ key, cp,
+ isc_result_totext(result));
+ if (result != ISC_R_SUCCESS)
+ undefine_action(key, 1,
+ value, NULL);
+ }
+ }
+ }
+ }
+
+ isc_symtab_destroy(&st);
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/task_test.c b/bin/tests/optional/task_test.c
new file mode 100644
index 0000000..1088010
--- /dev/null
+++ b/bin/tests/optional/task_test.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx = NULL;
+
+static void
+my_callback(isc_task_t *task, isc_event_t *event) {
+ int i, j;
+ char *name = event->ev_arg;
+
+ j = 0;
+ for (i = 0; i < 1000000; i++)
+ j += 100;
+ printf("task %s (%p): %d\n", name, task, j);
+ isc_event_free(&event);
+}
+
+static void
+my_shutdown(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("shutdown %s (%p)\n", name, task);
+ isc_event_free(&event);
+}
+
+static void
+my_tick(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("task %p tick %s\n", task, name);
+ isc_event_free(&event);
+}
+
+static char one[] = "1";
+static char two[] = "2";
+static char three[] = "3";
+static char four[] = "4";
+static char foo[] = "foo";
+static char bar[] = "bar";
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *manager = NULL;
+ isc_task_t *t1 = NULL, *t2 = NULL;
+ isc_task_t *t3 = NULL, *t4 = NULL;
+ isc_event_t *event;
+ unsigned int workers;
+ isc_timermgr_t *timgr;
+ isc_timer_t *ti1, *ti2;
+ struct isc_interval interval;
+
+ if (argc > 1) {
+ workers = atoi(argv[1]);
+ if (workers < 1)
+ workers = 1;
+ if (workers > 8192)
+ workers = 8192;
+ } else
+ workers = 2;
+ printf("%u workers\n", workers);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) ==
+ ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t3) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t4) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, one) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, two) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t3, my_shutdown, three) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t4, my_shutdown, four) ==
+ ISC_R_SUCCESS);
+
+ timgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);
+ ti1 = NULL;
+
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
+ &interval, t1, my_tick, foo, &ti1) ==
+ ISC_R_SUCCESS);
+
+ ti2 = NULL;
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
+ &interval, t2, my_tick, bar, &ti2) ==
+ ISC_R_SUCCESS);
+
+ printf("task 1 = %p\n", t1);
+ printf("task 2 = %p\n", t2);
+#ifndef WIN32
+ sleep(2);
+#else
+ Sleep(2000);
+#endif
+
+ /*
+ * Note: (void *)1 is used as a sender here, since some compilers
+ * don't like casting a function pointer to a (void *).
+ *
+ * In a real use, it is more likely the sender would be a
+ * structure (socket, timer, task, etc) but this is just a test
+ * program.
+ */
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, one,
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, two,
+ sizeof(*event));
+ isc_task_send(t2, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, three,
+ sizeof(*event));
+ isc_task_send(t3, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, four,
+ sizeof(*event));
+ isc_task_send(t4, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, two,
+ sizeof(*event));
+ isc_task_send(t2, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, three,
+ sizeof(*event));
+ isc_task_send(t3, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, four,
+ sizeof(*event));
+ isc_task_send(t4, &event);
+ isc_task_purgerange(t3,
+ NULL,
+ ISC_EVENTTYPE_FIRSTEVENT,
+ ISC_EVENTTYPE_LASTEVENT, NULL);
+
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+ isc_task_detach(&t3);
+ isc_task_detach(&t4);
+
+#ifndef WIN32
+ sleep(10);
+#else
+ Sleep(10000);
+#endif
+ printf("destroy\n");
+ isc_timer_detach(&ti1);
+ isc_timer_detach(&ti2);
+ isc_timermgr_destroy(&timgr);
+ isc_taskmgr_destroy(&manager);
+ printf("destroyed\n");
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/optional/timer_test.c b/bin/tests/optional/timer_test.c
new file mode 100644
index 0000000..53d3b35
--- /dev/null
+++ b/bin/tests/optional/timer_test.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx1, *mctx2, *mctx3;
+isc_task_t *t1, *t2, *t3;
+isc_timer_t *ti1, *ti2, *ti3;
+int tick_count = 0;
+
+static void
+shutdown_task(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("task %p shutdown %s\n", task, name);
+ isc_event_free(&event);
+}
+
+static void
+tick(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
+
+ printf("task %s (%p) tick\n", name, task);
+
+ tick_count++;
+ if (ti3 != NULL && tick_count % 3 == 0)
+ isc_timer_touch(ti3);
+
+ if (ti3 != NULL && tick_count == 7) {
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ isc_interval_set(&interval, 5, 0);
+ (void)isc_time_nowplusinterval(&expires, &interval);
+ isc_interval_set(&interval, 4, 0);
+ printf("*** resetting ti3 ***\n");
+ RUNTIME_CHECK(isc_timer_reset(ti3, isc_timertype_once,
+ &expires, &interval, true) ==
+ ISC_R_SUCCESS);
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+timeout(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+ const char *type;
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_IDLE ||
+ event->ev_type == ISC_TIMEREVENT_LIFE);
+
+ if (event->ev_type == ISC_TIMEREVENT_IDLE)
+ type = "idle";
+ else
+ type = "life";
+ printf("task %s (%p) %s timeout\n", name, task, type);
+
+ if (strcmp(name, "3") == 0) {
+ printf("*** saving task 3 ***\n");
+ isc_event_free(&event);
+ return;
+ }
+
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+}
+
+static char one[] = "1";
+static char two[] = "2";
+static char three[] = "3";
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *manager = NULL;
+ isc_timermgr_t *timgr = NULL;
+ unsigned int workers;
+ isc_time_t expires, now;
+ isc_interval_t interval;
+
+ if (argc > 1) {
+ workers = atoi(argv[1]);
+ if (workers < 1)
+ workers = 1;
+ if (workers > 8192)
+ workers = 8192;
+ } else
+ workers = 2;
+ printf("%u workers\n", workers);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx1) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx1, workers, 0, &manager) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx1, &timgr) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t1) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t2) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t3) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t1, shutdown_task, one) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t2, shutdown_task, two) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t3, shutdown_task, three) ==
+ ISC_R_SUCCESS);
+
+ printf("task 1: %p\n", t1);
+ printf("task 2: %p\n", t2);
+ printf("task 3: %p\n", t3);
+
+ TIME_NOW(&now);
+
+ isc_interval_set(&interval, 2, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, NULL,
+ &interval, t2, timeout, two, &ti2) ==
+ ISC_R_SUCCESS);
+
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
+ &interval, t1, tick, one, &ti1) ==
+ ISC_R_SUCCESS);
+
+ isc_interval_set(&interval, 10, 0);
+ RUNTIME_CHECK(isc_time_add(&now, &interval, &expires) ==
+ ISC_R_SUCCESS);
+ isc_interval_set(&interval, 2, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires,
+ &interval, t3, timeout, three, &ti3) ==
+ ISC_R_SUCCESS);
+
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+ isc_task_detach(&t3);
+
+#ifndef WIN32
+ sleep(15);
+#else
+ Sleep(15000);
+#endif
+ printf("destroy\n");
+ isc_timer_detach(&ti1);
+ isc_timer_detach(&ti2);
+ isc_timer_detach(&ti3);
+#ifndef WIN32
+ sleep(2);
+#else
+ Sleep(2000);
+#endif
+ isc_timermgr_destroy(&timgr);
+ isc_taskmgr_destroy(&manager);
+ printf("destroyed\n");
+
+ printf("Statistics for mctx1:\n");
+ isc_mem_stats(mctx1, stdout);
+ isc_mem_destroy(&mctx1);
+
+ return (0);
+}
diff --git a/bin/tests/optional/zone_test.c b/bin/tests/optional/zone_test.c
new file mode 100644
index 0000000..5ab46f1
--- /dev/null
+++ b/bin/tests/optional/zone_test.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/socket.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/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/zone.h>
+
+#ifdef ISC_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#endif
+
+static int debug = 0;
+static int quiet = 0;
+static int stats = 0;
+static isc_mem_t *mctx = NULL;
+dns_zone_t *zone = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_socketmgr_t *socketmgr = NULL;
+dns_zonemgr_t *zonemgr = NULL;
+dns_zonetype_t zonetype = dns_zone_master;
+isc_sockaddr_t addr;
+
+#define ERRRET(result, function) \
+ do { \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s() returned %s\n", \
+ function, dns_result_totext(result)); \
+ return; \
+ } \
+ } while (0)
+
+#define ERRCONT(result, function) \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s() returned %s\n", \
+ function, dns_result_totext(result)); \
+ continue; \
+ } else \
+ (void)NULL
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "usage: zone_test [-dqsSM] [-c class] [-f file] zone\n");
+ exit(1);
+}
+
+static void
+setup(const char *zonename, const char *filename, const char *classname) {
+ isc_result_t result;
+ dns_rdataclass_t rdclass;
+ isc_consttextregion_t region;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ const char *rbt = "rbt";
+
+ if (debug)
+ fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
+ zonename, filename, classname);
+ result = dns_zone_create(&zone, mctx);
+ ERRRET(result, "dns_zone_new");
+
+ dns_zone_settype(zone, zonetype);
+
+ isc_buffer_constinit(&buffer, zonename, strlen(zonename));
+ isc_buffer_add(&buffer, strlen(zonename));
+ dns_fixedname_init(&fixorigin);
+ result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
+ &buffer, dns_rootname, 0, NULL);
+ ERRRET(result, "dns_name_fromtext");
+ origin = dns_fixedname_name(&fixorigin);
+
+ result = dns_zone_setorigin(zone, origin);
+ ERRRET(result, "dns_zone_setorigin");
+
+ result = dns_zone_setdbtype(zone, 1, &rbt);
+ ERRRET(result, "dns_zone_setdatabase");
+
+ result = dns_zone_setfile(zone, filename);
+ ERRRET(result, "dns_zone_setfile");
+
+ region.base = classname;
+ region.length = strlen(classname);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)(void*)&region);
+ ERRRET(result, "dns_rdataclass_fromtext");
+
+ dns_zone_setclass(zone, rdclass);
+
+ if (zonetype == dns_zone_slave)
+ dns_zone_setmasters(zone, &addr, 1);
+
+ result = dns_zone_load(zone);
+ ERRRET(result, "dns_zone_load");
+
+ result = dns_zonemgr_managezone(zonemgr, zone);
+ ERRRET(result, "dns_zonemgr_managezone");
+}
+
+static void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
+ isc_buffer_t text;
+ char t[1000];
+ isc_result_t result;
+ isc_region_t r;
+
+ isc_buffer_init(&text, t, sizeof(t));
+ result = dns_rdataset_totext(rdataset, name, false, false,
+ &text);
+ isc_buffer_usedregion(&text, &r);
+ if (result == ISC_R_SUCCESS)
+ printf("%.*s", (int)r.length, (char *)r.base);
+ else
+ printf("%s\n", dns_result_totext(result));
+}
+
+static void
+query(void) {
+ char buf[1024];
+ dns_fixedname_t name;
+ dns_fixedname_t found;
+ dns_db_t *db;
+ char *s;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t sigset;
+ fd_set rfdset;
+
+ db = NULL;
+ result = dns_zone_getdb(zone, &db);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s() returned %s\n", "dns_zone_getdb",
+ dns_result_totext(result));
+ return;
+ }
+
+ dns_fixedname_init(&found);
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigset);
+
+ do {
+
+ fprintf(stdout, "zone_test ");
+ fflush(stdout);
+ FD_ZERO(&rfdset);
+ FD_SET(0, &rfdset);
+ select(1, &rfdset, NULL, NULL, NULL);
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ fprintf(stdout, "\n");
+ break;
+ }
+ buf[sizeof(buf) - 1] = '\0';
+
+ s = strchr(buf, '\n');
+ if (s != NULL)
+ *s = '\0';
+ s = strchr(buf, '\r');
+ if (s != NULL)
+ *s = '\0';
+ if (strcmp(buf, "dump") == 0) {
+ dns_zone_dumptostream(zone, stdout);
+ continue;
+ }
+ if (strlen(buf) == 0U)
+ continue;
+ dns_fixedname_init(&name);
+ isc_buffer_init(&buffer, buf, strlen(buf));
+ isc_buffer_add(&buffer, strlen(buf));
+ result = dns_name_fromtext(dns_fixedname_name(&name),
+ &buffer, dns_rootname, 0, NULL);
+ ERRCONT(result, "dns_name_fromtext");
+
+ result = dns_db_find(db, dns_fixedname_name(&name),
+ NULL /*vesion*/,
+ dns_rdatatype_a,
+ 0 /*options*/,
+ 0 /*time*/,
+ NULL /*nodep*/,
+ dns_fixedname_name(&found),
+ &rdataset, &sigset);
+ fprintf(stderr, "%s() returned %s\n", "dns_db_find",
+ dns_result_totext(result));
+ switch (result) {
+ case DNS_R_DELEGATION:
+ print_rdataset(dns_fixedname_name(&found), &rdataset);
+ break;
+ case ISC_R_SUCCESS:
+ print_rdataset(dns_fixedname_name(&name), &rdataset);
+ break;
+ default:
+ break;
+ }
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (dns_rdataset_isassociated(&sigset))
+ dns_rdataset_disassociate(&sigset);
+ } while (1);
+ dns_rdataset_invalidate(&rdataset);
+ dns_db_detach(&db);
+}
+
+int
+main(int argc, char **argv) {
+ int c;
+ char *filename = NULL;
+ const char *classname = "IN";
+
+ while ((c = isc_commandline_parse(argc, argv, "cdf:m:qsMS")) != EOF) {
+ switch (c) {
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'f':
+ if (filename != NULL)
+ usage();
+ filename = isc_commandline_argument;
+ break;
+ case 'm':
+ memset(&addr, 0, sizeof(addr));
+ addr.type.sin.sin_family = AF_INET;
+ if (inet_pton(AF_INET, isc_commandline_argument,
+ &addr.type.sin.sin_addr) != 1) {
+ fprintf(stderr, "bad master address '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ addr.type.sin.sin_port = htons(53);
+ break;
+ case 'q':
+ quiet++;
+ break;
+ case 's':
+ stats++;
+ break;
+ case 'S':
+ zonetype = dns_zone_slave;
+ break;
+ case 'M':
+ zonetype = dns_zone_master;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (argv[isc_commandline_index] == NULL)
+ usage();
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr,
+ &zonemgr) == ISC_R_SUCCESS);
+ if (filename == NULL)
+ filename = argv[isc_commandline_index];
+ setup(argv[isc_commandline_index], filename, classname);
+ query();
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ dns_zonemgr_shutdown(zonemgr);
+ dns_zonemgr_detach(&zonemgr);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_timermgr_destroy(&timermgr);
+ if (!quiet && stats)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/pkcs11/Makefile.in b/bin/tests/pkcs11/Makefile.in
new file mode 100644
index 0000000..73e0596
--- /dev/null
+++ b/bin/tests/pkcs11/Makefile.in
@@ -0,0 +1,44 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+PROVIDER = @PKCS11_PROVIDER@
+
+CINCLUDES = ${ISC_INCLUDES}
+
+CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\"
+
+ISCLIBS = ../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS = benchmarks
+
+TARGETS = pkcs11-md5sum@EXEEXT@ pkcs11-hmacmd5@EXEEXT@
+SRCS = pkcs11-md5sum.c pkcs11-hmacmd5.c
+
+@BIND9_MAKE_RULES@
+
+pkcs11-md5sum@EXEEXT@: @srcdir@/pkcs11-md5sum.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/pkcs11-md5sum.c ${LIBS}
+
+pkcs11-hmacmd5@EXEEXT@: @srcdir@/pkcs11-hmacmd5.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/pkcs11-hmacmd5.c ${LIBS}
+
+test:
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/pkcs11/README b/bin/tests/pkcs11/README
new file mode 100644
index 0000000..2b594d9
--- /dev/null
+++ b/bin/tests/pkcs11/README
@@ -0,0 +1,15 @@
+"pkcs11-hmacmd5" is here to check for the presence of a known bug in
+the Thales nCipher PKCS#11 provider library. To test for the bug, use
+pkcs11-hmacmd5 to hash a test vector from RFC 2104, and determine
+whether the resulting digest is is correct. For instance:
+
+ echo -n "Hi There" | \
+ ./pkcs11-hmacmd5 -p <PIN> -k '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'
+
+...must return "9294727a3638bb1c13f48ef8158bfc9d".
+
+If any other value is returned, then the provider library is buggy,
+and theflag PK11_MD5_HMAC_REPLACE must be defined in
+lib/isc/include/pk11/site.h
+However, if the correct value is returned, then it is safe to turn
+off PK11_MD5_HMAC_REPLACE. (It is on by default.)
diff --git a/bin/tests/pkcs11/benchmarks/Makefile.in b/bin/tests/pkcs11/benchmarks/Makefile.in
new file mode 100644
index 0000000..15f5460
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/Makefile.in
@@ -0,0 +1,83 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+PROVIDER = @PKCS11_PROVIDER@
+
+CINCLUDES = ${ISC_INCLUDES}
+
+CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\"
+
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = session@EXEEXT@ login@EXEEXT@ random@EXEEXT@ \
+ sha1@EXEEXT@ create@EXEEXT@ find@EXEEXT@ \
+ pubrsa@EXEEXT@ privrsa@EXEEXT@ genrsa@EXEEXT@ \
+ sign@EXEEXT@ verify@EXEEXT@
+
+SRCS = session.c login.c random.c sha1.c create.c find.c \
+ pubrsa.c privrsa.c genrsa.c sign.c verify.c
+
+@BIND9_MAKE_RULES@
+
+session@EXEEXT@: @srcdir@/session.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/session.c ${LIBS}
+
+login@EXEEXT@: @srcdir@/login.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/login.c ${LIBS}
+
+random@EXEEXT@: @srcdir@/random.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/random.c ${LIBS}
+
+sha1@EXEEXT@: @srcdir@/sha1.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/sha1.c ${LIBS}
+
+create@EXEEXT@: @srcdir@/create.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/create.c ${LIBS}
+
+find@EXEEXT@: @srcdir@/find.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/find.c ${LIBS}
+
+pubrsa@EXEEXT@: @srcdir@/pubrsa.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/pubrsa.c ${LIBS}
+
+privrsa@EXEEXT@: @srcdir@/privrsa.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/privrsa.c ${LIBS}
+
+genrsa@EXEEXT@: @srcdir@/genrsa.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/genrsa.c ${LIBS}
+
+sign@EXEEXT@: @srcdir@/sign.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/sign.c ${LIBS}
+
+verify@EXEEXT@: @srcdir@/verify.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/verify.c ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/pkcs11/benchmarks/create.c b/bin/tests/pkcs11/benchmarks/create.c
new file mode 100644
index 0000000..683aa40
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/create.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE buf[1024];
+char label[16];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE *hKey;
+ CK_OBJECT_CLASS kClass = CKO_DATA;
+ CK_ULONG len = sizeof(buf);
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
+ { CKA_VALUE, buf, (CK_ULONG) sizeof(buf) }
+ };
+ pk11_context_t pctx;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tcreate [-m module] [-s slot] [-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ hKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hKey[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, OP_ANY, true, true,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ /* Randomize the buffer */
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_objects;
+ }
+
+ if (ontoken)
+ kTemplate[1].pValue = &truevalue;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; i < count; i++) {
+ (void) snprintf(label, sizeof(label), "obj%u", i);
+ kTemplate[3].ulValueLen = strlen(label);
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 5, &hKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_CreateObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_objects;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u created objects in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g created objects/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ for (i = 0; i < count; i++) {
+ /* Destroy objects */
+ if (hKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, hKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(hKey);
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/find.c b/bin/tests/pkcs11/benchmarks/find.c
new file mode 100644
index 0000000..08d065a
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/find.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* find [-m module] [-s $slot] [-p pin] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE label[] = "foo??bar!!";
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ATTRIBUTE sTemplate[] =
+ {
+ { CKA_LABEL, label, (CK_ULONG) sizeof(label) },
+ };
+ CK_OBJECT_HANDLE sKey = CK_INVALID_HANDLE;
+ CK_ULONG found = 0;
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tfind [-m module] [-s slot] [-p pin] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, false,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; !error && (i < count); i++) {
+ rv = pkcs_C_FindObjectsInit(hSession, sTemplate, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjectsInit[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+
+ rv = pkcs_C_FindObjects(hSession, &sKey, 1, &found);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjects[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ /* no break here! */
+ }
+
+ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjectsFinal[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u object searches in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g object searches/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/genrsa.c b/bin/tests/pkcs11/benchmarks/genrsa.c
new file mode 100644
index 0000000..c642586
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/genrsa.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* genrsa [-m module] [-s $slot] [-p pin] [-t] [-b bits] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
+ CK_OBJECT_HANDLE *pubKey;
+ CK_OBJECT_HANDLE *privKey;
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
+ CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ULONG bits = 1024;
+ CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
+ CK_ATTRIBUTE pubTemplate[] =
+ {
+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
+ };
+ CK_ATTRIBUTE privTemplate[] =
+ {
+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tb:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'b':
+ bits = (CK_ULONG)atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tgenrsa [-m module] [-s slot] [-p pin] "
+ "[-t] [-b bits] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ pubKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (pubKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ privKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (privKey == NULL) {
+ free(pubKey);
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++) {
+ pubKey[i] = CK_INVALID_HANDLE;
+ privKey[i] = CK_INVALID_HANDLE;
+ }
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, true,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (ontoken) {
+ pubTemplate[2].pValue = &truevalue;
+ privTemplate[2].pValue = &truevalue;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_keys;
+ }
+
+ for (i = 0; i < count; i++) {
+ rv = pkcs_C_GenerateKeyPair(hSession, &mech,
+ pubTemplate, 7,
+ privTemplate, 5,
+ &pubKey[i], &privKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GenerateKeyPair[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_keys;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_keys;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u generated RSA in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g generated RSA/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_keys:
+ for (i = 0; i < count; i++) {
+ /* Destroy keys */
+ if (pubKey[i] == CK_INVALID_HANDLE)
+ goto destroy_priv;
+ rv = pkcs_C_DestroyObject(hSession, pubKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[pub%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ destroy_priv:
+ if (privKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, privKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[priv%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(pubKey);
+ free(privKey);
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/login.c b/bin/tests/pkcs11/benchmarks/login.c
new file mode 100644
index 0000000..280e983
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/login.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* login [-m module] [-s $slot] [-p pin] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/internal.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE *hSession;
+ CK_UTF8CHAR *pin = NULL;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i, j;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)isc_commandline_argument;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tlogin [-m module] [-s slot] [-p pin] [-n count]\n");
+ exit(1);
+ }
+
+ /* allocate sessions */
+ hSession = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hSession == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hSession[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+
+ rv = pkcs_C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ if (rv == 0xfe)
+ fprintf(stderr,
+ "Can't load or link module \"%s\"\n",
+ pk11_get_lib_name());
+ else
+ fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
+ free(hSession);
+ exit(1);
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_program;
+ }
+
+ /* loop */
+ for (i = 0; i < count; i++) {
+ /* Open sessions */
+ rv = pkcs_C_OpenSession(slot, CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_OpenSession[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+
+ /* Logon */
+ rv = pkcs_C_Login(hSession[i], CKU_USER,
+ pin, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_Login[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+
+ /* Logoff */
+ rv = pkcs_C_Logout(hSession[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_Logout[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_program;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u logins in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g logins/s\n",
+ i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ for (j = 0; j < i; j++) {
+ if (hSession[j] == CK_INVALID_HANDLE)
+ continue;
+ /* Close sessions */
+ rv = pkcs_C_CloseSession(hSession[j]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_CloseSession[%u]: Error = 0x%.8lX\n",
+ j, rv);
+ errflg = 1;
+ }
+ }
+
+ exit_program:
+ free(hSession);
+
+ rv = pkcs_C_Finalize(NULL_PTR);
+ if (rv != CKR_OK)
+ fprintf(stderr, "C_Finalize: Error = 0x%.8lX\n", rv);
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/privrsa.c b/bin/tests/pkcs11/benchmarks/privrsa.c
new file mode 100644
index 0000000..791a9a0
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/privrsa.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* privrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 };
+CK_BYTE privexp[] = {
+ 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02,
+ 0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33,
+ 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e,
+ 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63,
+ 0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b,
+ 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d,
+ 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e,
+ 0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea,
+ 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c,
+ 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7,
+ 0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc,
+ 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd,
+ 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f,
+ 0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d,
+ 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52,
+ 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c,
+ 0x41
+};
+CK_BYTE prime1[] = {
+ 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde,
+ 0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58,
+ 0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f,
+ 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36,
+ 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5,
+ 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1,
+ 0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed,
+ 0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8,
+ 0x21
+};
+CK_BYTE prime2[] = {
+ 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9,
+ 0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa,
+ 0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e,
+ 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab,
+ 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21,
+ 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88,
+ 0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36,
+ 0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0,
+ 0xdf
+};
+CK_BYTE exp_1[] = {
+ 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35,
+ 0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13,
+ 0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a,
+ 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f,
+ 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21,
+ 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42,
+ 0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f,
+ 0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1
+};
+CK_BYTE exp_2[] = {
+ 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c,
+ 0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb,
+ 0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb,
+ 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9,
+ 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24,
+ 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a,
+ 0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c,
+ 0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64,
+ 0x7f
+};
+CK_BYTE coeff[] = {
+ 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b,
+ 0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94,
+ 0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04,
+ 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5,
+ 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9,
+ 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5,
+ 0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67,
+ 0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9,
+ 0x8c
+};
+
+char label[16];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE *hKey;
+ CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) },
+ { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) },
+ { CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) },
+ { CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) },
+ { CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) },
+ { CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) },
+ { CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) }
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tprivrsa [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ hKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hKey[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, true,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ free(hKey);
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; i < count; i++) {
+ (void) snprintf(label, sizeof(label), "obj%u", i);
+ kTemplate[4].ulValueLen = strlen(label);
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 14, &hKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_CreateObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_objects;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u private RSA keys in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g private RSA keys/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ for (i = 0; i < count; i++) {
+ /* Destroy objects */
+ if (hKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, hKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(hKey);
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/pubrsa.c b/bin/tests/pkcs11/benchmarks/pubrsa.c
new file mode 100644
index 0000000..9a40b53
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/pubrsa.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* pubrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
+
+char label[16];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE *hKey;
+ CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tpubrsa [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ hKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hKey[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, true,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ free(hKey);
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; i < count; i++) {
+ (void) snprintf(label, sizeof(label), "obj%u", i);
+ kTemplate[4].ulValueLen = strlen(label);
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 8, &hKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_CreateObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_objects;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u public RSA keys in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g public RSA keys/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ for (i = 0; i < count; i++) {
+ /* Destroy objects */
+ if (hKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, hKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(hKey);
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/random.c b/bin/tests/pkcs11/benchmarks/random.c
new file mode 100644
index 0000000..144cfa8
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/random.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* random [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE buf[1024];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ULONG len = sizeof(buf);
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RAND;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\trandom [-m module] [-s slot] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ result = pk11_get_session(&pctx, op_type, false, false,
+ false, NULL, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ hSession = pctx.session;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_session;
+ }
+
+ for (i = 0; i < count; i++) {
+ /* Get random bytes */
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GenerateRandom[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_session;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%uK random bytes in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g random bytes/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/session.c b/bin/tests/pkcs11/benchmarks/session.c
new file mode 100644
index 0000000..2b576f3
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/session.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* session [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/internal.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE *hSession;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tsession [-m module] [-s slot] [-n count]\n");
+ exit(1);
+ }
+
+ /* Allocate sessions */
+ hSession = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hSession == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hSession[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ rv = pkcs_C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ if (rv == 0xfe)
+ fprintf(stderr,
+ "Can't load or link module \"%s\"\n",
+ pk11_get_lib_name());
+ else
+ fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
+ free(hSession);
+ exit(1);
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_program;
+ }
+
+ /* loop */
+ for (i = 0; i < count; i++) {
+ /* Open sessions */
+ rv = pkcs_C_OpenSession(slot, CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_OpenSession[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_program;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u sessions in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g sessions/s\n",
+ i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ for (i = 0; i < count; i++) {
+ /* Close sessions */
+ if (hSession[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_CloseSession(hSession[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_CloseSession[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ exit_program:
+ free(hSession);
+
+ rv = pkcs_C_Finalize(NULL_PTR);
+ if (rv != CKR_OK)
+ fprintf(stderr, "C_Finalize: Error = 0x%.8lX\n", rv);
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/sha1.c b/bin/tests/pkcs11/benchmarks/sha1.c
new file mode 100644
index 0000000..cc8ca45
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sha1.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* sha1 [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE buf[1024];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mech = { CKM_SHA_1, NULL, 0 };
+ CK_ULONG len = sizeof(buf);
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_DIGEST;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tssha1 [-m module] [-s slot] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ result = pk11_get_session(&pctx, op_type, false, false,
+ false, NULL, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ hSession = pctx.session;
+
+ /* Randomize the buffer */
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_session;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_session;
+ }
+
+ /* Initialize Digest */
+ rv = pkcs_C_DigestInit(hSession, &mech);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DigestInit: Error = 0x%.8lX\n", rv);
+ goto exit_session;
+ }
+
+
+ for (i = 0; i < count; i++) {
+ /* Digest buffer */
+ rv = pkcs_C_DigestUpdate(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DigestUpdate[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ /* Finalize Digest (unconditionally) */
+ len = 20U;
+ rv = pkcs_C_DigestFinal(hSession, buf, &len);
+ if ((rv != CKR_OK) && !error)
+ fprintf(stderr, "C_DigestFinal: Error = 0x%.8lX\n", rv);
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_session;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%uK digested bytes in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g digested bytes/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/sign.c b/bin/tests/pkcs11/benchmarks/sign.c
new file mode 100644
index 0000000..e9cdd6b
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sign.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* signrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 };
+CK_BYTE privexp[] = {
+ 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02,
+ 0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33,
+ 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e,
+ 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63,
+ 0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b,
+ 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d,
+ 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e,
+ 0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea,
+ 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c,
+ 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7,
+ 0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc,
+ 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd,
+ 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f,
+ 0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d,
+ 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52,
+ 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c,
+ 0x41
+};
+CK_BYTE prime1[] = {
+ 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde,
+ 0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58,
+ 0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f,
+ 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36,
+ 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5,
+ 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1,
+ 0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed,
+ 0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8,
+ 0x21
+};
+CK_BYTE prime2[] = {
+ 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9,
+ 0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa,
+ 0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e,
+ 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab,
+ 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21,
+ 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88,
+ 0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36,
+ 0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0,
+ 0xdf
+};
+CK_BYTE exp_1[] = {
+ 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35,
+ 0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13,
+ 0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a,
+ 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f,
+ 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21,
+ 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42,
+ 0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f,
+ 0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1
+};
+CK_BYTE exp_2[] = {
+ 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c,
+ 0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb,
+ 0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb,
+ 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9,
+ 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24,
+ 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a,
+ 0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c,
+ 0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64,
+ 0x7f
+};
+CK_BYTE coeff[] = {
+ 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b,
+ 0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94,
+ 0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04,
+ 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5,
+ 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9,
+ 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5,
+ 0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67,
+ 0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9,
+ 0x8c
+};
+
+CK_BYTE buf[1024];
+CK_BYTE sig[128];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ULONG len;
+ CK_ULONG slen;
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) },
+ { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) },
+ { CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) },
+ { CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) },
+ { CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) },
+ { CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) },
+ { CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) }
+ };
+ CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tsign [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, true,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ /* Create the private RSA key */
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 13, &hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
+ goto exit_key;
+ }
+
+ /* Randomize the buffer */
+ len = (CK_ULONG) sizeof(buf);
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_key;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_key;
+ }
+
+ for (i = 0; i < count; i++) {
+ /* Initialize Sign */
+ rv = pkcs_C_SignInit(hSession, &mech, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_SignInit[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+
+ /* Perform Sign */
+ slen = (CK_ULONG) sizeof(sig);
+ rv = pkcs_C_Sign(hSession, buf, len, sig, &slen);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_Sign[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_key;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u RSA signs in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g RSA signs/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_key:
+ if (hKey != CK_INVALID_HANDLE) {
+ rv = pkcs_C_DestroyObject(hSession, hKey);
+ if (rv != CKR_OK)
+ fprintf(stderr,
+ "C_DestroyObject: Error = 0x%.8lX\n",
+ rv);
+ }
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/verify.c b/bin/tests/pkcs11/benchmarks/verify.c
new file mode 100644
index 0000000..b04b777
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/verify.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* verify [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
+
+CK_BYTE buf[1024];
+CK_BYTE sig[128];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ULONG len;
+ CK_ULONG slen;
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
+ };
+ CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tverify [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, true,
+ true, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ /* Create the private RSA key */
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 7, &hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_key;
+ }
+
+ /* Randomize the buffer */
+ len = (CK_ULONG) sizeof(buf);
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_key;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_key;
+ }
+
+ for (i = 0; i < count; i++) {
+ /* Initialize Verify */
+ rv = pkcs_C_VerifyInit(hSession, &mech, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_VerifyInit[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+
+ /* Perform Verify */
+ slen = (CK_ULONG) sizeof(sig);
+ rv = pkcs_C_Verify(hSession, buf, len, sig, slen);
+ if ((rv != CKR_OK) && (rv != CKR_SIGNATURE_INVALID)) {
+ fprintf(stderr,
+ "C_Verify[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_key;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u RSA verify in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g RSA verify/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_key:
+ if (hKey != CK_INVALID_HANDLE) {
+ rv = pkcs_C_DestroyObject(hSession, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DestroyObject: Error = 0x%.8lX\n",
+ rv);
+ errflg = 1;
+ }
+ }
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/pkcs11-hmacmd5.c b/bin/tests/pkcs11/pkcs11-hmacmd5.c
new file mode 100644
index 0000000..ba4adb1
--- /dev/null
+++ b/bin/tests/pkcs11/pkcs11-hmacmd5.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pkcs11-hmacmd5
+ *
+ * Prints the MD5 HMAC of the standard input, using the PKCS#11 device.
+ *
+ * Usage:
+ * pkcs11-hmacmd5 [-m module] [-s $slot] [-n] [-p $pin]
+ * -m: PKCS#11 provider module. This must be the full
+ * path to a shared library object implementing the
+ * PKCS#11 API for a device.
+ * -s: Slot
+ * -p: PIN
+ * -n: don't log in to the PKCS#11 device
+ * -k: key name for the HMAC
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+/* Define static key template values */
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+#define BLOCKSIZE 32768
+
+char buffer[BLOCKSIZE + 72];
+char digest[16];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 };
+ CK_ULONG len;
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_MD5_HMAC;
+ CK_ATTRIBUTE keyTemplate[] =
+ {
+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_VALUE, NULL, 0 }
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_DIGEST;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ bool logon = true;
+ int c, errflg = 0;
+ char *key = NULL;
+ size_t sum = 0;
+ unsigned int i;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:np:k:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'n':
+ logon = false;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'k':
+ key = isc_commandline_argument;
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg || (key == NULL)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tpkcs11-hmacmd5 [-m module] [-s slot] "
+ "[-n|-p pin] -k key\n");
+ exit(1);
+ }
+
+ /* Decode the key */
+ for (i = 0; i < BLOCKSIZE / 2; i++) {
+ switch (c = *key++) {
+ case 0:
+ goto key_done;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if ((i & 1) == 0)
+ buffer[i >> 1] = (c - '0') << 4;
+ else
+ buffer[i >> 1] |= c - '0';
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ if ((i & 1) == 0)
+ buffer[i >> 1] = (c - 'A' + 10) << 4;
+ else
+ buffer[i >> 1] |= c - 'A' + 10;
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ if ((i & 1) == 0)
+ buffer[i >> 1] = (c - 'a' + 10) << 4;
+ else
+ buffer[i >> 1] |= c - 'a' + 10;
+ break;
+ default:
+ fprintf(stderr, "Not hexdigit '%c' in key\n", c);
+ exit(1);
+ }
+ }
+ key_done:
+ if ((i & 1) != 0) {
+ fprintf(stderr, "Even number of hexdigits in key\n");
+ exit(1);
+ }
+ len = i >> 1;
+ keyTemplate[5].pValue = buffer;
+ keyTemplate[5].ulValueLen = (CK_ULONG) len;
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (logon && pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, false, logon,
+ (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ rv = pkcs_C_CreateObject(hSession, keyTemplate, (CK_ULONG) 6, &hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ if (hKey == CK_INVALID_HANDLE) {
+ fprintf(stderr, "C_CreateObject failed\n");
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = pkcs_C_SignInit(hSession, &mech, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_SignInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_sign;
+ }
+
+ for (;;) {
+ size_t n;
+
+ for (;;) {
+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stdin);
+ sum += n;
+ if (sum == BLOCKSIZE)
+ break;
+ if (n == 0) {
+ if (ferror(stdin)) {
+ fprintf(stderr, "fread failed\n");
+ error = 1;
+ goto exit_sign;
+ }
+ goto partial_block;
+ }
+ if (feof(stdin))
+ goto partial_block;
+ }
+
+ rv = pkcs_C_SignUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) BLOCKSIZE);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_SignUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_sign;
+ }
+ }
+
+partial_block:
+ if (sum > 0) {
+ rv = pkcs_C_SignUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) sum);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_SignUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_sign;
+ }
+ }
+
+ len = 16;
+ rv = pkcs_C_SignFinal(hSession, (CK_BYTE_PTR) digest, &len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_SignFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_sign;
+ }
+ if (len != 16) {
+ fprintf(stderr, "C_SignFinal: bad length = %lu\n", len);
+ error = 1;
+ }
+
+ for (i = 0; i < 16; i++)
+ printf("%02x", digest[i] & 0xff);
+ printf("\n");
+
+ exit_sign:
+ rv = pkcs_C_DestroyObject(hSession, hKey);
+ if ((error == 0) && (rv != CKR_OK)) {
+ fprintf(stderr, "C_DestroyObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/pkcs11-md5sum.c b/bin/tests/pkcs11/pkcs11-md5sum.c
new file mode 100644
index 0000000..56f3a61
--- /dev/null
+++ b/bin/tests/pkcs11/pkcs11-md5sum.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions copyright (c) 2008 Nominet UK. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pkcs11-md5sum
+ *
+ * Prints the MD5 checksum of the standard input, using the PKCS#11 device.
+ *
+ * Usage:
+ * pkcs11-md5sum [-m module] [-s $slot] [-n] [-p $pin]
+ * -m: PKCS#11 provider module. This must be the full
+ * path to a shared library object implementing the
+ * PKCS#11 API for a device.
+ * -s: Slot
+ * -p: PIN
+ * -n: don't log in to the PKCS#11 device
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#define BLOCKSIZE 32768
+
+char buffer[BLOCKSIZE + 72];
+char digest[16];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
+ CK_ULONG len;
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_DIGEST;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ bool logon = true;
+ int c, errflg = 0;
+ size_t sum = 0;
+ unsigned int i;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:np:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'n':
+ logon = false;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n",
+ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+ if (errflg) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tpkcs11-md5sum [-m module] [-s slot] [-n|-p pin]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (logon && pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, false, false, logon,
+ (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ rv = pkcs_C_DigestInit(hSession, &mech);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DigestInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ for (;;) {
+ size_t n;
+
+ for (;;) {
+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stdin);
+ sum += n;
+ if (sum == BLOCKSIZE)
+ break;
+ if (n == 0) {
+ if (ferror(stdin)) {
+ fprintf(stderr, "fread failed\n");
+ error = 1;
+ goto exit_session;
+ }
+ goto partial_block;
+ }
+ if (feof(stdin))
+ goto partial_block;
+ }
+
+ rv = pkcs_C_DigestUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) BLOCKSIZE);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DigestUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_session;
+ }
+ }
+
+partial_block:
+ if (sum > 0) {
+ rv = pkcs_C_DigestUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) sum);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DigestUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_session;
+ }
+ }
+
+ len = 16;
+ rv = pkcs_C_DigestFinal(hSession, (CK_BYTE_PTR) digest, &len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DigestFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ if (len != 16) {
+ fprintf(stderr, "C_DigestFinal: bad length = %lu\n", len);
+ error = 1;
+ }
+
+ for (i = 0; i < 16; i++)
+ printf("%02x", digest[i] & 0xff);
+ printf("\n");
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/startperf/README b/bin/tests/startperf/README
new file mode 100644
index 0000000..0b8185b
--- /dev/null
+++ b/bin/tests/startperf/README
@@ -0,0 +1,17 @@
+These scripts generate a named.conf file with an arbitrary number of
+small zones, for testing startup performance.
+
+To generate a test server with 1000 zones each of which contains 5 A
+records, run:
+
+ $ sh setup.sh 1000 5 > named.conf
+
+Zones are generated with random names, and the zone files are created
+in the subdirectory "zones".
+
+Or, to generate a test server with 100 zones which all load from the same
+generic file (smallzone.db):
+
+ $ sh setup.sh -s 100 > named.conf
+
+The "number of records" argument is ignored if -s is used.
diff --git a/bin/tests/startperf/clean.sh b/bin/tests/startperf/clean.sh
new file mode 100644
index 0000000..4049ba3
--- /dev/null
+++ b/bin/tests/startperf/clean.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -rf zones
+rm -f named.conf
diff --git a/bin/tests/startperf/makenames.pl b/bin/tests/startperf/makenames.pl
new file mode 100644
index 0000000..a2bb2cf
--- /dev/null
+++ b/bin/tests/startperf/makenames.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+
+die "Usage: makenames.pl <num> [<len>]" if (@ARGV == 0 || @ARGV > 2);
+my $len = 10;
+$len = @ARGV[1] if (@ARGV == 2);
+
+my @chars = split("", "abcdefghijklmnopqrstuvwxyz123456789");
+
+srand;
+for (my $i = 0; $i < @ARGV[0]; $i++) {
+ my $name = "";
+ for (my $j = 0; $j < $len; $j++) {
+ my $r = rand 35;
+ $name .= $chars[$r];
+ }
+ print "$name" . ".example\n";
+}
diff --git a/bin/tests/startperf/mkzonefile.pl b/bin/tests/startperf/mkzonefile.pl
new file mode 100644
index 0000000..f050535
--- /dev/null
+++ b/bin/tests/startperf/mkzonefile.pl
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+
+die "Usage: makenames.pl zonename num_records" if (@ARGV != 2);
+my $zname = @ARGV[0];
+my $nrecords = @ARGV[1];
+
+my @chars = split("", "abcdefghijklmnopqrstuvwxyz");
+
+print"\$TTL 300 ; 5 minutes
+\$ORIGIN $zname.
+@ IN SOA mname1. . (
+ 2011080201 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3\n";
+
+srand;
+for (my $i = 0; $i < $nrecords; $i++) {
+ my $name = "";
+ for (my $j = 0; $j < 8; $j++) {
+ my $r = rand 25;
+ $name .= $chars[$r];
+ }
+ print "$name" . "\tIN\tA\t";
+ my $x = int rand 254;
+ my $y = int rand 254;
+ my $z = int rand 254;
+ print "10.$x.$y.$z\n";
+}
+
diff --git a/bin/tests/startperf/setup.sh b/bin/tests/startperf/setup.sh
new file mode 100644
index 0000000..e784665
--- /dev/null
+++ b/bin/tests/startperf/setup.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+usage () {
+ echo "Usage: $0 [-s] <number of zones> [<records per zone>]"
+ echo " -s: use the same zone file all zones"
+ exit 1
+}
+
+if [ "$#" -lt 1 -o "$#" -gt 3 ]; then
+ usage
+fi
+
+single_file=""
+if [ $1 = "-s" ]; then
+ single_file=yes
+ shift
+fi
+
+nzones=$1
+shift
+
+nrecords=5
+[ "$#" -eq 1 ] && nrecords=$1
+
+. ../system/conf.sh
+
+cat << EOF
+options {
+ directory "`pwd`";
+ listen-on { localhost; };
+ listen-on-v6 { localhost; };
+ port 5300;
+ allow-query { any; };
+ allow-transfer { localhost; };
+ allow-recursion { none; };
+ recursion no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 127.0.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+logging {
+ channel basic {
+ file "`pwd`/named.log" versions 3 size 100m;
+ severity info;
+ print-time yes;
+ print-severity no;
+ print-category no;
+ };
+ category default {
+ basic;
+ };
+};
+
+EOF
+
+$PERL makenames.pl $nzones | while read zonename; do
+ if [ $single_file ]; then
+ echo "zone $zonename { type master; file \"smallzone.db\"; };"
+ else
+ [ -d zones ] || mkdir zones
+ $PERL mkzonefile.pl $zonename $nrecords > zones/$zonename.db
+ echo "zone $zonename { type master; file \"zones/$zonename.db\"; };"
+ fi
+done
diff --git a/bin/tests/startperf/smallzone.db b/bin/tests/startperf/smallzone.db
new file mode 100644
index 0000000..20a3b9d
--- /dev/null
+++ b/bin/tests/startperf/smallzone.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in
new file mode 100644
index 0000000..c18b4c5
--- /dev/null
+++ b/bin/tests/system/Makefile.in
@@ -0,0 +1,140 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+SUBDIRS = dlzexternal dyndb lwresd pipelined rndc rsabigexponent tkey
+
+CINCLUDES = ${ISC_INCLUDES} ${DNS_INCLUDES}
+
+CDEFINES = @USE_GSSAPI@
+CWARNINGS =
+
+DNSLIBS =
+ISCLIBS = ../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+DNSDEPLIBS =
+ISCDEPLIBS =
+
+DEPLIBS =
+
+LIBS = @LIBS@
+
+OBJS = feature-test.@O@
+SRCS = feature-test.c
+
+TARGETS = feature-test@EXEEXT@
+
+@BIND9_MAKE_RULES@
+
+subdirs: ${TARGETS}
+
+feature-test@EXEEXT@: feature-test.@O@
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ feature-test.@O@ ${ISCLIBS} ${LIBS}
+
+# Running the scripts below is bypassed when a separate build directory is
+# used.
+
+# Define the tests that can be run in parallel. This should be identical to
+# the definition of PARALLELDIRS in conf.sh. Note: longer-running tests
+# such as serve-stale and rpzrecurse are scheduled first to get more
+# benefit from parallelism.
+PARALLEL = rpzrecurse dnssec \
+ acl additional addzone allow-query autosign \
+ builtin cacheclean case catz chain \
+ checkconf checknames checkzone \
+ @CHECKDS@ @COVERAGE@ @KEYMGR@ \
+ cookie database digdelv dlv dlz dlzexternal \
+ dns64 @DNSTAP@ dscp dsdigest dyndb \
+ ednscompliance emptyzones \
+ fetchlimit filter-aaaa formerr forward \
+ geoip glue idna inline integrity ixfr \
+ legacy limits logfileconfig \
+ masterfile masterformat metadata mkeys \
+ names notify nslookup nsupdate nzd2nzf \
+ pending pipelined \
+ reclimit redirect resolver rndc rootkeysentinel rpz \
+ rrchecker rrl rrsetorder rsabigexponent runtime \
+ sfcache smartsign sortlist \
+ spf staticstub statistics statschannel stub \
+ tcp tsig tsiggss \
+ unknown upforwd verify views wildcard \
+ xfer xferquota zero zonechecks
+
+# Produce intermediate makefile that assigns unique port numbers to each
+# parallel test. The start port number of 5,000 is arbitrary - it must just
+# be greater than the highest privileged port, 1024.
+#
+# Test names need to be sanitized because Solaris make does not like
+# underscores in target names and requires explicit differentiation
+# between a target name and a directory name (.PHONY is not supported).
+
+.PHONY: parallel.mk
+
+parallel.mk:
+ @PARALLEL_SANITIZED=`echo $(PARALLEL) | sed "s|\([^ ][^ ]*\)|test-\1|g;" | tr _ -` ; \
+ echo ".PHONY: $$PARALLEL_SANITIZED" > $@ ; \
+ echo "" >> $@ ; \
+ echo "check_interfaces:" >> $@ ; \
+ echo " @${PERL} testsock.pl > /dev/null 2>&1 || { \\" >> $@ ; \
+ echo " echo \"I:NOTE: System tests were skipped because they require that the\"; \\" >> $@ ; \
+ echo " echo \"I: IP addresses 10.53.0.1 through 10.53.0.8 be configured\"; \\" >> $@ ; \
+ echo " echo \"I: as alias 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: $$PARALLEL_SANITIZED" >> $@ ; \
+ port=$${STARTPORT:-5000} ; \
+ for directory in $(PARALLEL) ; do \
+ echo "" >> $@ ; \
+ echo "test-`echo $$directory | tr _ -`: check_interfaces" >> $@ ; \
+ echo " @$(SHELL) ./run.sh -r -p $$port $$directory 2>&1 | tee $$directory/test.output" >> $@ ; \
+ port=`expr $$port + 100` ; \
+ done
+
+# Targets to run the tests.
+
+test: parallel.mk subdirs
+ @$(MAKE) -f parallel.mk check
+ @$(SHELL) ./runsequential.sh -r
+ @$(SHELL) ./testsummary.sh
+
+check: test
+
+# Other targets:
+#
+# testclean - delete files generated by running tests.
+# clean - testclean + also delete files built for the tests by "make".
+# distclean - clean + also delete test-related files generated by "configure".
+
+testclean clean distclean::
+ if test -f ./cleanall.sh; then $(SHELL) ./cleanall.sh; fi
+ rm -f systests.output
+ rm -f random.data
+ rm -f parallel.mk
+
+clean distclean::
+ rm -f ${TARGETS}
+ rm -f ${OBJS}
+
+distclean::
+ rm -f conf.sh
+
+installdirs:
+
+install::
+
+uninstall::
diff --git a/bin/tests/system/README b/bin/tests/system/README
new file mode 100644
index 0000000..f527e79
--- /dev/null
+++ b/bin/tests/system/README
@@ -0,0 +1,773 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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) and "win32" (which holds files needed to run the tests in a
+Windows environment), 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
+===
+
+Running an Individual Test
+---
+The tests can be run individually using the following command:
+
+ sh run.sh [flags] <test-name> [<test-arguments>]
+
+e.g.
+
+ sh 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.
+
+ -r The "runall" flag. This is related to cleaning up after
+ the tests (see "Maintenance Notes" below). If specified,
+ it prevents a copy of the test's output listing from being
+ deleted when the directory is cleaned up after the test
+ completes. (The test's output listing comprises messages
+ produced by the test during its execution; it does not
+ include the output files produced by utilities such as
+ "dig" or "rndc", nor any logging output from named itself.)
+ It is usually only used when "run.sh" is being called
+ during a run of the entire test suite. Note that if "-n"
+ is specified on the "run.sh" command line, the test output
+ is retained even if this option is omitted.
+
+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 run.sh being piped through "tee").
+
+The optional flag "-n" has the same effect as it does for "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 master (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.
+ UNTESTED The test was not run for some other reason, e.g. a
+ prerequisite is available but is not compatible with
+ the platform on which the test is run.
+
+<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.
+
+Deletion of files produced by an individual test can be done with the command:
+
+ sh clean.sh [-r] <test-name>
+
+The optional flag is:
+
+ -r The "runall" flag. This is related to cleaning up after
+ the tests (see "Maintenance Notes" below). If specified,
+ it prevents a copy of the test's output listing from being
+ deleted when the directory is cleaned after the test
+ completes.
+
+Deletion of the files produced by the set of tests (e.g. after the execution
+of "runall.sh") can be deleted by 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 result of R:SKIPPED or R:UNTESTED. 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 "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 "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 "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 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:
+
+ SYSTEMTESTTOP=..
+ . $SYSTEMTESTTOP/conf.sh
+
+"conf.sh" defines a series of environment variables together with functions
+useful for the test scripts. (conf.sh.win32 is the Windows equivalent of this
+file.)
+
+
+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=`expr $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=`expr $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 "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,size,mctx
+ 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).
+
+In addition, start.pl also sets the following undocumented flag:
+
+ -T clienttest Makes clients single-shot with their own memory context.
+
+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 "clienttest" option has already been mentioned, but 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 "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.
+
+* conf.sh.win32 This is the Windows equivalent of conf.sh.in. The name of the
+test should be added to the PARALLELDIRS or SEQUENTIALDIRS variables as
+appropriate.
+
+* 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.
+
+
+Maintenance Notes
+===
+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 "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) run.sh -r -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, files are created in the test directory. These files fall
+into three categories:
+
+1. Files generated by the test itself, e.g. output from "dig" and "rndc".
+
+2. Files produced by named which may not be cleaned up if named exits
+abnormally, e.g. core files, PID files etc.
+
+3. The file "test.output" containing the text written to stdout by the test.
+This 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". This is called from the system's "clean.sh", which in turn is
+called from "run.sh".
+
+2. Files that may not be cleaned up if named exits abnormally are removed
+by the system's "clean.sh".
+
+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 "systest.output" file before deleting them.
+
+A complication arises with the "test.output" file however:
+
+1. "clean.sh" is called by "run.sh" if the test ends successfully. For
+this reason, "clean.sh" cannot delete "test.output" as, if the test is
+being run as part of a test suite, the file must be retained.
+
+2. If the deletion of "test.output" were to be solely the responsibility of
+"testsummary.sh", should a test suite terminate abnormally, cleaning up a test
+directory with "sh clean.sh <test-directory>" would leave the file present.
+
+3. An additional step could be added to "cleanall.sh" (which calls the
+system's "clean.sh" for each test) to remove the "test.output" file. However,
+although the file would be deleted should all test directories be cleaned,
+it would still mean that running "clean.sh" on a particular test directory
+could leave the file present.
+
+To get round this, the system's "clean.sh" script takes an optional flag, "-r"
+(the "runall" flag). When the test suite is run, each invocation of "run.sh"
+is passed the runall flag. In turn, "run.sh" passes the flag to "clean.sh",
+which causes that script not to delete the "tests.output" file. In other
+words, when the system's "clean.sh" is invoked standalone on a test directory
+(or as part of a run of "cleanall.sh"), it will delete the "test.output" if it
+is present. When invoked during a run of the entire test suite, it won't.
diff --git a/bin/tests/system/acl/clean.sh b/bin/tests/system/acl/clean.sh
new file mode 100644
index 0000000..75aceba
--- /dev/null
+++ b/bin/tests/system/acl/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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*
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..0ea6502
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named1.conf.in
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ 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..b877880
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named2.conf.in
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ 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..0a95062
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named3.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+};
+
+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 master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ 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..7cdcb6e
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named4.conf.in
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+};
+
+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 master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ 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..4b4e050
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named5.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ allow-query-on { 10.53.0.2; };
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { !key one; any; };
+};
diff --git a/bin/tests/system/acl/ns2/named6.conf.in b/bin/tests/system/acl/ns2/named6.conf.in
new file mode 100644
index 0000000..805942d
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named6.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ allow-query-on { 10.53.0.2; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { ecs 10.53/16; !10/8; };
+};
diff --git a/bin/tests/system/acl/ns2/named7.conf.in b/bin/tests/system/acl/ns2/named7.conf.in
new file mode 100644
index 0000000..5dde658
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named7.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ allow-query-on { 10.53.0.2; };
+};
+
+view one {
+ match-clients { ecs 192.0.2/24; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type master;
+ file "example.db";
+ };
+};
+
+view two {
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type master;
+ file "example.db";
+ };
+};
diff --git a/bin/tests/system/acl/ns3/example.db b/bin/tests/system/acl/ns3/example.db
new file mode 100644
index 0000000..ae1ceab
--- /dev/null
+++ b/bin/tests/system/acl/ns3/example.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..760c2bc
--- /dev/null
+++ b/bin/tests/system/acl/ns3/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
diff --git a/bin/tests/system/acl/ns4/example.db b/bin/tests/system/acl/ns4/example.db
new file mode 100644
index 0000000..f5e178d
--- /dev/null
+++ b/bin/tests/system/acl/ns4/example.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..f5e178d
--- /dev/null
+++ b/bin/tests/system/acl/ns4/existing.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..17cef4a
--- /dev/null
+++ b/bin/tests/system/acl/ns4/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+zone "existing" {
+ type master;
+ 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..e410e03
--- /dev/null
+++ b/bin/tests/system/acl/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+$SHELL ../genzone.sh 2 3 >ns2/example.db
+$SHELL ../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..09f31f2
--- /dev/null
+++ b/bin/tests/system/acl/tests.sh
@@ -0,0 +1,236 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+t=0
+
+echo_i "testing basic ACL processing"
+# key "one" should fail
+t=`expr $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=`expr $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
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+
+# prefix 10/8 should fail
+t=`expr $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=`expr $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=`expr $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
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+
+# should succeed
+t=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y 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
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+
+# should succeed
+t=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+t=`expr $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 EDNS client-subnet ACL processing"
+copy_setports ns2/named6.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+
+# should fail
+t=`expr $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 $t failed" ; status=1; }
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 +subnet="10.53.0/24" axfr > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+echo_i "testing EDNS client-subnet response scope"
+copy_setports ns2/named7.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+
+t=`expr $t + 1`
+$DIG -p ${PORT} example. soa @10.53.0.2 +subnet="10.53.0.1/32" > dig.out.${t}
+grep "CLIENT-SUBNET.*10.53.0.1/32/0" dig.out.${t} > /dev/null || { echo_i "test $t failed" ; status=1; }
+
+t=`expr $t + 1`
+$DIG -p ${PORT} example. soa @10.53.0.2 +subnet="192.0.2.128/32" > dig.out.${t}
+grep "CLIENT-SUBNET.*192.0.2.128/32/24" dig.out.${t} > /dev/null || { echo_i "test $t failed" ; status=1; }
+
+# 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 master; file "example.db"; }; '
+sleep 1
+
+t=`expr $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=`expr $status + $ret`
+
+echo_i "calling rndc reconfig"
+$RNDCCMD 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+
+sleep 1
+
+t=`expr $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=`expr $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 master; file "example.db"; }; '
+sleep 1
+
+t=`expr $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=`expr $status + $ret`
+
+echo_i "calling rndc reconfig"
+$RNDCCMD 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
+
+sleep 1
+
+t=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/additional/clean.sh b/bin/tests/system/additional/clean.sh
new file mode 100644
index 0000000..03e55cd
--- /dev/null
+++ b/bin/tests/system/additional/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
diff --git a/bin/tests/system/additional/ns1/mx.db b/bin/tests/system/additional/ns1/mx.db
new file mode 100644
index 0000000..32a2b87
--- /dev/null
+++ b/bin/tests/system/additional/ns1/mx.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..69787f6
--- /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,size,mctx -c named.conf -d 99 -X named.lock -g -T clienttest -n 1
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..dcaf81c
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named1.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ additional-from-auth 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 "rt.example" {
+ type master;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type master;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type master;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type master;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type master;
+ 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..cd0a15e
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named2.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ additional-from-auth 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 "rt.example" {
+ type master;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type master;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type master;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type master;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type master;
+ 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..8b5248b
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named3.conf.in
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ additional-from-auth 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 "rt.example" {
+ type master;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type master;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type master;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type master;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type master;
+ 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..eb503fe
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named4.conf.in
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ additional-from-auth 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 "mx.example" {
+ type master;
+ file "mx.db";
+};
+
+zone "srv.example" {
+ type master;
+ file "srv.db";
+};
+
+zone "rt.example" {
+ type master;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type master;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type master;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type master;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type master;
+ 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..d604a3a
--- /dev/null
+++ b/bin/tests/system/additional/ns1/naptr.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 127.0.0.0
+
+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..090e9b6
--- /dev/null
+++ b/bin/tests/system/additional/ns1/naptr2.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 127.0.0.0
+
+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..70e4dc8
--- /dev/null
+++ b/bin/tests/system/additional/ns1/nid.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 127.0.0.0
+
+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/rt.db b/bin/tests/system/additional/ns1/rt.db
new file mode 100644
index 0000000..57ee400
--- /dev/null
+++ b/bin/tests/system/additional/ns1/rt.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 127.0.0.0
+
+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..73cb9f3
--- /dev/null
+++ b/bin/tests/system/additional/ns1/rt2.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 127.0.0.0
+
+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..bc8d581
--- /dev/null
+++ b/bin/tests/system/additional/ns1/srv.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/ns3/named.conf.in b/bin/tests/system/additional/ns3/named.conf.in
new file mode 100644
index 0000000..f01bd47
--- /dev/null
+++ b/bin/tests/system/additional/ns3/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/additional/ns3/root.hint b/bin/tests/system/additional/ns3/root.hint
new file mode 100644
index 0000000..c1784c7
--- /dev/null
+++ b/bin/tests/system/additional/ns3/root.hint
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/additional/setup.sh b/bin/tests/system/additional/setup.sh
new file mode 100644
index 0000000..417a8b8
--- /dev/null
+++ b/bin/tests/system/additional/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named1.conf.in ns1/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..692af54
--- /dev/null
+++ b/bin/tests/system/additional/tests.sh
@@ -0,0 +1,330 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+dotests() {
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=1
+ fi
+
+ n=`expr $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=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
+$RNDCCMD 10.53.0.1 reconfig 2>&1 | sed 's/^/ns1 /' | cat_i
+sleep 2
+
+echo_i "testing with 'minimal-responses no;'"
+minimal=no
+dotests
+
+n=`expr $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: 1, ADDITIONAL: 2" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i " failed"; status=1
+fi
+
+echo_i "reconfiguring server: minimal-any yes"
+copy_setports ns1/named3.conf.in ns1/named.conf
+$RNDCCMD 10.53.0.1 reconfig 2>&1 | sed 's/^/ns1 /' | cat_i
+sleep 2
+
+n=`expr $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=1
+fi
+n=`expr $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=1
+fi
+
+n=`expr $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=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
+$RNDCCMD 10.53.0.1 reconfig 2>&1 | sed 's/^/ns1 /' | cat_i
+sleep 2
+
+echo_i "testing with 'minimal-responses no-auth-recursive;'"
+minimal=no-auth-recursive
+dotests
+
+n=`expr $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=1
+fi
+
+n=`expr $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=1
+fi
+
+echo_i "reconfiguring server: minimal-responses no"
+copy_setports ns1/named2.conf.in ns1/named.conf
+$RNDCCMD 10.53.0.1 reconfig 2>&1 | sed 's/^/ns1 /' | cat_i
+sleep 2
+
+n=`expr $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=1
+fi
+
+n=`expr $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=1
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/addzone/clean.sh b/bin/tests/system/addzone/clean.sh
new file mode 100644
index 0000000..30889d2
--- /dev/null
+++ b/bin/tests/system/addzone/clean.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f rndc.out*
+rm -f */named.conf
+rm -f */named.memstats
+rm -f ns2/*.nzf
+rm -f ns2/*.nzf~
+rm -f ns2/*.nzd ns2/*.nzd-lock
+rm -f ns2/core*
+rm -f ns2/inline.db.jbk
+rm -f ns2/inline.db.signed
+rm -f ns2/inlineslave.bk*
+rm -f ns*/named.lock
+rm -f ns*/named.run
+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/inlineslave.db
diff --git a/bin/tests/system/addzone/ns1/inlineslave.db b/bin/tests/system/addzone/ns1/inlineslave.db
new file mode 100644
index 0000000..625349e
--- /dev/null
+++ b/bin/tests/system/addzone/ns1/inlineslave.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN inlineslave.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..dddddfc
--- /dev/null
+++ b/bin/tests/system/addzone/ns1/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+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; };
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "inlineslave.example" {
+ type master;
+ file "inlineslave.db";
+};
diff --git a/bin/tests/system/addzone/ns2/added.db b/bin/tests/system/addzone/ns2/added.db
new file mode 100644
index 0000000..9b54d19
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/added.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+;$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..099f9e4
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/default.nzf.in
@@ -0,0 +1 @@
+zone previous.example { type master; 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..418ea96
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/hints.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..a45d30e
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/inline.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..47a3cc9
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/named1.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+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 master;
+ file "normal.db";
+};
+
+zone "finaldot.example." {
+ type master;
+ 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..c063d42
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/named2.conf.in
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+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 master;
+ 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/normal.db b/bin/tests/system/addzone/ns2/normal.db
new file mode 100644
index 0000000..5045092
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/normal.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..7fe5517
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/previous.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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 b/bin/tests/system/addzone/ns2/redirect.db
new file mode 100644
index 0000000..7b40db9
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/redirect.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 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..d5f7ff9
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/e.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA ns3 hostmaster 0 0 0 0 0
+@ NS ns3
+ns3 A 10.53.0.3
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..11be2f2
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/named1.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+masters "testmaster" {
+ 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..5aa682f
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/named2.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
diff --git a/bin/tests/system/addzone/setup.sh b/bin/tests/system/addzone/setup.sh
new file mode 100644
index 0000000..05ba68e
--- /dev/null
+++ b/bin/tests/system/addzone/setup.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named1.conf.in ns2/named.conf
+cp -f ns2/default.nzf.in ns2/3bf305731dd26307.nzf
+copy_setports ns3/named1.conf.in ns3/named.conf
+
+rm -f ns3/*.nzf ns3/*.nzf~
+rm -f ns3/*.nzd ns3/*.nzd-lock
+rm -f ns3/inlineslave.db
diff --git a/bin/tests/system/addzone/tests.sh b/bin/tests/system/addzone/tests.sh
new file mode 100755
index 0000000..1b0cd41
--- /dev/null
+++ b/bin/tests/system/addzone/tests.sh
@@ -0,0 +1,539 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -n "$NZD" ]; then
+ echo_i "checking that existing NZF file was renamed after migration ($n)"
+ [ -e ns2/3bf305731dd26307.nzf~ ] || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "adding new zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'added.example { type master; file "added.db"; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+$DIG $DIGOPTS @10.53.0.2 a.added.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+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
+grep "addzone: 'mister' unexpected" ns2/named.run >/dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+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
+grep "modzone: 'mister' unexpected" ns2/named.run >/dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "added.db"; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+$DIG $DIGOPTS @10.53.0.2 "a.32/1.0.0.127-in-addr.added.example" a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.32/1.0.0.127-in-addr.added.example' dig.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "added.db"; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+$DIG $DIGOPTS @10.53.0.2 "a.foo\"bar.example" a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.foo\\"bar.example' dig.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "adding new zone with missing master 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 master; file "missing.db"; };' 2> rndc.out.ns2.$n
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -z "$NZD" ]; 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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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 master; file "previous.db"; };'
+[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -n "$NZD" ]; 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=`expr $status + $ret`
+fi
+
+echo_i "deleting previously added zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone previous.example 2>&1 | sed 's/^/ns2 /' | cat_i
+$DIG $DIGOPTS @10.53.0.2 a.previous.example a > dig.out.ns2.$n
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.previous.example' dig.out.ns2.$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -n "$NZD" ]; then
+ echo_i "checking zone was deleted from NZD ($n)"
+ for i in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ $NZD2NZF ns2/_default.nzd | grep previous.example > /dev/null && ret=1
+ [ $ret = 0 ] && break
+ sleep 1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+if [ -z "$NZD" ]; 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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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/^/ns2 /' | cat_i
+$DIG $DIGOPTS @10.53.0.2 a.added.example a > dig.out.ns2.$n
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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/^/ns2 /' | cat_i
+$DIG $DIGOPTS @10.53.0.2 "a.foo\"bar.example" a > dig.out.ns2.$n
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep "^a.foo\"bar.example" dig.out.ns2.$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "normal.db"; };'
+[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "normal.db"; };'
+[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+$DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n
+grep "is no longer active and will be deleted" rndc.out.ns2.$n > /dev/null || ret=1
+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
+
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "attempting to add master zone with inline signing ($n)"
+$RNDCCMD 10.53.0.2 addzone 'inline.example { type master; file "inline.db"; inline-signing yes; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+for i in 1 2 3 4 5
+do
+ret=0
+$DIG $DIGOPTS @10.53.0.2 a.inline.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.inline.example' dig.out.ns2.$n > /dev/null || ret=1
+[ $ret = 0 ] && break
+sleep 1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "attempting to add master zone with inline signing and missing master ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'inlinemissing.example { type master; file "missing.db"; inline-signing yes; };' 2> rndc.out.ns2.$n
+grep "file not found" rndc.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "attempting to add slave zone with inline signing ($n)"
+$RNDCCMD 10.53.0.2 addzone 'inlineslave.example { type slave; masters { 10.53.0.1; }; file "inlineslave.bk"; inline-signing yes; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+for i in 1 2 3 4 5
+do
+ret=0
+$DIG $DIGOPTS @10.53.0.2 a.inlineslave.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.inlineslave.example' dig.out.ns2.$n > /dev/null || ret=1
+[ $ret = 0 ] && break
+sleep 1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "attempting to delete slave zone with inline signing ($n)"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ test -f ns2/inlineslave.bk.signed -a -f ns2/inlineslave.bk && break
+ sleep 1
+done
+$RNDCCMD 10.53.0.2 delzone inlineslave.example 2>&1 > rndc.out2.test$n
+test -f inlineslave.bk ||
+grep '^inlineslave.bk$' rndc.out2.test$n > /dev/null || {
+ echo_i "failed to report inlineslave.bk"; ret=1;
+}
+test ! -f inlineslave.bk.signed ||
+grep '^inlineslave.bk.signed$' rndc.out2.test$n > /dev/null || {
+ echo_i "failed to report inlineslave.bk.signed"; ret=1;
+}
+n=`expr $n + 1`
+status=`expr $status + $ret`
+
+echo_i "restoring slave zone with inline signing ($n)"
+$RNDCCMD 10.53.0.2 addzone 'inlineslave.example { type slave; masters { 10.53.0.1; }; file "inlineslave.bk"; inline-signing yes; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+for i in 1 2 3 4 5
+do
+ret=0
+$DIG $DIGOPTS @10.53.0.2 a.inlineslave.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.inlineslave.example' dig.out.ns2.$n > /dev/null || ret=1
+[ $ret = 0 ] && break
+sleep 1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "deleting slave zone with automatic zone file removal ($n)"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ test -f ns2/inlineslave.bk.signed -a -f ns2/inlineslave.bk && break
+ sleep 1
+done
+$RNDCCMD 10.53.0.2 delzone -clean inlineslave.example 2>&1 > /dev/null
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ test -f ns2/inlineslave.bk.signed -a -f ns2/inlineslave.bk && ret=1
+ [ $ret = 0 ] && break
+ sleep 1
+done
+n=`expr $n + 1`
+status=`expr $status + $ret`
+
+echo_i "modifying zone configuration ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'mod.example { type master; 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 master; 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that adding a 'stub' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'stub.example { type stub; masters { 1.2.3.4; }; file "stub.example.bk"; };' > rndc.out.ns2.$n 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that zone type 'redirect' (master) is properly rejected ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"." { type redirect; file "redirect.db"; };' > rndc.out.ns2.$n 2>&1 && ret=1
+grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that zone type 'redirect' (slave) is properly rejected ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"." { type redirect; masters { 1.2.3.4; }; file "redirect.bk"; };' > rndc.out.ns2.$n 2>&1 && ret=1
+grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "reconfiguring server with multiple views"
+rm -f ns2/named.conf
+copy_setports ns2/named2.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 5
+
+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 master; file "added.db"; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+$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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -z "$NZD" ]; 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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+if [ -n "$NZD" ]; then
+ echo_i "verifying added.example in external view created an external.nzd DB ($n)"
+ ret=0
+ [ -e ns2/external.nzd ] || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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
+$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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking rndc showzone with newly added zone ($n)"
+# loop because showzone may complain if zones are still being
+# loaded from the NZDB at this point.
+for try in 0 1 2 3 4 5; do
+ ret=0
+$RNDCCMD 10.53.0.2 showzone added.example in external > rndc.out.ns2.$n 2>/dev/null
+ if [ -z "$NZD" ]; then
+ expected='zone "added.example" in external { type master; file "added.db"; };'
+ else
+ expected='zone "added.example" { type master; file "added.db"; };'
+ fi
+ [ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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/^/ns2 /' | cat_i
+$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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "added.db"; };' 2> rndc.out.ns2.$n
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+grep 'cannot be deleted' rndc.out.ns2.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "ensure the configuration context is cleaned up correctly ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 reconfig > /dev/null 2>&1 || ret=1
+sleep 5
+$RNDCCMD 10.53.0.2 status > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check delzone after reconfig failure ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 addzone 'inlineslave.example. IN { type slave; file "inlineslave.db"; masterfile-format text; masters { testmaster; }; };' > /dev/null 2>&1 || ret=1
+copy_setports ns3/named2.conf.in ns3/named.conf
+$RNDCCMD 10.53.0.3 reconfig > /dev/null 2>&1 && ret=1
+sleep 5
+$RNDCCMD 10.53.0.3 delzone inlineslave.example > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "e.db"; };' > /dev/null 2>&1 || ret=1
+ $RNDCCMD 10.53.0.3 addzone "test2.baz" '{ type master; file "dne.db"; };' > /dev/null 2>&1 && ret=1
+ $RNDCCMD 10.53.0.3 addzone "test3.baz" '{ type master; 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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "check that named restarts with multiple added zones ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 addzone "test4.baz" '{ type master; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone "test5.baz" '{ type master; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$PERL $SYSTEMTESTTOP/stop.pl . ns3
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns3 || ret=1
+$DIG $DIGOPTS @10.53.0.3 version.bind txt ch > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/allow-query/clean.sh b/bin/tests/system/allow-query/clean.sh
new file mode 100644
index 0000000..1d02bf5
--- /dev/null
+++ b/bin/tests/system/allow-query/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
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..607925b
--- /dev/null
+++ b/bin/tests/system/allow-query/ns1/named.conf.in
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+zone "." {
+ type master;
+ 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..0040271
--- /dev/null
+++ b/bin/tests/system/allow-query/ns1/root.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1. hostmaster.localhost. 1 3600 1200 604800 3600
+ NS ns1.
+ns1. 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..dc51ce2
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/generic.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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
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..5c736ea
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named01.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..ec65cb2
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named02.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { any; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..1e3a3fd
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named03.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { none; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..565b666
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named04.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..f340ecb
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named05.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..0860add
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named06.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..760888e
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named07.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..2cf07de
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named08.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..bb5542e
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named09.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..1569913
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named10.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..18ac91c
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named11.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..b824844
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named12.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..88b4372
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named21.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..b461283
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named22.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..b24dac0
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named23.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { none; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..67dfbfb
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named24.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { 10.53.0.2; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..50ec84a
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named25.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { 10.53.0.1; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..a04f633
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named26.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query {! 10.53.0.2; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..0916cad
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named27.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { accept; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..9dae4c9
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named28.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { accept; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..0495516
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named29.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query {! accept; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..aeb1540
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named30.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { key one; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..d4b7432
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named31.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { key one; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..c025938
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named32.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query {! key one; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..f69bf75
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named33.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { none; };
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..694864d
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named34.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { any; };
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { none; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..d83b376
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named40.conf.in
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ file "generic.db";
+};
+
+zone "any.example" {
+ type master;
+ file "generic.db";
+ allow-query { any; };
+};
+
+zone "none.example" {
+ type master;
+ file "generic.db";
+ allow-query { none; };
+};
+
+zone "addrallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { 10.53.0.2; };
+};
+
+zone "addrnotallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { 10.53.0.1; };
+};
+
+zone "addrdisallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { ! 10.53.0.2; };
+};
+
+zone "aclallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { accept; };
+};
+
+zone "aclnotallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { badaccept; };
+};
+
+zone "acldisallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { ! accept; };
+};
+
+/* Also usable for testing key not allowed */
+zone "keyallow.example" {
+ type master;
+ file "generic.db";
+ allow-query { key one; };
+};
+
+zone "keydisallow.example" {
+ type master;
+ 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..d08a22c
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named53.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { none; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..921f3c9
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named54.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { any; };
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ 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..8652ffb
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named55.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { none; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..37d014d
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named56.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ 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..0614727
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named57.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+include "controls.conf";
+
+view "internal" {
+ allow-query-on { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type master;
+ file "generic.db";
+ };
+
+ zone "aclnotallow.example" {
+ type master;
+ 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..a8f679b
--- /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,size,mctx -c named.conf -d 99 -X named.lock -g -T clienttest -T fixedlocal
diff --git a/bin/tests/system/allow-query/ns3/named.conf.in b/bin/tests/system/allow-query/ns3/named.conf.in
new file mode 100644
index 0000000..6eace59
--- /dev/null
+++ b/bin/tests/system/allow-query/ns3/named.conf.in
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+};
+
+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..10b3c93
--- /dev/null
+++ b/bin/tests/system/allow-query/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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/named.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..fb6059d
--- /dev/null
+++ b/bin/tests/system/allow-query/tests.sh
@@ -0,0 +1,617 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 master, slave and stub can be tested in parallel by using
+# multiple instances (ns2 as master, ns3 as slave, ns4 as stub) and querying
+# as necessary.
+#
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p ${PORT}"
+
+rndc_reload() {
+ echo_i "`$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 2>&1 | sed 's/^/ns2 /'`"
+ for try in 0 1 2 3 4 5 6 7 8 9; do
+ nextpart ns2/named.run | grep "reloading configuration succeeded" > /dev/null && break
+ sleep 1
+ done
+}
+
+status=0
+n=0
+
+nextpart ns2/named.run > /dev/null
+
+# Test 1 - default, query allowed
+n=`expr $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=`expr $status + $ret`
+
+# Test 2 - explicit any, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named02.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 3 - none, query refused
+n=`expr $n + 1`
+copy_setports ns2/named03.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 4 - address allowed, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named04.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 5 - address not allowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named05.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 6 - address disallowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named06.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 7 - acl allowed, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named07.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 8 - acl not allowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named08.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+# Test 9 - acl disallowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named09.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 10 - key allowed, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named10.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 11 - key not allowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named11.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 12 - key disallowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named12.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# The next set of tests check if allow-query works in a view
+
+n=20
+# Test 21 - views default, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named21.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 22 - views explicit any, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named22.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 23 - views none, query refused
+n=`expr $n + 1`
+copy_setports ns2/named23.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 24 - views address allowed, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named24.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 25 - views address not allowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named25.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 26 - views address disallowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named26.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 27 - views acl allowed, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named27.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 28 - views acl not allowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named28.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 29 - views acl disallowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named29.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 30 - views key allowed, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named30.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 31 - views key not allowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named31.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 32 - views key disallowed, query refused
+n=`expr $n + 1`
+copy_setports ns2/named32.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 33 - views over options, views allow, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named33.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 34 - views over options, views disallow, query refused
+n=`expr $n + 1`
+copy_setports ns2/named34.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Tests for allow-query in the zone statements
+
+n=40
+
+# Test 41 - zone default, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named40.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 42 - zone explicit any, query allowed
+n=`expr $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=`expr $status + $ret`
+
+# Test 43 - zone none, query refused
+n=`expr $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 '^a.none.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 44 - zone address allowed, query allowed
+n=`expr $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=`expr $status + $ret`
+
+# Test 45 - zone address not allowed, query refused
+n=`expr $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 '^a.addrnotallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 46 - zone address disallowed, query refused
+n=`expr $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 '^a.addrdisallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 47 - zone acl allowed, query allowed
+n=`expr $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=`expr $status + $ret`
+
+# Test 48 - zone acl not allowed, query refused
+n=`expr $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 '^a.aclnotallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 49 - zone acl disallowed, query refused
+n=`expr $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 '^a.acldisallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 50 - zone key allowed, query allowed
+n=`expr $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=`expr $status + $ret`
+
+# Test 51 - zone key not allowed, query refused
+n=`expr $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 '^a.keyallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 52 - zone key disallowed, query refused
+n=`expr $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 '^a.keydisallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 53 - zones over options, zones allow, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named53.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 54 - zones over options, zones disallow, query refused
+n=`expr $n + 1`
+copy_setports ns2/named54.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 55 - zones over views, zones allow, query allowed
+n=`expr $n + 1`
+copy_setports ns2/named55.conf.in ns2/named.conf
+rndc_reload
+
+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=`expr $status + $ret`
+
+# Test 56 - zones over views, zones disallow, query refused
+n=`expr $n + 1`
+copy_setports ns2/named56.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 57 - zones over views, zones disallow, query refused (allow-query-on)
+n=`expr $n + 1`
+copy_setports ns2/named57.conf.in ns2/named.conf
+rndc_reload
+
+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 '^a.aclnotallow.example' dig.out.ns2.2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test 58 - allow-recursion inheritance
+n=`expr $n + 1`
+echo_i "test $n: default recursion configuration"
+ret=0
+$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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/ans.pl b/bin/tests/system/ans.pl
new file mode 100644
index 0000000..d7f9f63
--- /dev/null
+++ b/bin/tests/system/ans.pl
@@ -0,0 +1,519 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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.
+
+
+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) = 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)) {
+ 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);
+ $packet = new Net::DNS::Packet($qname, $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/autosign/clean.sh b/bin/tests/system/autosign/clean.sh
new file mode 100644
index 0000000..6147d8d
--- /dev/null
+++ b/bin/tests/system/autosign/clean.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */dsset-* */*.signed */trusted.conf */tmp* */*.jnl */*.bk
+rm -f */core
+rm -f */example.bk
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.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 digcomp.out.test*
+rm -f missingzsk.key inactivezsk.key
+rm -f nopriv.key vanishing.key del1.key del2.key
+rm -f ns*/named.lock
+rm -f ns*/named.lock
+rm -f ns1/root.db
+rm -f ns2/example.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/inacksk2.example.db
+rm -f ns3/inacksk3.example.db
+rm -f ns3/inaczsk2.example.db
+rm -f ns3/inaczsk3.example.db
+rm -f ns3/delzsk.example.db
+rm -f ns3/kg.out ns3/s.out ns3/st.out
+rm -f ns3/nozsk.example.db ns3/inaczsk.example.db
+rm -f ns3/nsec.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/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..ae98c42
--- /dev/null
+++ b/bin/tests/system/autosign/ns1/keygen.sh
@@ -0,0 +1,52 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+zonefile=root.db
+infile=root.db.in
+
+(cd ../ns2 && $SHELL keygen.sh )
+
+cat $infile ../ns2/dsset-example$TP > $zonefile
+
+zskact=`$KEYGEN -3 -q -r $RANDFILE $zone`
+zskvanish=`$KEYGEN -3 -q -r $RANDFILE $zone`
+zskdel=`$KEYGEN -3 -q -r $RANDFILE -D now $zone`
+zskinact=`$KEYGEN -3 -q -r $RANDFILE -I now $zone`
+zskunpub=`$KEYGEN -3 -q -r $RANDFILE -G $zone`
+zsksby=`$KEYGEN -3 -q -r $RANDFILE -A none $zone`
+zskactnowpub1d=`$KEYGEN -3 -q -r $RANDFILE -A now -P +1d $zone`
+zsknopriv=`$KEYGEN -3 -q -r $RANDFILE $zone`
+rm $zsknopriv.private
+
+ksksby=`$KEYGEN -3 -q -r $RANDFILE -P now -A now+15s -fk $zone`
+kskrev=`$KEYGEN -3 -q -r $RANDFILE -R now+15s -fk $zone`
+
+keyfile_to_trusted_keys $ksksby > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
+
+keyfile_to_trusted_keys $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..8c2e86c
--- /dev/null
+++ b/bin/tests/system/autosign/ns1/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+ allow-transfer { any; };
+ allow-query { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+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..4ed9990
--- /dev/null
+++ b/bin/tests/system/autosign/ns1/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.+005+30676.key b/bin/tests/system/autosign/ns2/Xbar.+005+30676.key
new file mode 100644
index 0000000..7428d5c
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+005+30676.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 30676, for bar.
+; Created: Sat Dec 26 03:13:10 2009
+; Publish: Sat Dec 26 03:13:10 2009
+; Activate: Sat Dec 26 03:13:10 2009
+bar. IN DNSKEY 257 3 5 AwEAAc7ppysDZjlldTwsvcXcTTOYJd5TvW5RUWWYKRsee+ozwY6C7vNI 0Xp1PiY+H31GhcnNMCjQU00y8Vezo42oJ4kpRTDevL0STksExXi1/wG+ M4j1CFMh2wgJ/9XLFzHaEWzt4sflVBAVZVXa/qNkRWDXYjsr30MWyylA wHCIxEuyA+NxAL6UL+ZuFo1j84AvfwkGcMbXTcOBSCaHT6AJToSXAcCa X4fnKJIzG4RyJoN2GK4TVdj4qSzLxL1lRkYHNqJvcmMjezxUs9A5fHNI iBEBRPs7NKrQJxegAGVn9ALylKHyhJW6uyBjleOWUDom4ej2J1vGrpQT /KCA35toCvU=
diff --git a/bin/tests/system/autosign/ns2/Xbar.+005+30676.private b/bin/tests/system/autosign/ns2/Xbar.+005+30676.private
new file mode 100644
index 0000000..dcc0fbd
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+005+30676.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 5 (RSASHA1)
+Modulus: zumnKwNmOWV1PCy9xdxNM5gl3lO9blFRZZgpGx576jPBjoLu80jRenU+Jj4ffUaFyc0wKNBTTTLxV7OjjagniSlFMN68vRJOSwTFeLX/Ab4ziPUIUyHbCAn/1csXMdoRbO3ix+VUEBVlVdr+o2RFYNdiOyvfQxbLKUDAcIjES7ID43EAvpQv5m4WjWPzgC9/CQZwxtdNw4FIJodPoAlOhJcBwJpfh+cokjMbhHImg3YYrhNV2PipLMvEvWVGRgc2om9yYyN7PFSz0Dl8c0iIEQFE+zs0qtAnF6AAZWf0AvKUofKElbq7IGOV45ZQOibh6PYnW8aulBP8oIDfm2gK9Q==
+PublicExponent: AQAB
+PrivateExponent: BcfjYsFCjuH1x4ucdbW09ncOv8ppJXbiJkt9AoP0hFOT2c5wrJ1hNOGnrdvYd2CMBlpUOR+w5BxDP+cF78Q97ogXpcjjTwj+5PuqJLg4+qx8thvacrAkdXIKEsgMytjD2d4/ksQmeBiQ7zgiGyCHC7CYzvxnzXEKlgl4FuzLRy4SH1YiSTxKfw1ANKKHxmw8Xvav9ljubrzNdBEQNs6eJNkC6c3aGqiPFyTWGa90s6t1mwTXSxFqBUR1WlbfyYfuiAK2CAvFHeNo7VuC934ri7ceEq8jeOSuY0IqDq2pA3gVWVOyR4NFLXJWeDA3pjqi109t/WGg9IGydD/hsleP4Q==
+Prime1: /hz+WxAL+9bO1l/857ME/OhxImSp86Xi7eA920sAo5ukOIQAQ6hbaKemYxyUbwBmGHEX9d0GOU+xAgZWUU9PbZgXw0fdf+uw6Hrgfce0rWY+uJpUcVHfjLPFgMC/XYrfcVQ8tsCXqRsIbqL+ynsEkQ4vybLhlSAyFqGqYFk/Qt0=
+Prime2: 0HLxXynoSxUcNW15cbuMRHD34ri8sUQsqCtezofPWcCo/17jqf42W7X9YGO70+BvmG3awSr3LaLf862ovCR5+orwE2MqamAV6JZMyR7nvMNGSHTdg3Kk7Jv7T5Gu7Cg6K+on8pMRW3aIms4gs/Z16j0Gxz74ES9IP3vsvC+q6vk=
+Exponent1: NLeXHRUrJ0fdCSRIt1iwRDeEoPn5OA7GEUtgCcp5i3eSjhb0ZxTaQc/l+NHJCW4vwApWSi9cRy99LUpbResKM1ZGN8EE9rDStqgnQnDXztFTWcDKm+e8VNhGtPtHuARDbqNnJRK3Y+Gz0iAGc8Mpo14qE9IEcoeHXKKVUf+x3BE=
+Exponent2: dKCbJB+SdM/u5IXH+TZyGKkMSLIMATKfucfqV6vs+86rv5Yb0zUEvPNqPNAQe0+LoMF2L7YWblY+71wumHXgOaobAP3u8W2pVGUjuTOtfRPU8x1QAwfV9vye87oTINaxFXkBuNtITuBXNiY2bfprpw9WB4zXxuWpiruPjQsumiE=
+Coefficient: qk8HX5fy74Sx6z3niBfTM/SUEjcsnJCTTmsXy6e7nOXWBK5ihKkmMw7LDhaY4OwjXvaVQH0Z190dfyOkWYTbXInIyNNnqCD+xZXkuzuvsUwLNgvXEFhVnzrrj3ozNiizZsyeAhFCKcITz3ci15HB3y8ZLChGYBPFU1ui7MsSkc8=
+Created: 20091226021310
+Publish: 20091226021310
+Activate: 20091226021310
diff --git a/bin/tests/system/autosign/ns2/Xbar.+005+30804.key b/bin/tests/system/autosign/ns2/Xbar.+005+30804.key
new file mode 100644
index 0000000..ab53d8c
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+005+30804.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 30804, for bar.
+; Created: Sat Dec 26 03:13:10 2009
+; Publish: Sat Dec 26 03:13:10 2009
+; Activate: Sat Dec 26 03:13:10 2009
+bar. IN DNSKEY 257 3 5 AwEAgc7ppysDZjlldTwsvcXcTTOYJd5TvW5RUWWYKRsee+ozwY6C7vNI 0Xp1PiY+H31GhcnNMCjQU00y8Vezo42oJ4kpRTDevL0STksExXi1/wG+ M4j1CFMh2wgJ/9XLFzHaEWzt4sflVBAVZVXa/qNkRWDXYjsr30MWyylA wHCIxEuyA+NxAL6UL+ZuFo1j84AvfwkGcMbXTcOBSCaHT6AJToSXAcCa X4fnKJIzG4RyJoN2GK4TVdj4qSzLxL1lRkYHNqJvcmMjezxUs9A5fHNI iBEBRPs7NKrQJxegAGVn9ALylKHyhJW6uyBjleOWUDom4ej2J1vGrpQT /KCA35toCvU=
diff --git a/bin/tests/system/autosign/ns2/Xbar.+005+30804.private b/bin/tests/system/autosign/ns2/Xbar.+005+30804.private
new file mode 100644
index 0000000..79f8d3b
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+005+30804.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 5 (RSASHA1)
+Modulus: zumnKwNmOWV1PCy9xdxNM5gl3lO9blFRZZgpGx576jPBjoLu80jRenU+Jj4ffUaFyc0wKNBTTTLxV7OjjagniSlFMN68vRJOSwTFeLX/Ab4ziPUIUyHbCAn/1csXMdoRbO3ix+VUEBVlVdr+o2RFYNdiOyvfQxbLKUDAcIjES7ID43EAvpQv5m4WjWPzgC9/CQZwxtdNw4FIJodPoAlOhJcBwJpfh+cokjMbhHImg3YYrhNV2PipLMvEvWVGRgc2om9yYyN7PFSz0Dl8c0iIEQFE+zs0qtAnF6AAZWf0AvKUofKElbq7IGOV45ZQOibh6PYnW8aulBP8oIDfm2gK9Q==
+PublicExponent: AQCB
+PrivateExponent: I5TcRq2sbSi1u5a+jL6VVBBu3nyY7p3NXeD1WYYYD66b8RWbgJdTtsZxgixD5sKKrW/xT68d3FUsIjs36w7yp5+g99q7lJ3v35VcMuLXbaKitS/LJdTZF/GIWwRs+DHdt+chh0QeNLzclq8ZfBeTAycFxwC7zVDLsqqcL6/JHiJhHT+dNEqj6/AIOgSYJzVeBI34LtZLW94IKf4dHLzREnLK6+64PFjpwjOG12O9klKfwHRIRN9WUsDG4AuzDSABH+qo2Zc6uJusC/D6HADbiG7tXmLYL6IxanWTbTrx4Hfp01fF+JQCuyOCRmN47X/nCumvDXKMn9Ve5+OlYi0vAQ==
+Prime1: /hz+WxAL+9bO1l/857ME/OhxImSp86Xi7eA920sAo5ukOIQAQ6hbaKemYxyUbwBmGHEX9d0GOU+xAgZWUU9PbZgXw0fdf+uw6Hrgfce0rWY+uJpUcVHfjLPFgMC/XYrfcVQ8tsCXqRsIbqL+ynsEkQ4vybLhlSAyFqGqYFk/Qt0=
+Prime2: 0HLxXynoSxUcNW15cbuMRHD34ri8sUQsqCtezofPWcCo/17jqf42W7X9YGO70+BvmG3awSr3LaLf862ovCR5+orwE2MqamAV6JZMyR7nvMNGSHTdg3Kk7Jv7T5Gu7Cg6K+on8pMRW3aIms4gs/Z16j0Gxz74ES9IP3vsvC+q6vk=
+Exponent1: JDLRyjRz53hTP7H2oaKgQYADs/UDswN2lwWpuag0wsPwQmeRAZZY2TiISPSu+3Mvh4XJ6r5UHQd5FbAN1v2mG4aYgWwoYwoxyvdTLcnQXciX2z+7877GcEyKHPno4fYXRqhVH4i1QjKaQl8dw9LFvzbVvGvvwsHGwQeqPprw7hk=
+Exponent2: vbnob7AZKqKhiVdEcnnhbeZBGcaKkTpE+RAkUL7spNQDiTPvJgo5fcTk/h6G7ijAXK0j62ZHZ3RS7RnaRa+KhO7usPcYMFiJ/VdAyRlIivhyi+WNQ2x4vSygwDy2VV9elljFeNe4dV1Cb+ssE8kAmbP52JjJD6MkhvVLd0u/jMk=
+Coefficient: qk8HX5fy74Sx6z3niBfTM/SUEjcsnJCTTmsXy6e7nOXWBK5ihKkmMw7LDhaY4OwjXvaVQH0Z190dfyOkWYTbXInIyNNnqCD+xZXkuzuvsUwLNgvXEFhVnzrrj3ozNiizZsyeAhFCKcITz3ci15HB3y8ZLChGYBPFU1ui7MsSkc8=
+Created: 20091226021310
+Publish: 20091226021310
+Activate: 20091226021310
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..a78c518
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/bar.db.in
@@ -0,0 +1,78 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8c7db65
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/child.nsec3.example.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8c7db65
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/child.optout.example.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..769d2b5
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/dst.example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..b4eeccb
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/example.db.in
@@ -0,0 +1,84 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
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..8655214
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/insecure.secure.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4c5e07e
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/keygen.sh
@@ -0,0 +1,52 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+# 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
+do
+ cp ../ns3/dsset-$subdomain.example$TP .
+done
+
+# Create keys and pass the DS to the parent.
+zone=example
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cat $infile dsset-*.example$TP > $zonefile
+
+kskname=`$KEYGEN -3 -q -r $RANDFILE -fk $zone`
+$KEYGEN -3 -q -r $RANDFILE $zone > /dev/null
+$DSFROMKEY $kskname.key > dsset-${zone}$TP
+
+# Create keys for a private secure zone.
+zone=private.secure.example
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cp $infile $zonefile
+$KEYGEN -3 -q -r $RANDFILE -fk $zone > /dev/null
+$KEYGEN -3 -q -r $RANDFILE $zone > /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.+005+30676.key Xbar.+005+30804.key Xbar.+005+30676.private \
+ Xbar.+005+30804.private
+do
+ cp $i `echo $i | sed s/X/K/`
+done
+$KEYGEN -q -r $RANDFILE $zone > /dev/null
+$DSFROMKEY Kbar.+005+30804.key > dsset-bar$TP
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..9f0c617
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/named.conf.in
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+ dnssec-loadkeys-interval 30;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "bar" {
+ type master;
+ file "bar.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly yes;
+};
+
+zone "private.secure.example" {
+ type master;
+ file "private.secure.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "insecure.secure.example" {
+ type master;
+ file "insecure.secure.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "child.nsec3.example" {
+ type master;
+ file "child.nsec3.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "child.optout.example" {
+ type master;
+ file "child.optout.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+include "trusted.conf";
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..37a77b7
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/private.secure.example.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..0b160d7
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/autonsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/delay.example.db b/bin/tests/system/autosign/ns3/delay.example.db
new file mode 100644
index 0000000..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/delay.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..241de31
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/delzsk.example.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/inacksk2.example.db.in b/bin/tests/system/autosign/ns3/inacksk2.example.db.in
new file mode 100644
index 0000000..90dcba9
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inacksk2.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..90dcba9
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inacksk3.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..90dcba9
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inaczsk.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..90dcba9
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inaczsk2.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..90dcba9
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inaczsk3.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/insecure.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh
new file mode 100644
index 0000000..bfe077d
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/keygen.sh
@@ -0,0 +1,318 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=autosign
+
+dumpit () {
+ echo "D:${debug}: dumping ${1}"
+ cat "${1}" | sed 's/^/D:/'
+}
+
+setup () {
+ echo_i "setting up zone: $1"
+ debug="$1"
+ zone="$1"
+ zonefile="${zone}.db"
+ infile="${zonefile}.in"
+ n=`expr ${n:-0} + 1`
+}
+
+setup secure.example
+cp $infile $zonefile
+ksk=`$KEYGEN -3 -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# NSEC3/NSEC test zone
+#
+setup secure.nsec3.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# NSEC3/NSEC3 test zone
+#
+setup nsec3.nsec3.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# OPTOUT/NSEC3 test zone
+#
+setup optout.nsec3.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A nsec3 zone (non-optout).
+#
+setup nsec3.example
+cat $infile dsset-*.${zone}$TP > $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# An NSEC3 zone, with NSEC3 parameters set prior to signing
+#
+setup autonsec3.example
+cat $infile > $zonefile
+ksk=`$KEYGEN -G -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+echo $ksk > ../autoksk.key
+zsk=`$KEYGEN -G -q -3 -r $RANDFILE $zone 2> kg.out` || dumpit kg.out
+echo $zsk > ../autozsk.key
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# OPTOUT/NSEC test zone
+#
+setup secure.optout.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# OPTOUT/NSEC3 test zone
+#
+setup nsec3.optout.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# OPTOUT/OPTOUT test zone
+#
+setup optout.optout.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A optout nsec3 zone.
+#
+setup optout.example
+cat $infile dsset-*.${zone}$TP > $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A RSASHA256 zone.
+#
+setup rsasha256.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -a RSASHA256 -b 2048 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -a RSASHA256 -b 1024 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A RSASHA512 zone.
+#
+setup rsasha512.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -a RSASHA512 -b 2048 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -a RSASHA512 -b 1024 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# NSEC-only zone.
+#
+setup nsec.example
+cp $infile $zonefile
+ksk=`$KEYGEN -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# 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
+$KEYGEN -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -PS -s now-1y -e now-6mo -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
+
+#
+# NSEC3->NSEC transition test zone.
+#
+setup nsec3-to-nsec.example
+$KEYGEN -q -a RSASHA512 -b 2048 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -a RSASHA512 -b 1024 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
+
+#
+# secure-to-insecure transition test zone; used to test removal of
+# keys via nsupdate
+#
+setup secure-to-insecure.example
+$KEYGEN -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -S -o $zone -f $zonefile $infile > s.out 2>&1 || 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 -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+echo $ksk > ../del1.key
+zsk=`$KEYGEN -q -3 -r $RANDFILE $zone 2> kg.out` || dumpit kg.out
+echo $zsk > ../del2.key
+$SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
+
+#
+# Introducing a pre-published key test.
+#
+setup prepub.example
+infile="secure-to-insecure2.example.db.in"
+$KEYGEN -3 -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
+
+#
+# Key TTL tests.
+#
+
+# no default key TTL; DNSKEY should get SOA TTL
+setup ttl1.example
+$KEYGEN -3 -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+cp $infile $zonefile
+
+# default key TTL should be used
+setup ttl2.example
+$KEYGEN -3 -q -r $RANDFILE -fk -L 60 $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -3 -q -r $RANDFILE -L 60 $zone > kg.out 2>&1 || dumpit kg.out
+cp $infile $zonefile
+
+# mismatched key TTLs, should use shortest
+setup ttl3.example
+$KEYGEN -3 -q -r $RANDFILE -fk -L 30 $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -3 -q -r $RANDFILE -L 60 $zone > kg.out 2>&1 || dumpit kg.out
+cp $infile $zonefile
+
+# existing DNSKEY RRset, should retain TTL
+setup ttl4.example
+$KEYGEN -3 -q -r $RANDFILE -L 30 -fk $zone > kg.out 2>&1 || dumpit kg.out
+cat ${infile} K${zone}.+*.key > $zonefile
+$KEYGEN -3 -q -r $RANDFILE -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 -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+echo $ksk > ../delayksk.key
+zsk=`$KEYGEN -G -q -3 -r $RANDFILE $zone 2> kg.out` || dumpit kg.out
+echo $zsk > ../delayzsk.key
+
+#
+# A zone with signatures that are already expired, and the private ZSK
+# is missing.
+#
+setup nozsk.example
+$KEYGEN -q -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+zsk=`$KEYGEN -q -3 -r $RANDFILE $zone`
+$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out 2>&1 || dumpit s.out
+echo $zsk > ../missingzsk.key
+rm -f ${zsk}.private
+
+#
+# A zone with signatures that are already expired, and the private ZSK
+# is inactive.
+#
+setup inaczsk.example
+$KEYGEN -q -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+zsk=`$KEYGEN -q -3 -r $RANDFILE $zone`
+$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out 2>&1 || dumpit s.out
+echo $zsk > ../inactivezsk.key
+$SETTIME -I now $zsk > st.out 2>&1 || dumpit st.out
+
+#
+# A zone that is set to 'auto-dnssec maintain' during a recofnig
+#
+setup reconf.example
+cp secure.example.db.in $zonefile
+$KEYGEN -q -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+
+#
+# A zone which generates a CDS and CDNSEY RRsets automatically
+#
+setup sync.example
+cp $infile $zonefile
+ksk=`$KEYGEN -3 -q -r $RANDFILE -fk -P sync now $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+echo ns3/$ksk > ../sync.key
+
+#
+# A zone that has a published inactive key that is autosigned.
+#
+setup inacksk2.example
+cp $infile $zonefile
+ksk=`$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -Pnow -A now+3600 -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A zone that has a published inactive key that is autosigned.
+#
+setup inaczsk2.example
+cp $infile $zonefile
+ksk=`$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A zone that starts with a active KSK + ZSK and a inactive ZSK.
+#
+setup inacksk3.example
+cp $infile $zonefile
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -P now -A now+3600 -fk $zone > kg.out 2>&1 || dumpit kg.out
+ksk=`$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# A zone that starts with a active KSK + ZSK and a inactive ZSK.
+#
+setup inaczsk3.example
+cp $infile $zonefile
+ksk=`$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
+
+#
+# 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 NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+zsk=`$KEYGEN -a NSEC3RSASHA1 -b 1024 -3 -q -r $RANDFILE -I now-1w $zone 2>kg.out` || dumpit kg.out
+echo $zsk > ../delzsk.key
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..257a47b
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/named.conf.in
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+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-enable yes;
+ dnssec-validation yes;
+ dnssec-loadkeys-interval 10;
+ allow-new-zones yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "bar" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "bar.bk";
+};
+
+zone "secure.example" {
+ type master;
+ file "secure.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "insecure.example" {
+ type master;
+ file "insecure.example.db";
+};
+
+zone "nsec3.example" {
+ type master;
+ file "nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "autonsec3.example" {
+ type master;
+ file "autonsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout.nsec3.example" {
+ type master;
+ file "optout.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec3.nsec3.example" {
+ type master;
+ file "nsec3.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "secure.nsec3.example" {
+ type master;
+ file "secure.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout.example" {
+ type master;
+ file "optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "secure.optout.example" {
+ type master;
+ file "secure.optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec3.optout.example" {
+ type master;
+ file "nsec3.optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout.optout.example" {
+ type master;
+ file "optout.optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "rsasha256.example" {
+ type master;
+ file "rsasha256.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "rsasha512.example" {
+ type master;
+ file "rsasha512.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec.example" {
+ type master;
+ file "nsec.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec3-to-nsec.example" {
+ type master;
+ file "nsec3-to-nsec.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "secure-to-insecure.example" {
+ type master;
+ file "secure-to-insecure.example.db";
+ allow-update { any; };
+ dnssec-secure-to-insecure yes;
+};
+
+zone "secure-to-insecure2.example" {
+ type master;
+ file "secure-to-insecure2.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+ dnssec-secure-to-insecure yes;
+};
+
+zone "oldsigs.example" {
+ type master;
+ file "oldsigs.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "prepub.example" {
+ type master;
+ file "prepub.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl1.example" {
+ type master;
+ file "ttl1.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl2.example" {
+ type master;
+ file "ttl2.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl3.example" {
+ type master;
+ file "ttl3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl4.example" {
+ type master;
+ file "ttl4.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "delay.example" {
+ type master;
+ file "delay.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nozsk.example" {
+ type master;
+ file "nozsk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "inaczsk.example" {
+ type master;
+ file "inaczsk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "sync.example" {
+ type master;
+ file "sync.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "inacksk2.example" {
+ type master;
+ file "inacksk2.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+};
+
+zone "inacksk3.example" {
+ type master;
+ file "inacksk3.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+};
+
+zone "inaczsk2.example" {
+ type master;
+ file "inaczsk2.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "inaczsk3.example" {
+ type master;
+ file "inaczsk3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "delzsk.example." {
+ type master;
+ file "delzsk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+include "trusted.conf";
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..90dcba9
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nozsk.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.example.db.in b/bin/tests/system/autosign/ns3/nsec.example.db.in
new file mode 100644
index 0000000..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..0b160d7
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/oldsigs.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..5d5416d
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/optout.example.db.in
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/optout.optout.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..862dadb
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/rsasha256.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..862dadb
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/rsasha512.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure-to-insecure2.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.nsec3.example.db.in b/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in
new file mode 100644
index 0000000..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure.optout.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c3dbada
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/sync.example.db.in
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl1.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl2.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl3.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cbfb691
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl4.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..dc1803f
--- /dev/null
+++ b/bin/tests/system/autosign/ns4/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-must-be-secure mustbesecure.example yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.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..bc33b23
--- /dev/null
+++ b/bin/tests/system/autosign/ns5/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/autosign/prereq.sh b/bin/tests/system/autosign/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/autosign/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/autosign/setup.sh b/bin/tests/system/autosign/setup.sh
new file mode 100644
index 0000000..fdf1911
--- /dev/null
+++ b/bin/tests/system/autosign/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+. ./clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..cfb8fa9
--- /dev/null
+++ b/bin/tests/system/autosign/tests.sh
@@ -0,0 +1,1428 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+# convert private-type records to readable form
+showprivate () {
+ echo "-- $@ --"
+ $DIG $DIGOPTS +nodnssec +short @$2 -t 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
+checkprivate () {
+ _ret=0
+ expected="${3:-0}"
+ x=`showprivate "$@"`
+ echo $x | grep incomplete > /dev/null && _ret=1
+
+ if [ $_ret = $expected ]; then
+ return 0
+ fi
+
+ echo "$x"
+ echo_i "failed"
+ return 1
+}
+
+#
+# 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.
+ 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
+ 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=`expr $i + 1`
+ if [ $ret = 0 ]; then break; fi
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "done"; fi
+status=`expr $status + $ret`
+
+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
+
+#
+# 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_i " resigned after the active KSK is deleted - stage 1: Verify that DNSKEY"
+echo_i " 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 7 2 " dig.out.ns3.test$n > /dev/null || ret=1
+
+pattern="DNSKEY 7 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`
+
+$SETTIME -D now+5 ns3/Kinacksk3.example.+007+${id} > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 loadkeys inacksk3.example 2>&1 | sed 's/^/ns3 /' | cat_i
+
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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_i " resigned after the active ZSK is deleted - stage 1: Verify that zone"
+echo_i " 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 7 3 " dig.out.ns3.test$n > /dev/null || ret=1
+grep "CNAME 7 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`
+$SETTIME -D now+5 ns3/Kinaczsk3.example.+007+${id} > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 loadkeys inaczsk3.example 2>&1 | sed 's/^/ns3 /' | cat_i
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+
+# try to convert nsec.example; this should fail due to non-NSEC key
+echo_i "preset nsec3param in unsigned zone via nsupdate ($n)"
+$NSUPDATE > nsupdate.out 2>&1 <<END
+server 10.53.0.3 ${PORT}
+zone nsec.example.
+update add nsec.example. 3600 NSEC3PARAM 1 0 10 BEEF
+send
+END
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 | sed 's/^/ns3 /' | cat_i
+grep "Pending NSEC3 chain 1 0 20 DEAF" signing.out.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "signing preset nsec3 zone"
+zsk=`cat autozsk.key`
+ksk=`cat autoksk.key`
+$SETTIME -K ns3 -P now -A now $zsk > /dev/null 2>&1
+$SETTIME -K ns3 -P now -A now $ksk > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 loadkeys autonsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i
+
+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
+
+echo_i "checking that expired RRSIGs from missing key are not deleted ($n)"
+ret=0
+missing=`sed 's/^K.*+007+0*\([0-9]\)/\1/' < missingzsk.key`
+$JOURNALPRINT ns3/nozsk.example.db.jnl | \
+ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$missing || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that expired RRSIGs from inactive key are not deleted ($n)"
+ret=0
+inactive=`sed 's/^K.*+007+0*\([0-9]\)/\1/' < inactivezsk.key`
+$JOURNALPRINT ns3/inaczsk.example.db.jnl | \
+ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$inactive || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that non-replaceable RRSIGs are logged only once (missing private key) ($n)"
+ret=0
+loglines=`grep "Key nozsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l`
+[ "$loglines" -eq 1 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that non-replaceable RRSIGs are logged only once (inactive private key) ($n)"
+ret=0
+loglines=`grep "Key inaczsk.example/NSEC3RSASHA1/$inactive .* retaining signatures" ns3/named.run | wc -l`
+[ "$loglines" -eq 1 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+$RNDCCMD 10.53.0.2 sync 2>&1 | sed 's/^/ns2 /' | cat_i
+$RNDCCMD 10.53.0.3 sync 2>&1 | sed 's/^/ns3 /' | cat_i
+
+echo_i "checking expired signatures were updated ($n)"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ $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
+ [ $ret = 0 ] && break
+ sleep 1
+done
+n=`expr $n + 1`
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking NSEC->NSEC3 conversion failed with NSEC-only key ($n)"
+ret=0
+grep "failed: REFUSED" nsupdate.out > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+sleep 2
+# this command should result in an empty file:
+$DIG $DIGOPTS +noall +answer autonsec3.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.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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 || ret=1 | cat_i
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 || ret=1 | cat_i
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 || ret=1 | cat_i
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 || ret=1 | cat_i
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for unpublished key ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for activated but unpublished key ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that standby key does not sign records ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that deactivated key does not sign records ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking insertion of public-only key ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking key deletion ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+ egrep '(RRSIG|DNSKEY|NSEC)' dig.out.ns3.test$n > /dev/null && ret=1
+ [ $ret -eq 0 ] && break
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 > /dev/null
+file="ns3/`cat del2.key`.key"
+$SETTIME -I now -D now $file > /dev/null
+$RNDCCMD 10.53.0.3 sign secure-to-insecure2.example. 2>&1 | sed 's/^/ns3 /' | cat_i
+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
+ egrep '(RRSIG|DNSKEY|NSEC3)' dig.out.ns3.test$n > /dev/null && ret=1
+ [ $ret -eq 0 ] && break
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 -3 -q -r $RANDFILE -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
+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=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`sed 's/^K.+007+0*\([0-9]\)/\1/' < active.key`
+newfile=`cat standby.key`
+newid=`sed 's/^K.+007+0*\([0-9]\)/\1/' < standby.key`
+$SETTIME -K ns1 -I now+2s -D now+25 $oldfile > /dev/null
+$SETTIME -K ns1 -i 0 -S $oldfile $newfile > /dev/null
+
+# 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
+sleep 4
+
+echo_i "revoking key to duplicated key ID"
+$SETTIME -R now -K ns2 Kbar.+005+30676.key > /dev/null 2>&1
+
+$RNDCCMD 10.53.0.2 loadkeys bar. 2>&1 | sed 's/^/ns2 /' | cat_i
+
+echo_i "waiting for changes to take effect"
+sleep 5
+
+echo_i "checking former standby key 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 || ret=1
+checkprivate private.secure.example 10.53.0.3 || ret=1
+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 || ret=1
+checkprivate nsec.example 10.53.0.3 || ret=1
+checkprivate oldsigs.example 10.53.0.3 || ret=1
+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
+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 || ret=1
+checkprivate secure-to-insecure.example 10.53.0.3 || ret=1
+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=`expr $n + 1`
+status=`expr $status + $ret`
+
+echo_i "forcing full sign"
+$RNDCCMD 10.53.0.1 sign . 2>&1 | sed 's/^/ns1 /' | cat_i
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 | grep -v UNSET > /dev/null 2>&1 && ret=1
+$SETTIME -K ns3 -pA -pP $ksk | grep -v UNSET > /dev/null 2>&1 && 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking scheduled key publication, not activation ($n)"
+ret=0
+$SETTIME -K ns3 -P now+3s -A none $zsk > /dev/null 2>&1
+$SETTIME -K ns3 -P now+3s -A none $ksk > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 loadkeys delay.example. 2>&1 | sed 's/^/ns2 /' | cat_i
+
+echo_i "waiting for changes to take effect"
+sleep 5
+
+$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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking scheduled key activation ($n)"
+ret=0
+$SETTIME -K ns3 -A now+3s $zsk > /dev/null 2>&1
+$SETTIME -K ns3 -A now+3s $ksk > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 loadkeys delay.example. 2>&1 | sed 's/^/ns2 /' | cat_i
+
+echo_i "waiting for changes to take effect"
+sleep 5
+
+$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
+# DNSKEY expected:
+awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.1.test$n || ret=1
+# RRSIG expected:
+awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.1.test$n || ret=1
+$DIG $DIGOPTS +noall +answer a a.delay.example. @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
+# A expected:
+awk 'BEGIN {r=1} $4=="A" {r=0} END {exit r}' dig.out.ns3.2.test$n || ret=1
+# RRSIG expected:
+awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.2.test$n || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking private key file removal caused no immediate harm ($n)"
+ret=0
+id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking revoked key with duplicate key ID (failure expected) ($n)"
+lret=0
+id=30676
+$DIG $DIGOPTS +multi dnskey bar @10.53.0.2 > dig.out.ns2.test$n || lret=1
+grep '; key id = '"$id"'$' dig.out.ns2.test$n > /dev/null || lret=1
+$DIG $DIGOPTS dnskey bar @10.53.0.4 > dig.out.ns4.test$n || lret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || lret=1
+n=`expr $n + 1`
+if [ $lret != 0 ]; then echo_i "not yet implemented"; fi
+
+echo_i "checking key event timers are always set ($n)"
+# 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 's/\.//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 $?
+}
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+$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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 master; file "reconf.example.db"; };' 2>&1 | sed 's/^/ns3 /' | cat_i
+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 master; file "reconf.example.db"; allow-update { any; }; auto-dnssec maintain; };' 2>&1 | sed 's/^/ns3 /' | cat_i
+$RNDCCMD 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+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=`expr $n + 1`
+if [ "$lret" != 0 ]; then ret=$lret; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ "$lret" != 0 ]; then ret=$lret; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "setting CDS and CDNSKEY deletion times and calling 'rndc loadkeys'"
+$SETTIME -D sync now+2 `cat sync.key` > /dev/null
+$RNDCCMD 10.53.0.3 loadkeys sync.example | sed 's/^/ns3 /' | cat_i
+echo_i "waiting for deletion to occur"
+sleep 3
+
+echo_i "checking that the CDS and CDNSKEY are deleted ($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=`expr $n + 1`
+if [ "$lret" != 0 ]; then ret=$lret; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that dnssec-settime -p Dsync works ($n)"
+ret=0
+$SETTIME -p Dsync `cat sync.key` > settime.out.$n|| ret=0
+grep "SYNC Delete:" settime.out.$n >/dev/null || ret=0
+n=`expr $n + 1`
+if [ "$lret" != 0 ]; then ret=$lret; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that dnssec-settime -p Psync works ($n)"
+ret=0
+$SETTIME -p Psync `cat sync.key` > settime.out.$n|| ret=0
+grep "SYNC Publish:" settime.out.$n >/dev/null || ret=0
+n=`expr $n + 1`
+if [ "$lret" != 0 ]; then ret=$lret; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 7 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 7 2 [0-9]* [0-9]* [0-9]* ${kskid} "
+grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1
+
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 7 2" dig.out.ns3.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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_i " resigned after the active KSK is deleted - stage 2: Verify that DNSKEY"
+echo_i " 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 7 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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_i " resigned after the active ZSK is deleted - stage 2: Verify that zone"
+echo_i " 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 7 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+ if [ $? -eq 0 ]; then
+ _ret=0
+ break
+ 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 2>&1 || 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
+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.2.test$n 2>&1
+ grep "Signing " signing.out.2.test$n > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ if [ `cat signing.out.2.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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/builtin/clean.sh b/bin/tests/system/builtin/clean.sh
new file mode 100644
index 0000000..93a1115
--- /dev/null
+++ b/bin/tests/system/builtin/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns?/named.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
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..d181a36
--- /dev/null
+++ b/bin/tests/system/builtin/ns1/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
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..e875a92
--- /dev/null
+++ b/bin/tests/system/builtin/ns2/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
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..4bce9f7
--- /dev/null
+++ b/bin/tests/system/builtin/ns3/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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";
+};
diff --git a/bin/tests/system/builtin/setup.sh b/bin/tests/system/builtin/setup.sh
new file mode 100644
index 0000000..c9f645b
--- /dev/null
+++ b/bin/tests/system/builtin/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/builtin/tests.sh b/bin/tests/system/builtin/tests.sh
new file mode 100644
index 0000000..391c239
--- /dev/null
+++ b/bin/tests/system/builtin/tests.sh
@@ -0,0 +1,242 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+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=`expr $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=`expr $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=`expr $status + $ret`; fi
+
+n=`expr $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=`expr $status + $ret`; fi
+
+n=`expr $n + 1`
+echo_i "Checking that reloading empty zones is silent ($n)"
+$RNDCCMD 10.53.0.1 reload > /dev/null
+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=`expr $status + $ret`; fi
+
+VERSION=`../../../../isc-config.sh --version | cut -d = -f 2`
+HOSTNAME=`$FEATURETEST --gethostname`
+
+n=`expr $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 "^version: BIND $VERSION " rndc.status.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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 "^version: BIND $VERSION ${DESCRIPTION}${DESCRIPTION:+ }<id:........*> (this is a test of version)" rndc.status.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^\"$VERSION\"$" dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^\"this is a test of version\"$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^\"$HOSTNAME\"$" dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^\"this.is.a.test.of.hostname\"$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+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=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^\"$HOSTNAME\"$" dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^; NSID: .* (\"$HOSTNAME\")$" dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+grep "^\"this.is.a.test.of.server-id\"$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+
+n=`expr $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
+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=`expr $status + $ret`; fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/cacheclean/clean.sh b/bin/tests/system/cacheclean/clean.sh
new file mode 100644
index 0000000..174179c
--- /dev/null
+++ b/bin/tests/system/cacheclean/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after cache cleaner tests.
+#
+
+rm -f dig.out.ns2
+rm -f dig.out.expire
+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
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..0231fbc
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/example.db
@@ -0,0 +1,2940 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..32d7081
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/expire-test.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..72a1096
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/flushtest.db
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.conf.in b/bin/tests/system/cacheclean/ns1/named.conf.in
new file mode 100644
index 0000000..2f448f7
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ check-integrity no;
+};
+
+zone "." {
+ type master;
+ file "example.db";
+};
+
+zone "flushtest.example" {
+ type master;
+ file "flushtest.db";
+};
+
+zone "expire-test" {
+ type master;
+ file "expire-test.db";
+};
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..c3c4260
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns2/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify yes;
+ max-cache-size 80%;
+ disable-empty-zone 127.IN-ADDR.ARPA;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 slave;
+ masters { 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..85855f3
--- /dev/null
+++ b/bin/tests/system/cacheclean/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/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/cacheclean/tests.sh b/bin/tests/system/cacheclean/tests.sh
new file mode 100755
index 0000000..92e0bf5
--- /dev/null
+++ b/bin/tests/system/cacheclean/tests.sh
@@ -0,0 +1,257 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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 $RNDCOPTS dumpdb -cache _default
+ for i in 0 1 2 3 4 5 6 7 8 9
+ do
+ grep '^; Dump complete$' ns2/named_dump.db > /dev/null && break
+ sleep 1
+ done
+ mv ns2/named_dump.db ns2/named_dump.db.$n
+}
+
+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
+}
+
+n=`expr $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=`expr $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=`expr $n + 1`
+echo_i "reset and check that records are correctly cached initially ($n)"
+ret=0
+load_cache
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db.$n | grep -v '^;' | egrep '(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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check flushing of the full cache ($n)"
+ret=0
+clear_cache
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db.$n | grep -v '^;' | wc -l`
+[ $nrecords -eq 0 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check the number of cached records remaining ($n)"
+ret=0
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db.$n | grep -v '^;' | egrep '(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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check the number of cached records remaining ($n)"
+ret=0
+dump_cache
+nrecords=`grep flushtest.example ns2/named_dump.db.$n | grep -v '^;' | egrep '(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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check flushtree clears adb correctly ($n)"
+ret=0
+load_cache
+dump_cache
+mv ns2/named_dump.db.$n ns2/named_dump.db.$n.a
+sed -n '/plain success\/timeout/,/Unassociated entries/p' \
+ ns2/named_dump.db.$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.$n ns2/named_dump.db.$n.b
+sed -n '/plain success\/timeout/,/Unassociated entries/p' \
+ ns2/named_dump.db.$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check expire option returned from master zone ($n)"
+ret=0
+$DIG @10.53.0.1 -p ${PORT} +expire soa expire-test > dig.out.expire
+grep EXPIRE: dig.out.expire > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check expire option returned from slave zone ($n)"
+ret=0
+$DIG @10.53.0.2 -p ${PORT} +expire soa expire-test > dig.out.expire
+grep EXPIRE: dig.out.expire > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/case/clean.sh b/bin/tests/system/case/clean.sh
new file mode 100644
index 0000000..646f3f6
--- /dev/null
+++ b/bin/tests/system/case/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
diff --git a/bin/tests/system/case/dynamic.good b/bin/tests/system/case/dynamic.good
new file mode 100644
index 0000000..2e10b64
--- /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..ee1c464
--- /dev/null
+++ b/bin/tests/system/case/ns1/dynamic.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..8aba293
--- /dev/null
+++ b/bin/tests/system/case/ns1/example.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..e1e3160
--- /dev/null
+++ b/bin/tests/system/case/ns1/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ also-notify { 10.53.0.2; };
+};
+
+zone "dynamic" {
+ type master;
+ 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..1720237
--- /dev/null
+++ b/bin/tests/system/case/ns2/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ 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; };
+};
+
+zone "example" {
+ type slave;
+ file "example.bk";
+ masters { 10.53.0.1; };
+};
+
+zone "dynamic" {
+ type slave;
+ file "dynamic.bk";
+ masters { 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..46bce2e
--- /dev/null
+++ b/bin/tests/system/case/postns1.good
@@ -0,0 +1,14 @@
+
+; <<>> DiG 9.11.0pre-alpha <<>> axfr dynamic @10.53.0.1 -p 5300
+;; global options: +cmd
+dYNAMIc. 0 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. 0 IN SOA mname1. . 2000042409 20 20 1814400 3600
+;; Query time: 0 msec
+;; SERVER: 10.53.0.1#5300(10.53.0.1)
+;; WHEN: Mon Jan 19 14:50:54 EST 2015
+;; XFR size: 6 records (messages 1, bytes 234)
+
diff --git a/bin/tests/system/case/postupdate.good b/bin/tests/system/case/postupdate.good
new file mode 100644
index 0000000..66e5e36
--- /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..066ceb2
--- /dev/null
+++ b/bin/tests/system/case/setup.sh
@@ -0,0 +1,16 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+${SHELL} clean.sh
+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..1f5634d
--- /dev/null
+++ b/bin/tests/system/case/tests.sh
@@ -0,0 +1,138 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+
+status=0
+n=0
+
+n=`expr $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
+ 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
+ grep SOA dig.ns2.test$n > /dev/null && break
+ sleep 1
+done
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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
+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=`expr $status + $ret`
+
+n=`expr $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
+digcomp dig.ns1.test$n dynamic.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=`expr $status + $ret`
+
+n=`expr $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
+digcomp dig.ns2.test$n dynamic.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=`expr $status + $ret`
+
+n=`expr $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
+digcomp dig.ns1.test$n postupdate.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=`expr $status + $ret`
+
+for i in 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS soa dynamic @10.53.0.2 | grep 2000042408 > /dev/null && break
+ sleep 1
+done
+
+n=`expr $n + 1`
+echo_i "check SOA owner case is transfered to slave ($n)"
+ret=0
+$DIG $DIGOPTS axfr dynamic @10.53.0.2 > dig.ns2.test$n
+digcomp dig.ns2.test$n postupdate.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=`expr $status + $ret`
+
+#update delete Ns1.DyNaMIC. 300 IN A 10.53.0.1
+n=`expr $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
+digcomp dig.ns1.test$n postns1.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=`expr $status + $ret`
+
+for i in 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS soa dynamic @10.53.0.2 | grep 2000042409 > /dev/null && break
+ sleep 1
+done
+
+n=`expr $n + 1`
+echo_i "check A owner case is transfered to slave ($n)"
+ret=0
+$DIG $DIGOPTS axfr dynamic @10.53.0.2 > dig.ns2.test$n
+digcomp dig.ns2.test$n postns1.good || ret=1
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/catz/clean.sh b/bin/tests/system/catz/clean.sh
new file mode 100644
index 0000000..4f90bf7
--- /dev/null
+++ b/bin/tests/system/catz/clean.sh
@@ -0,0 +1,24 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f ns*/*.jnl
+rm -f ns*/*.nzf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.conf
+rm -f ns*/named.run
+rm -f ns1/*dom*example.db
+rm -f ns2/__catz__*db
+rm -f ns2/named.conf.tmp
+rm -f ns3/dom13.example.db ns3/dom14.example.db
+rm -f nsupdate.out.*
+rm -f ns[123]/catalog[1234].example.db
+rm -rf ns2/zonedir
+rm -f ns*/*.nzd ns*/*.nzd-lock
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..dc18bf5
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog.example.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "1"
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..74b7d37
--- /dev/null
+++ b/bin/tests/system/catz/ns1/named.conf.in
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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@;
+ allow-new-zones yes;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on port @EXTRAPORT1@ { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ recursion no;
+ allow-transfer { any; };
+};
+
+zone "catalog1.example" {
+ type master;
+ file "catalog1.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+zone "catalog3.example" {
+ type master;
+ file "catalog3.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+zone "catalog4.example" {
+ type master;
+ file "catalog4.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+/* catalog5 is missing on purpose */
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm hmac-md5;
+};
diff --git a/bin/tests/system/catz/ns2/named.conf.in b/bin/tests/system/catz/ns2/named.conf.in
new file mode 100644
index 0000000..ee83efb
--- /dev/null
+++ b/bin/tests/system/catz/ns2/named.conf.in
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ catalog-zones {
+ zone "catalog1.example"
+ default-masters { 10.53.0.1; }
+ in-memory no
+ zone-directory "zonedir";
+ zone "catalog2.example"
+ default-masters { 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-masters { 10.53.0.1; };
+ };
+};
+
+zone "catalog1.example" {
+ type slave;
+ file "catalog1.example.db";
+ masters { 10.53.0.1; };
+};
+
+zone "catalog2.example" {
+ type slave;
+ file "catalog2.example.db";
+ masters { 10.53.0.3; };
+};
+
+zone "catalog3.example" {
+ type slave;
+ file "catalog3.example.db";
+ masters { 10.53.0.1; };
+};
+
+zone "catalog4.example" {
+ type slave;
+ file "catalog4.example.db";
+ masters { 10.53.0.1; };
+};
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm hmac-md5;
+};
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..f61860d
--- /dev/null
+++ b/bin/tests/system/catz/ns3/dom5.example.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..f61860d
--- /dev/null
+++ b/bin/tests/system/catz/ns3/dom6.example.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..d5ee7c8
--- /dev/null
+++ b/bin/tests/system/catz/ns3/named.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+zone "catalog2.example" {
+ type master;
+ file "catalog2.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+zone "dom5.example" {
+ type master;
+ file "dom5.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ notify explicit;
+};
+
+zone "dom6.example" {
+ type master;
+ file "dom6.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ notify explicit;
+};
diff --git a/bin/tests/system/catz/setup.sh b/bin/tests/system/catz/setup.sh
new file mode 100644
index 0000000..19e11c9
--- /dev/null
+++ b/bin/tests/system/catz/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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 -f ns1/catalog.example.db.in ns1/catalog1.example.db
+cp -f ns1/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
+
+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..01f2bf4
--- /dev/null
+++ b/bin/tests/system/catz/tests.sh
@@ -0,0 +1,1999 @@
+#!/bin/sh -x
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+##########################################################################
+echo_i "Testing adding/removing of domain in catalog zone"
+n=`expr $n + 1`
+echo_i "checking that dom1.example is not served by master ($n)"
+ret=0
+$DIG soa dom1.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom1.example to master via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom1.example.db
+echo "@ IN NS invalid." >> ns1/dom1.example.db
+$RNDCCMD 10.53.0.1 addzone dom1.example '{type master; file "dom1.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom1.example is now served by master ($n)"
+ret=0
+$DIG soa dom1.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom1.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom1.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom1.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom1.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that zone-directory is populated ($n)"
+ret=0
+[ -f "ns2/zonedir/__catz___default_catalog1.example_dom1.example.db" ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom1.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom1.example is not served by slave ($n)"
+ret=0
+$DIG soa dom1.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that zone-directory is emptied ($n)"
+ret=0
+[ -f "ns2/zonedir/__catz___default_catalog1.example_dom1.example.db" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing various simple operations on domains, including using multiple catalog zones and garbage in zone"
+n=`expr $n + 1`
+echo_i "adding domain dom2.example to master 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
+$RNDCCMD 10.53.0.1 addzone dom2.example '{type master; file "dom2.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "adding domain dom4.example to master 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 '{type master; file "dom4.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom4.example' from catalog 'catalog2.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom4.example/IN' from 10.53.0.1#${EXTRAPORT1}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom4.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom4.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+n=`expr $n + 1`
+echo_i "checking that dom3.example is not served by master ($n)"
+ret=0
+$DIG soa dom3.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "adding a domain dom3.example to master 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 '{type master; file "dom3.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom3.example is served by master ($n)"
+ret=0
+$DIG soa dom3.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom2.example' from catalog 'catalog1.example'" > /dev/null &&
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom3.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom2.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null &&
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom3.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom3.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom3.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 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
+ send
+
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example 3600 IN PTR dom4.example.
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing masters suboption and random labels"
+n=`expr $n + 1`
+echo_i "adding dom5.example with a valid masters 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 masters.somerandomlabel.zones.catalog1.example 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom5.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom5.example/IN' from 10.53.0.3#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom5.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom5.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 masters.somerandomlabel.zones.catalog1.example 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom5.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom5.example is no longer served by slave ($n)"
+ret=0
+$DIG soa dom5.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+##########################################################################
+echo_i "Testing masters global option"
+n=`expr $n + 1`
+echo_i "adding dom6.example and a valid global masters 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 masters.catalog1.example 3600 IN A 10.53.0.3
+ update add masters.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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 120
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom6.example/IN' from " > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom6.example is served by slave ($n)"
+try=0
+while test $try -lt 150
+do
+ $DIG soa dom6.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 masters.catalog1.example 3600 IN A 10.53.0.3
+ update delete masters.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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom6.example is no longer served by slave ($n)"
+ret=0
+$DIG soa dom6.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "adding dom6.example and an invalid global masters 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.masters.catalog1.example 3600 IN TXT "tsig_key"
+ update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example 3600 IN PTR dom6.example.
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "error .* while trying to generate config for zone \"dom6.example\"" > /dev/null && {
+
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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.masters.catalog1.example 3600 IN TXT "tsig_key"
+ update delete 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example 3600 IN PTR dom6.example.
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing allow-query and allow-transfer ACLs"
+n=`expr $n + 1`
+echo_i "adding domains dom7.example and dom8.example to master 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 '{type master; file "dom7.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 '{type master; file "dom8.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom7.example is now served by master ($n)"
+ret=0
+$DIG soa dom7.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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.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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom7.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom7.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom7.example is accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG soa dom7.example -b 10.53.0.1 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom7.example is not accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG soa dom7.example -b 10.53.0.2 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom7.example is accessible from 10.53.0.5 ($n)"
+ret=0
+$DIG soa dom7.example -b 10.53.0.5 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+n=`expr $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.catalog1.example 3600 IN APL 1:10.53.0.1/32
+ update add allow-transfer.catalog1.example 3600 IN APL 1:10.53.0.2/32
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG soa dom8.example -b 10.53.0.1 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is not accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG soa dom8.example -b 10.53.0.2 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is not AXFR accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG axfr dom8.example -b 10.53.0.1 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is AXFR accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG axfr dom8.example -b 10.53.0.2 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+n=`expr $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.catalog1.example 3600 IN APL 1:10.53.0.1/32
+ update delete allow-transfer.catalog1.example 3600 IN APL 1:10.53.0.2/32
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+ret=0
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG soa dom8.example -b 10.53.0.1 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG soa dom8.example -b 10.53.0.2 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is AXFR accessible from 10.53.0.1 ($n)"
+ret=0
+$DIG axfr dom8.example -b 10.53.0.1 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom8.example is AXFR accessible from 10.53.0.2 ($n)"
+ret=0
+$DIG axfr dom8.example -b 10.53.0.2 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+##########################################################################
+echo_i "Testing TSIG keys for masters set per-domain"
+n=`expr $n + 1`
+echo_i "adding a domain dom9.example to master 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 '{type master; file "dom9.example.db"; allow-transfer { key tsig_key; }; };' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom9.example is now served by master ($n)"
+ret=0
+$DIG soa dom9.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "adding domain dom9.example to catalog1 zone with a valid masters 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.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN A 10.53.0.1
+ update add label1.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom9.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom9.example is accessible on slave ($n)"
+ret=0
+$DIG soa dom9.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN A 10.53.0.1
+ update delete label1.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom9.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom9.example is no longer accessible on slave ($n)"
+ret=0
+$DIG soa dom9.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "adding domain dom9.example to catalog1 zone with an invalid masters 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.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "error .* while trying to generate config for zone \"dom9.example\"" > /dev/null && {
+
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom9.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing very long domain in catalog"
+n=`expr $n + 1`
+echo_i "checking that this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example is not served by master ($n)"
+ret=0
+$DIG soa this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example to master 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 this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example '{type master; file "dom10.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example is now served by master ($n)"
+ret=0
+$DIG soa this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "Adding domain this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.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 825f48b1ce1b4cf5a041d20255a0c8e98d114858.zones.catalog1.example 3600 IN PTR this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example.
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example is served by slave ($n)"
+ret=0
+$DIG soa this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that zone-directory is populated with a hashed filename ($n)"
+ret=0
+[ -f "ns2/zonedir/__catz__4d70696f2335687069467f11f5d5378c480383f97782e553fb2d04a7bb2a23ed.db" ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "removing domain this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.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 825f48b1ce1b4cf5a041d20255a0c8e98d114858.zones.catalog1.example
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example is not served by slave ($n)"
+ret=0
+$DIG soa this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that zone-directory is emptied ($n)"
+ret=0
+[ -f "ns2/zonedir/__catz__4d70696f2335687069467f11f5d5378c480383f97782e553fb2d04a7bb2a23ed.db" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing adding a domain and a subdomain of it"
+n=`expr $n + 1`
+echo_i "checking that dom11.example is not served by master ($n)"
+ret=0
+$DIG soa dom11.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom11.example to master 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 '{type master; file "dom11.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom11.example is now served by master ($n)"
+ret=0
+$DIG soa dom11.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom11.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom11.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom11.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom11.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that subdomain.of.dom11.example is not served by master ($n)"
+ret=0
+$DIG soa subdomain.of.dom11.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain subdomain.of.dom11.example to master 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 '{type master; file "subdomain.of.dom11.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that subdomain.of.dom11.example is now served by master ($n)"
+ret=0
+$DIG soa subdomain.of.dom11.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'subdomain.of.dom11.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'subdomain.of.dom11.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that subdomain.of.dom11.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa subdomain.of.dom11.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom11.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom11.example is not served by slave ($n)"
+ret=0
+$DIG soa dom11.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that subdomain.of.dom11.example is still served by slave ($n)"
+ret=0
+$DIG soa subdomain.of.dom11.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'subdomain.of.dom11.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that subdomain.of.dom11.example is not served by slave ($n)"
+ret=0
+$DIG soa subdomain.of.dom11.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+##########################################################################
+echo_i "Testing adding a catalog zone at runtime with rndc reconfig"
+n=`expr $n + 1`
+echo_i "checking that dom12.example is not served by master ($n)"
+ret=0
+$DIG soa dom12.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom12.example to master 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 '{type master; file "dom12.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom12.example is now served by master ($n)"
+ret=0
+$DIG soa dom12.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom12.example is not served by slave ($n)"
+ret=0
+$DIG soa dom12.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+n=`expr $n + 1`
+echo_i "reconfiguring slave - adding catalog4 catalog zone ($n)"
+ret=0
+cat ns2/named.conf.in |sed -e "s/^#T1//g" > ns2/named.conf.tmp
+copy_setports ns2/named.conf.tmp ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom12.example' from catalog 'catalog4.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom12.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom7.example is still served by slave after reconfiguration ($n)"
+ret=0
+$DIG soa dom7.example -b 10.53.0.1 @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "checking that dom12.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom12.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "reconfiguring slave - removing catalog4 catalog zone, adding non-existent catalog5 catalog zone ($n)"
+ret=0
+cat ns2/named.conf.in | sed -e "s/^#T2//" > ns2/named.conf.tmp
+copy_setports ns2/named.conf.tmp ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "reconfiguring slave - removing non-existent catalog5 catalog zone ($n)"
+ret=0
+copy_setports ns2/named.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom12.example is not served by slave ($n)"
+ret=0
+$DIG soa dom12.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing having a zone in two different catalogs"
+n=`expr $n + 1`
+echo_i "checking that dom13.example is not served by master ($n)"
+ret=0
+$DIG soa dom13.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom13.example to master 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 '{type master; file "dom13.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom13.example is now served by master ns1 ($n)"
+ret=0
+$DIG soa dom13.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom13.example to master 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 master; file "dom13.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom13.example is now served by master ns3 ($n)"
+ret=0
+$DIG soa dom13.example @10.53.0.3 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "Adding domain dom13.example to catalog1 zone with ns1 as master ($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 masters.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example 3600 IN A 10.53.0.1
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom13.example' from catalog 'catalog1.example'" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret = 0 ]; then
+ ret=1
+ try=0
+ while test $try -lt 45
+ do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom13.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+ done
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "checking that dom13.example is served by slave and that it's the one from ns1 ($n)"
+ret=0
+$DIG a dom13.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding domain dom13.example to catalog2 zone with ns3 as master ($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 masters.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom13.example is served by slave and that it's still the one from ns1 ($n)"
+ret=0
+$DIG a dom13.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 masters.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom13.example is served by slave and that it's still the one from ns1 ($n)"
+ret=0
+$DIG a dom13.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 masters.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example 3600 IN A 10.53.0.2
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom13.example is no longer served by slave ($n)"
+ret=0
+$DIG a dom13.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing having a regular zone and a zone in catalog zone of the same name"
+n=`expr $n + 1`
+echo_i "checking that dom14.example is not served by master ($n)"
+ret=0
+$DIG soa dom14.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom14.example to master 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 '{type master; file "dom14.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom14.example is now served by master ns1 ($n)"
+ret=0
+$DIG soa dom14.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom14.example to master 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 master; file "dom14.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom14.example is now served by master ns3 ($n)"
+ret=0
+$DIG soa dom14.example @10.53.0.3 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "Adding domain dom14.example with rndc with ns1 as master ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone dom14.example '{type slave; masters {10.53.0.1;};};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom14.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $n + 1`
+echo_i "checking that dom14.example is served by slave and that it's the one from ns1 ($n)"
+ret=0
+$DIG a dom14.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding domain dom14.example to catalog2 zone with ns3 as master ($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 masters.45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom14.example is served by slave and that it's still the one from ns1 ($n)"
+ret=0
+$DIG a dom14.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 masters.45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom14.example is served by slave and that it's still the one from ns1 ($n)"
+ret=0
+$DIG a dom14.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+##########################################################################
+echo_i "Testing changing label for a member zone"
+n=`expr $n + 1`
+echo_i "checking that dom15.example is not served by master ($n)"
+ret=0
+$DIG soa dom15.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Adding a domain dom15.example to master 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 '{type master; file "dom15.example.db";};' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom15.example is now served by master ns1 ($n)"
+ret=0
+$DIG soa dom15.example @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking that dom15.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom15.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "waiting for slave to sync up ($n)"
+ret=1
+try=0
+while test $try -lt 45
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns2/named.run | grep "catz: update_from_db: new zone merged" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that dom15.example is served by slave ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG soa dom15.example @10.53.0.2 -p ${PORT} > dig.out.test$n
+ ret=0
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/chain/README b/bin/tests/system/chain/README
new file mode 100644
index 0000000..f51c123
--- /dev/null
+++ b/bin/tests/system/chain/README
@@ -0,0 +1,15 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..cdbfc84
--- /dev/null
+++ b/bin/tests/system/chain/ans3/ans.pl
@@ -0,0 +1,101 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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";
+ } 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..a419c61
--- /dev/null
+++ b/bin/tests/system/chain/ans4/README.anspy
@@ -0,0 +1,17 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..2dd7def
--- /dev/null
+++ b/bin/tests/system/chain/ans4/ans.py
@@ -0,0 +1,347 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+############################################################################
+# 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 origninal
+# 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..265123f
--- /dev/null
+++ b/bin/tests/system/chain/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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/example.db.signed
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..5815c3c
--- /dev/null
+++ b/bin/tests/system/chain/ns1/named.conf.in
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-enable yes;
+};
+
+zone "." { type master; 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..bc70f8c
--- /dev/null
+++ b/bin/tests/system/chain/ns1/root.db
@@ -0,0 +1,45 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+
+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..5f29f86
--- /dev/null
+++ b/bin/tests/system/chain/ns2/example.db
@@ -0,0 +1,67 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..60568dd
--- /dev/null
+++ b/bin/tests/system/chain/ns2/generic.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 86400 SOA ns2.nil. hostmaster.ns2.nil. 0 1 1 1 1
+@ 86400 NS ns2.nil.
+ns2 86400 A 10.53.0.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
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..519bfb3
--- /dev/null
+++ b/bin/tests/system/chain/ns2/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+};
+
+zone "example" {
+ type master;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+zone "sub2.example" {
+ type master;
+ file "sub.db";
+};
+
+zone "signed-sub2.example" {
+ type master;
+ file "sub.db";
+};
+
+zone "domain0.nil" { type master; file "generic.db"; };
+zone "domain1.nil" { type master; file "generic.db"; };
+zone "domain2.nil" { type master; file "generic.db"; };
+zone "domain3.nil" { type master; file "generic.db"; };
+zone "domain4.nil" { type master; file "generic.db"; };
+zone "domain5.nil" { type master; file "generic.db"; };
+zone "domain6.nil" { type master; file "generic.db"; };
+zone "domain7.nil" { type master; file "generic.db"; };
+zone "domain8.nil" { type master; file "generic.db"; };
+zone "domain9.nil" { type master; 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..11b87ad
--- /dev/null
+++ b/bin/tests/system/chain/ns2/sign.sh
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.
+zonefile=example.db
+
+ksk=`$KEYGEN -q -a RSASHA256 -b 2048 -fk -r $RANDFILE $zone`
+zsk=`$KEYGEN -q -a RSASHA256 -b 1024 -r $RANDFILE $zone`
+$SIGNER -S -r $RANDFILE -o $zone example.db > /dev/null 2>&1
diff --git a/bin/tests/system/chain/ns2/sub.db b/bin/tests/system/chain/ns2/sub.db
new file mode 100644
index 0000000..5e65fdf
--- /dev/null
+++ b/bin/tests/system/chain/ns2/sub.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/ns5/named.conf.in b/bin/tests/system/chain/ns5/named.conf.in
new file mode 100644
index 0000000..d6813b6
--- /dev/null
+++ b/bin/tests/system/chain/ns5/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "sub5.example" {
+ type master;
+ file "sub.db";
+};
+
+zone "signed-sub5.example" {
+ type master;
+ 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..9ddb431
--- /dev/null
+++ b/bin/tests/system/chain/ns5/sub.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c314922
--- /dev/null
+++ b/bin/tests/system/chain/ns7/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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 hmac-sha256;
+};
+
+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..ab755ba
--- /dev/null
+++ b/bin/tests/system/chain/ns7/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/chain/prereq.sh
new file mode 100644
index 0000000..f3f1939
--- /dev/null
+++ b/bin/tests/system/chain/prereq.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL ../testcrypto.sh || exit 255
+
+if test -n "$PYTHON"
+then
+ if $PYTHON -c "import dns" 2> /dev/null
+ then
+ :
+ else
+ echo_i "This test requires the dnspython module." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires Python and the dnspython module." >&2
+ exit 1
+fi
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION >= 0.69 && $Net::DNS::VERSION <= 0.74);' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS versions 0.69 to 0.74 have bugs that cause this test to fail: please update." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires the perl Net::DNS library." >&2
+ exit 1
+fi
+if $PERL -e 'use Net::DNS::Nameserver;' 2>/dev/null
+then
+ :
+else
+ echo_i "This test requires the Net::DNS::Nameserver library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/chain/setup.sh b/bin/tests/system/chain/setup.sh
new file mode 100644
index 0000000..c2b0d69
--- /dev/null
+++ b/bin/tests/system/chain/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..e7ad91e
--- /dev/null
+++ b/bin/tests/system/chain/tests.sh
@@ -0,0 +1,269 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+SEND="$PERL $SYSTEMTESTTOP/send.pl 10.53.0.4 ${EXTRAPORT1}"
+status=0
+n=0
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking short DNAME from recursive ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking long DNAME from recursive ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking (too) long DNAME from recursive with cached DNAME ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking (too) long DNAME from recursive without cached DNAME ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME to DNAME from recursive"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking DNAME is returned with synthesized CNAME before DNAME ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking DNAME is returned with CNAME to synthesized CNAME before DNAME ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME loops are detected ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME to external delegated zones is handled ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME to internal delegated zones is handled ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME to signed external delgation is handled ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME to signed internal delgation is handled ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME chains in various orders ($n)"
+ret=0
+echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|1,1,2,2,3,4,s4,s3,s1" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|2,1,3,4,s3,s1,s2,s4" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | $SEND
+$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" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|4,3,3,3,s1,s1,1,3,4" | $SEND
+$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=`expr $status + $ret`
+
+n=`expr $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" | $SEND
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking DNAME chains in various orders ($n)"
+ret=0
+$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" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "dname,dname|2,3,s1,s2,s3,s4,1" | $SEND
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking external CNAME/DNAME chains in various orders ($n)"
+ret=0
+echo "xname,dname|1,2,3,4,s1,s2,s3,s4" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "xname,dname|s2,2,s1,1,4,s4,3" | $SEND
+$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 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "xname,dname|s2,2,2,2" | $SEND
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking explicit DNAME query ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking DNAME via ANY query ($n)"
+ret=0
+$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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkconf/altdb.conf b/bin/tests/system/checkconf/altdb.conf
new file mode 100644
index 0000000..0ee9680
--- /dev/null
+++ b/bin/tests/system/checkconf/altdb.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view override_bind chaos {
+ zone "version.bind" chaos {
+ type master;
+ 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..8633197
--- /dev/null
+++ b/bin/tests/system/checkconf/altdlz.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dlz external {
+ database "dlopen driver.so";
+ search no;
+};
+
+zone "example.com" {
+ type master;
+ dlz external;
+};
+
+zone "." {
+ type redirect;
+ dlz external;
+};
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..bf27dab
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-also-notify.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Missing master in also-notify clause.
+ */
+
+zone dummy {
+ type master;
+ file "xxxx";
+ also-notify { xxxx; };
+};
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..429a214
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-catz-zone.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ catalog-zones {
+ zone "nonexistent";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-dnssec.conf b/bin/tests/system/checkconf/bad-dnssec.conf
new file mode 100644
index 0000000..9db164e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dnssec.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone not-inline {
+ type slave;
+ masters { 127.0.0.1; };
+ inline-signing no;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+ dnssec-loadkeys-interval 10;
+
+};
+
+zone inline {
+ type slave;
+ masters { 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-hint.conf b/bin/tests/system/checkconf/bad-hint.conf
new file mode 100644
index 0000000..a99ddba
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-hint.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..dfde124
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-in-view-dup.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view a {
+ zone x { type master; file "x"; };
+};
+
+view b {
+ zone x { type master; file "x"; };
+ zone x { in-view a; };
+};
diff --git a/bin/tests/system/checkconf/bad-inline-slave.conf b/bin/tests/system/checkconf/bad-inline-slave.conf
new file mode 100644
index 0000000..ff283b6
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-inline-slave.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+ /*
+ * An inline-signing slave should be forced to have a file option
+ */
+
+ zone "." {
+ type slave;
+ inline-signing yes;
+ masters { 10.53.0.1; };
+ }; \ No newline at end of file
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..c2c8929
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-keep-response-order.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ keep-response-order {
+ does_not_exist;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-lifetime.conf b/bin/tests/system/checkconf/bad-lifetime.conf
new file mode 100644
index 0000000..b5926f0
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lifetime.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..17d2ac5
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..99540ca
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..e5e50f7
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..252ab36
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize unlimited;
+};
diff --git a/bin/tests/system/checkconf/bad-many.conf b/bin/tests/system/checkconf/bad-many.conf
new file mode 100644
index 0000000..27f7e9b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-many.conf
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ avoid-v4-udp-ports { 100; }
+ avoid-v6-udp-ports { 100; };
+ blackhole { 10.0.0.0/8; };
+ coresize 1G;
+ datasize 100M;
+ deallocate-on-exit yes;
+ directory ".";
+ dump-file "named_dumpdb";
+ fake-iquery yes;
+ files 1000;
+ has-old-clients no;
+ heartbeat-interval 30;
+ host-statistics yes;
+ host-statistics-max 100;
+ hostname none;
+ interface-interval 30;
+ keep-response-order { 10.0.0.10/24; };
+ listen-on port 90 { any; };
+ listen-on port 100 { 127.0.0.1; };
+ listen-on-v6 port 53 { none; };
+ match-mapped-addresses yes;
+ memstatistics-file "named.memstats";
+ multiple-cnames no;
+ named-xfer "this is no longer needed";
+ pid-file none;
+ port 5300;
+ querylog yes;
+ recursing-file "named.recursing";
+ random-device "/dev/random";
+ recursive-clients 3000;
+ serial-queries 10;
+ serial-query-rate 100;
+ server-id none;
+};
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..2d3913f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-master-request-ixfr.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * request-ixfr clause is not allowed in zone of type master.
+ */
+
+zone dummy {
+ type master;
+ request-ixfr no;
+ file "xxxx";
+};
diff --git a/bin/tests/system/checkconf/bad-maxttlmap.conf b/bin/tests/system/checkconf/bad-maxttlmap.conf
new file mode 100644
index 0000000..f404b3e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxttlmap.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type master;
+ masterfile-format map;
+ file "example.db";
+ max-zone-ttl 3600;
+};
diff --git a/bin/tests/system/checkconf/bad-noddns.conf b/bin/tests/system/checkconf/bad-noddns.conf
new file mode 100644
index 0000000..d4e93dc
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-noddns.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type master;
+ file "example.db";
+ auto-dnssec maintain;
+ allow-update { none; };
+};
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..d5a28c0
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-options-also-notify.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ also-notify { missing; };
+};
+
+zone "example.net" {
+ type slave;
+ masters { 192.168.1.1; };
+};
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..b344a0f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-acl.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..6a60a8b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..bea9639
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..b94d8db
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..4378e71
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..ed05f57
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..893640e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..8e2f407
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..585e90e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..21f528c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..784f529
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..c616295
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-slip.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..5a0bcdb
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-window.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ window 3601; // greater than default of 3600
+ };
+};
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..120c8e4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rpz-zone.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..38d244a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedwritable1.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone a {
+ type master;
+ file "shared.db";
+};
+zone b {
+ type slave;
+ file "shared.db";
+ masters { 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..31c77c4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedwritable2.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone a {
+ type slave;
+ file "shared.db";
+ masters { 1.2.3.4; };
+};
+zone b {
+ type slave;
+ file "shared.db";
+ masters { 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..3782991
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedzone1.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "first" {
+ match-clients {
+ "none";
+ };
+ zone "clone" {
+ type master;
+ file "xxx";
+ };
+};
+view "second" {
+ match-clients {
+ "any";
+ };
+ zone "clone" {
+ in-view "first";
+ type slave;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedzone2.conf b/bin/tests/system/checkconf/bad-sharedzone2.conf
new file mode 100644
index 0000000..91b0472
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedzone2.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "first" {
+ match-clients {
+ "none";
+ };
+ zone "clone" {
+ type master;
+ file "xxx";
+ };
+};
+view "second" {
+ match-clients {
+ "any";
+ };
+ zone "clone" {
+ in-view "first";
+ forward only;
+ forwarders { 10.0.0.100; };
+ type slave;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedzone3.conf b/bin/tests/system/checkconf/bad-sharedzone3.conf
new file mode 100644
index 0000000..e174ab1
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedzone3.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view first {
+ zone shared.example {
+ in-view second;
+ };
+};
+
+view second {
+ zone shared.example {
+ type master;
+ file "shared.example.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-tsig.conf b/bin/tests/system/checkconf/bad-tsig.conf
new file mode 100644
index 0000000..21be03e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-tsig.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* Bad secret */
+key "badtsig" {
+ algorithm hmac-md5;
+ secret "jEdD+BPKg==";
+};
+
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..13e21db
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy1.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..8c9a4ad
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy10.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..6f81c31
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy11.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..c636f1b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy12.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..4fb16f2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy13.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..1498180
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy14.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..7591b0b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy15.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant a-key-name wildcard TXT;
+ };
+};
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..987e096
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy2.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant * selfsub TXT;
+ };
+};
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..ff0811f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy3.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..396f69b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy4.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..718dad5
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy5.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..992e384
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy6.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..3bd2185
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy7.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..c88b0e2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy8.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..382f899
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy9.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant * 6to4-self TXT;
+ };
+};
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..418fa47
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-view-also-notify.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view example {
+ also-notify { missing; };
+ zone "example.net" {
+ type slave;
+ masters { 192.168.1.1; };
+ };
+};
diff --git a/bin/tests/system/checkconf/check-dlv-ksk-key.conf b/bin/tests/system/checkconf/check-dlv-ksk-key.conf
new file mode 100644
index 0000000..2322e7d
--- /dev/null
+++ b/bin/tests/system/checkconf/check-dlv-ksk-key.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trusted-keys {
+ dlv.isc.org 257 3 5 "BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWE
+ n4MxDCE1+lLy2brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8
+ +jAGl2FZLK8t+1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ
+ 2kJb56dhgMde5ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnG
+ xPPEmHAte/URkY62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mR
+ x/vwwMCTgNboMQKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWL
+ KjHzpT59k/VStTDN0YUuWrBNh";
+};
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..684e8c6
--- /dev/null
+++ b/bin/tests/system/checkconf/check-dup-records-fail.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-dup-records" {
+ type master;
+ 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..3d148e5
--- /dev/null
+++ b/bin/tests/system/checkconf/check-dup-records.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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-mx-cname-fail.conf b/bin/tests/system/checkconf/check-mx-cname-fail.conf
new file mode 100644
index 0000000..71292c8
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx-cname-fail.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-mx-cname" {
+ type master;
+ 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..321c38e
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx-cname.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2eb8ad6
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx-fail.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-mx" {
+ type master;
+ 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..28331b4
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..9c0ac26
--- /dev/null
+++ b/bin/tests/system/checkconf/check-names-fail.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-names" {
+ type master;
+ 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..7763647
--- /dev/null
+++ b/bin/tests/system/checkconf/check-names.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..025564c
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-ksk-2010.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trusted-keys {
+ # 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.
+ . 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..ebefd9c
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-ksk-2017.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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-root-ksk-both.conf b/bin/tests/system/checkconf/check-root-ksk-both.conf
new file mode 100644
index 0000000..aebf7f5
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-ksk-both.conf
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trusted-keys {
+ # 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.
+ . 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.
+ . 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..e846307
--- /dev/null
+++ b/bin/tests/system/checkconf/check-srv-cname-fail.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-srv-cname" {
+ type master;
+ 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..8bc71bd
--- /dev/null
+++ b/bin/tests/system/checkconf/check-srv-cname.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/clean.sh b/bin/tests/system/checkconf/clean.sh
new file mode 100644
index 0000000..ed02f98
--- /dev/null
+++ b/bin/tests/system/checkconf/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f good.conf.in good.conf.out badzero.conf *.out
+rm -rf test.keydir
+rm -f checkconf.out*
+rm -f ns*/named.lock
diff --git a/bin/tests/system/checkconf/dlz-bad.conf b/bin/tests/system/checkconf/dlz-bad.conf
new file mode 100644
index 0000000..2ba89b1
--- /dev/null
+++ b/bin/tests/system/checkconf/dlz-bad.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dlz one {
+ database "one";
+};
+
+dlz two {
+ database "two";
+ search no;
+};
+
+zone master {
+ type master;
+ 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..176711f
--- /dev/null
+++ b/bin/tests/system/checkconf/dnssec.1
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-enable no;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/checkconf/dnssec.2 b/bin/tests/system/checkconf/dnssec.2
new file mode 100644
index 0000000..64db848
--- /dev/null
+++ b/bin/tests/system/checkconf/dnssec.2
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-enable no;
+};
+
+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.3 b/bin/tests/system/checkconf/dnssec.3
new file mode 100644
index 0000000..fbb5882
--- /dev/null
+++ b/bin/tests/system/checkconf/dnssec.3
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-validation no;
+};
+
+view view1 {
+ match-clients { any; };
+ dnssec-enable no;
+};
+
+view view2 {
+ match-clients { none; };
+ dnssec-enable yes;
+};
+
+view view3 {
+ match-clients { none; };
+ dnssec-validation auto;
+};
+
+view view4 {
+ match-clients { none; };
+ dnssec-lookaside no;
+};
+
+view view5 {
+ match-clients { none; };
+ auto-dnssec off;
+};
diff --git a/bin/tests/system/checkconf/good-acl.conf b/bin/tests/system/checkconf/good-acl.conf
new file mode 100644
index 0000000..5321899
--- /dev/null
+++ b/bin/tests/system/checkconf/good-acl.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl a {
+ { "none"; };
+ { !19.0.0.0/8; };
+};
+
+options {
+ allow-query { a; };
+};
diff --git a/bin/tests/system/checkconf/good-class.conf b/bin/tests/system/checkconf/good-class.conf
new file mode 100644
index 0000000..1839fe2
--- /dev/null
+++ b/bin/tests/system/checkconf/good-class.conf
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" class00 { };
diff --git a/bin/tests/system/checkconf/good-dlv-dlv.example.com.conf b/bin/tests/system/checkconf/good-dlv-dlv.example.com.conf
new file mode 100644
index 0000000..fd242bc
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dlv-dlv.example.com.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-lookaside . trust-anchor dlv.example.com;
+};
diff --git a/bin/tests/system/checkconf/good-lmdb-mapsize-largest.conf b/bin/tests/system/checkconf/good-lmdb-mapsize-largest.conf
new file mode 100644
index 0000000..a01fbc4
--- /dev/null
+++ b/bin/tests/system/checkconf/good-lmdb-mapsize-largest.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize 1024G;
+};
diff --git a/bin/tests/system/checkconf/good-lmdb-mapsize-smallest.conf b/bin/tests/system/checkconf/good-lmdb-mapsize-smallest.conf
new file mode 100644
index 0000000..797395f
--- /dev/null
+++ b/bin/tests/system/checkconf/good-lmdb-mapsize-smallest.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize 1M;
+};
diff --git a/bin/tests/system/checkconf/good-nested.conf b/bin/tests/system/checkconf/good-nested.conf
new file mode 100644
index 0000000..4523b40
--- /dev/null
+++ b/bin/tests/system/checkconf/good-nested.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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-options-also-notify.conf b/bin/tests/system/checkconf/good-options-also-notify.conf
new file mode 100644
index 0000000..fcb0163
--- /dev/null
+++ b/bin/tests/system/checkconf/good-options-also-notify.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ also-notify { missing; };
+};
+
+zone "example.net" {
+ type slave;
+ notify no;
+ masters { 192.168.1.1; };
+};
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..68e511f
--- /dev/null
+++ b/bin/tests/system/checkconf/good-response-dot.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com." {
+ type master;
+ file "example.com.zone";
+};
+
+options {
+ response-policy {
+ zone "example.com." policy given;
+ };
+};
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..8d34518
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy1.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..60bea6b
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy10.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..ba6f396
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy11.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..09bd926
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy12.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant * 6to4-self . TXT;
+ };
+};
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..5b453e7
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy2.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..3f4cef2
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy3.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..a3ef534
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy4.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..1f70f0c
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy5.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..ac43c48
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy6.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..96431a3
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy7.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..cd33559
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy8.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..dcb5b46
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy9.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type master;
+ 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..b8a46e9
--- /dev/null
+++ b/bin/tests/system/checkconf/good-view-also-notify.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view example {
+ also-notify { missing; };
+ zone "example.net" {
+ type slave;
+ notify no;
+ masters { 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..9ab35b3
--- /dev/null
+++ b/bin/tests/system/checkconf/good.conf
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is just a random selection of configuration options.
+ */
+
+/* cut here */
+options {
+ avoid-v4-udp-ports {
+ 100;
+ };
+ avoid-v6-udp-ports {
+ 100;
+ };
+ blackhole {
+ 10.0.0.0/8;
+ };
+ coresize 1073741824;
+ datasize 104857600;
+ deallocate-on-exit yes;
+ directory ".";
+ dscp 41;
+ dump-file "named_dumpdb";
+ fake-iquery yes;
+ files 1000;
+ has-old-clients no;
+ heartbeat-interval 30;
+ host-statistics yes;
+ host-statistics-max 100;
+ 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";
+ multiple-cnames no;
+ named-xfer "this is no longer needed";
+ pid-file none;
+ port 5300;
+ querylog yes;
+ random-device "/dev/random";
+ recursing-file "named.recursing";
+ recursive-clients 3000;
+ serial-queries 10;
+ serial-query-rate 100;
+ server-id none;
+ max-cache-size 20000000000000;
+ nta-lifetime 604800;
+ nta-recheck 604800;
+ transfer-source 0.0.0.0 dscp 63;
+ zone-statistics none;
+};
+view "first" {
+ match-clients {
+ "none";
+ };
+ zone "example1" {
+ type master;
+ file "xxx";
+ update-policy local;
+ notify-source 10.10.10.10 port 53 dscp 55;
+ };
+ zone "clone" {
+ type master;
+ file "yyy";
+ };
+ dnssec-validation auto;
+ zone-statistics terse;
+};
+view "second" {
+ match-clients {
+ "any";
+ };
+ zone "example1" {
+ type master;
+ file "zzz";
+ update-policy local;
+ zone-statistics yes;
+ };
+ zone "example2" {
+ type static-stub;
+ forward only;
+ forwarders {
+ 10.53.0.4;
+ };
+ zone-statistics no;
+ };
+ zone "clone" {
+ in-view "first";
+ };
+ zone "." {
+ type redirect;
+ masters {
+ 1.2.3.4;
+ };
+ };
+ dnssec-lookaside "." trust-anchor "example.org.";
+ 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 master;
+ file "file";
+ auto-dnssec maintain;
+ };
+ allow-update {
+ "any";
+ };
+};
+view "chaos" chaos {
+ zone "hostname.bind" chaos {
+ type master;
+ database "_builtin hostname";
+ };
+};
+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/hint-nofile.conf b/bin/tests/system/checkconf/hint-nofile.conf
new file mode 100644
index 0000000..f0ef89f
--- /dev/null
+++ b/bin/tests/system/checkconf/hint-nofile.conf
@@ -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 http://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..3161c38
--- /dev/null
+++ b/bin/tests/system/checkconf/in-view-good.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view internal {
+ zone shared.example {
+ type master;
+ 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..011bea9
--- /dev/null
+++ b/bin/tests/system/checkconf/inline-bad.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl "transferees" {};
+masters "stealthMasters" {127.0.0.1;};
+masters "publicSlaves" {127.0.0.1;};
+zone "example.net" {
+ type slave;
+ key-directory "/var/lib/bind/example.net";
+ auto-dnssec maintain;
+ inline-signing yes;
+ masters { stealthMasters; };
+ notify explicit;
+ also-notify { publicSlaves; };
+ 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..8e3115b
--- /dev/null
+++ b/bin/tests/system/checkconf/inline-good.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl "transferees" {};
+masters "stealthMasters" {127.0.0.1;};
+masters "publicSlaves" {127.0.0.1;};
+zone "example.net" {
+ type slave;
+ file "/var/cache/bind/example.net.db";
+ key-directory "/var/lib/bind/example.net";
+ auto-dnssec maintain;
+ inline-signing yes;
+ masters { stealthMasters; };
+ notify explicit;
+ also-notify { publicSlaves; };
+ 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..c441fa9
--- /dev/null
+++ b/bin/tests/system/checkconf/inline-no.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl "transferees" {};
+masters "stealthMasters" {127.0.0.1;};
+masters "publicSlaves" {127.0.0.1;};
+zone "example.net" {
+ type slave;
+ key-directory "/var/lib/bind/example.net";
+ auto-dnssec maintain;
+ inline-signing no;
+ masters { stealthMasters; };
+ notify explicit;
+ also-notify { publicSlaves; };
+ allow-transfer { localhost; transferees; };
+};
+
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..ff9dc8f
--- /dev/null
+++ b/bin/tests/system/checkconf/max-cache-size-good.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..074bc2c
--- /dev/null
+++ b/bin/tests/system/checkconf/max-ttl.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ max-zone-ttl 600;
+};
+
+zone "maxttl1.example" {
+ type master;
+ file "maxttl-bad.db";
+};
+
+zone "maxttl2.example" {
+ type master;
+ file "maxttl-bad.db";
+ max-zone-ttl 300;
+};
+
+zone "maxttl3.example" {
+ type master;
+ 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..ac4ca65
--- /dev/null
+++ b/bin/tests/system/checkconf/maxttl-bad.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ max-zone-ttl 8000w;
+};
+
+zone "maxttl.example" {
+ type master;
+ 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..9c8aa7e
--- /dev/null
+++ b/bin/tests/system/checkconf/maxttl-bad.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..21536b4
--- /dev/null
+++ b/bin/tests/system/checkconf/maxttl.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..60c4f15
--- /dev/null
+++ b/bin/tests/system/checkconf/notify.conf
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ notify master-only;
+
+ # also-notify inconsistent with master-only notify option
+ zone "slave" {
+ type slave;
+ masters { 1.2.3.4; };
+ also-notify { 5.6.7.8; };
+ };
+
+ # OK
+ zone "master" {
+ type master;
+ file "filename";
+ also-notify { 5.6.7.8; };
+ };
+};
+
+view two {
+ notify no;
+
+ # also-notify inconsistent with notify option at the view level
+ zone "slave" {
+ type slave;
+ masters { 1.2.3.4; };
+ also-notify { 5.6.7.8; };
+ };
+
+ # OK
+ zone "master" {
+ type master;
+ file "filename";
+ notify yes;
+ also-notify { 5.6.7.8; };
+ };
+};
+
+view three {
+ # also-notify inconsistent with notify option at the zone level
+ zone "slave" {
+ type slave;
+ masters { 1.2.3.4; };
+ notify no;
+ also-notify { 5.6.7.8; };
+ };
+
+ # OK
+ zone "master" {
+ type master;
+ file "filename";
+ also-notify { 5.6.7.8; };
+ };
+};
+
+view four {
+ also-notify { 5.6.7.8; };
+
+ # OK
+ zone "slave" {
+ type slave;
+ masters { 1.2.3.4; };
+ notify master-only;
+ };
+
+ # OK
+ zone "master" {
+ type master;
+ 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..e02097f
--- /dev/null
+++ b/bin/tests/system/checkconf/portrange-good.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..a7f94d9
--- /dev/null
+++ b/bin/tests/system/checkconf/range.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 999999;
+ dscp 222;
+ listen-on port 100 dscp 444 {
+ 127.0.0.1/32;
+ };
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/checkconf/shared.example.db b/bin/tests/system/checkconf/shared.example.db
new file mode 100644
index 0000000..7b40db9
--- /dev/null
+++ b/bin/tests/system/checkconf/shared.example.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..18c8bb2
--- /dev/null
+++ b/bin/tests/system/checkconf/tests.sh
@@ -0,0 +1,394 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf handles a known good config ($n)"
+ret=0
+$CHECKCONF good.conf > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 | grep -v '^good.conf.in:' > good.conf.out 2>&1 || ret=1
+cmp good.conf.in good.conf.out || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 | grep -v '^good.conf.in:' > good.conf.out 2>&1 || ret=1
+grep 'secret "????????????????"' good.conf.out > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+for bad in bad-*.conf
+do
+ n=`expr $n + 1`
+ echo_i "checking that named-checkconf detects error in $bad ($n)"
+ ret=0
+ $CHECKCONF $bad > checkconf.out 2>&1
+ if [ $? != 1 ]; then ret=1; fi
+ grep "^$bad:[0-9]*: " checkconf.out > /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 > /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 > /dev/null || ret=1
+ ;;
+ bad-update-policy[67].conf|bad-update-policy1[2345].conf)
+ pat="missing name field type '.*' found"
+ grep "$pat" checkconf.out > /dev/null || ret=1
+ ;;
+ esac
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+done
+
+for good in good-*.conf
+do
+ n=`expr $n + 1`
+ echo_i "checking that named-checkconf detects no error in $good ($n)"
+ ret=0
+ $CHECKCONF $good > /dev/null 2>&1
+ if [ $? != 0 ]; then echo_i "failed"; ret=1; fi
+ status=`expr $status + $ret`
+done
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf catches range errors ($n)"
+ret=0
+$CHECKCONF range.conf > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf warns of notify inconsistencies ($n)"
+ret=0
+warnings=`$CHECKCONF notify.conf 2>&1 | grep "'notify' is disabled" | wc -l`
+[ $warnings -eq 3 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking named-checkconf dnssec warnings ($n)"
+ret=0
+$CHECKCONF dnssec.1 2>&1 | grep 'validation yes.*enable no' > /dev/null || ret=1
+$CHECKCONF dnssec.2 2>&1 | grep 'auto-dnssec may only be ' > /dev/null || ret=1
+$CHECKCONF dnssec.2 2>&1 | grep 'validation auto.*enable no' > /dev/null || ret=1
+$CHECKCONF dnssec.2 2>&1 | grep 'validation yes.*enable no' > /dev/null || ret=1
+# this one should have no warnings
+$CHECKCONF dnssec.3 2>&1 | grep '.*' && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 > /dev/null 2>&1
+ [ $? -eq 1 ] || { echo_i "options $field failed" ; ret=1; }
+ cat > badzero.conf << EOF
+view dummy {
+ $field 0;
+};
+EOF
+ $CHECKCONF badzero.conf > /dev/null 2>&1
+ [ $? -eq 1 ] || { echo_i "view $field failed" ; ret=1; }
+ cat > badzero.conf << EOF
+options {
+ $field 0;
+};
+view dummy {
+};
+EOF
+ $CHECKCONF badzero.conf > /dev/null 2>&1
+ [ $? -eq 1 ] || { echo_i "options + view $field failed" ; ret=1; }
+ cat > badzero.conf << EOF
+zone dummy {
+ type slave;
+ masters { 0.0.0.0; };
+ $field 0;
+};
+EOF
+ $CHECKCONF badzero.conf > /dev/null 2>&1
+ [ $? -eq 1 ] || { echo_i "zone $field failed" ; ret=1; }
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking options allowed in inline-signing slaves ($n)"
+ret=0
+l=`$CHECKCONF bad-dnssec.conf 2>&1 | grep "dnssec-dnskey-kskonly.*requires inline" | wc -l`
+[ $l -eq 1 ] || ret=1
+l=`$CHECKCONF bad-dnssec.conf 2>&1 | grep "dnssec-loadkeys-interval.*requires inline" | wc -l`
+[ $l -eq 1 ] || ret=1
+l=`$CHECKCONF bad-dnssec.conf 2>&1 | grep "update-check-ksk.*requires inline" | wc -l`
+[ $l -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check file + inline-signing for slave zones ($n)"
+l=`$CHECKCONF inline-no.conf 2>&1 | grep "missing 'file' entry" | wc -l`
+[ $l -eq 0 ] || ret=1
+l=`$CHECKCONF inline-good.conf 2>&1 | grep "missing 'file' entry" | wc -l`
+[ $l -eq 0 ] || ret=1
+l=`$CHECKCONF inline-bad.conf 2>&1 | grep "missing 'file' entry" | wc -l`
+[ $l -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking named-checkconf DLZ warnings ($n)"
+ret=0
+$CHECKCONF dlz-bad.conf 2>&1 | grep "'dlz' and 'database'" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking for missing key directory warning ($n)"
+ret=0
+rm -rf test.keydir
+l=`$CHECKCONF warn-keydir.conf 2>&1 | grep "'test.keydir' does not exist" | wc -l`
+[ $l -eq 1 ] || ret=1
+touch test.keydir
+l=`$CHECKCONF warn-keydir.conf 2>&1 | grep "'test.keydir' is not a directory" | wc -l`
+[ $l -eq 1 ] || ret=1
+rm -f test.keydir
+mkdir test.keydir
+l=`$CHECKCONF warn-keydir.conf 2>&1 | grep "key-directory" | wc -l`
+[ $l -eq 0 ] || ret=1
+rm -rf test.keydir
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=`expr $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
+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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z catches invalid max-ttl ($n)"
+ret=0
+$CHECKCONF -z max-ttl-bad.conf > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z skips zone check with alternate databases ($n)"
+ret=0
+$CHECKCONF -z altdb.conf > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z skips zone check with DLZ ($n)"
+ret=0
+$CHECKCONF -z altdlz.conf > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z fails on view with ANY class ($n)"
+ret=0
+$CHECKCONF -z view-class-any1.conf > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z fails on view with CLASS255 class ($n)"
+ret=0
+$CHECKCONF -z view-class-any2.conf > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z passes on view with IN class ($n)"
+ret=0
+$CHECKCONF -z view-class-in1.conf > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named-checkconf -z passes on view with CLASS1 class ($n)"
+ret=0
+$CHECKCONF -z view-class-in2.conf > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that named-checkconf -z handles in-view ($n)"
+ret=0
+$CHECKCONF -z in-view-good.conf > checkconf.out7 2>&1 || ret=1
+grep "zone shared.example/IN: loaded serial" < checkconf.out7 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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.out8 2>&1 || ret=1
+grep "max-cache-size 60%;" checkconf.out8 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that 'dnssec-lookaside auto;' generates a warning ($n)"
+ret=0
+$CHECKCONF warn-dlv-auto.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "dnssec-lookaside 'auto' is no longer supported" checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that 'dnssec-lookaside . trust-anchor dlv.isc.org;' generates a warning ($n)"
+ret=0
+$CHECKCONF warn-dlv-dlv.isc.org.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "dlv.isc.org has been shut down" checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that 'dnssec-lookaside . trust-anchor dlv.example.com;' doesn't generates a warning ($n)"
+ret=0
+$CHECKCONF good-dlv-dlv.example.com.conf > checkconf.out$n 2>/dev/null || ret=1
+[ -s checkconf.out$n ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "trusted-key for root from 2010 without updated" checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+echo_i "check that the 2010 ICANN ROOT KSK with the 2017 ICANN ROOT KSK does not 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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+echo_i "check that the 2017 ICANN ROOT KSK alone does not 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 != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+echo_i "check that the dlv.isc.org KSK generates a warning ($n)"
+ret=0
+$CHECKCONF check-dlv-ksk-key.conf > checkconf.out$n 2>/dev/null || ret=1
+[ -s checkconf.out$n ] || ret=1
+grep "trusted-key for dlv.isc.org still present" checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
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..9832ce0
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-any1.conf
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..03f0803
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-any2.conf
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..794f9e0
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-in1.conf
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..c519b1a
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-in2.conf
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" class1 { };
diff --git a/bin/tests/system/checkconf/warn-dlv-auto.conf b/bin/tests/system/checkconf/warn-dlv-auto.conf
new file mode 100644
index 0000000..3ba7342
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-dlv-auto.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-lookaside auto;
+};
diff --git a/bin/tests/system/checkconf/warn-dlv-dlv.isc.org.conf b/bin/tests/system/checkconf/warn-dlv-dlv.isc.org.conf
new file mode 100644
index 0000000..49b11bc
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-dlv-dlv.isc.org.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-lookaside . trust-anchor dlv.isc.org;
+};
diff --git a/bin/tests/system/checkconf/warn-keydir.conf b/bin/tests/system/checkconf/warn-keydir.conf
new file mode 100644
index 0000000..502a4f3
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-keydir.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * key-directory defined but doesn't exist.
+ */
+options {
+ directory ".";
+};
+
+zone dummy {
+ type master;
+ file "xxxx";
+ key-directory "test.keydir";
+};
diff --git a/bin/tests/system/checkds/clean.sh b/bin/tests/system/checkds/clean.sh
new file mode 100644
index 0000000..436f66d
--- /dev/null
+++ b/bin/tests/system/checkds/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id$
+
+rm -f checkds.*
+rm -f ns*/named.lock
diff --git a/bin/tests/system/checkds/dig.bat b/bin/tests/system/checkds/dig.bat
new file mode 100755
index 0000000..bf07a4f
--- /dev/null
+++ b/bin/tests/system/checkds/dig.bat
@@ -0,0 +1,38 @@
+@echo off
+set ext=
+set file=
+
+:loop
+@set arg=%1
+if "%arg%" == "" goto end
+if "%arg:~0,1%" == "+" goto next
+if "%arg%" == "-t" goto next
+if "%arg%" == "ds" goto ds
+if "%arg%" == "DS" goto ds
+if "%arg%" == "dlv" goto dlv
+if "%arg%" == "DLV" goto dlv
+if "%arg%" == "dnskey" goto dnskey
+if "%arg%" == "DNSKEY" goto dnskey
+set file=%arg%
+goto next
+
+:ds
+set ext=ds
+goto next
+
+:dlv
+set ext=dlv
+goto next
+
+:dnskey
+set ext=dnskey
+goto next
+
+:next
+shift
+goto loop
+
+:end
+
+set name=%file%.%ext%.db
+type %name%
diff --git a/bin/tests/system/checkds/dig.pl b/bin/tests/system/checkds/dig.pl
new file mode 100644
index 0000000..51e5713
--- /dev/null
+++ b/bin/tests/system/checkds/dig.pl
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id$
+
+my $arg;
+my $ext;
+my $file;
+
+foreach $arg (@ARGV) {
+ if ($arg =~ /^\+/) {
+ next;
+ }
+ if ($arg =~ /^-t/) {
+ next;
+ }
+ if ($arg =~ /^ds$/i) {
+ $ext = "ds";
+ next;
+ }
+ if ($arg =~ /^dlv$/i) {
+ $ext = "dlv";
+ next;
+ }
+ if ($arg =~ /^dnskey$/i) {
+ $ext = "dnskey";
+ next;
+ }
+ $file = $arg;
+ next;
+}
+
+open F, $file . "." . $ext . ".db" || die $!;
+while (<F>) {
+ print;
+}
+close F;
diff --git a/bin/tests/system/checkds/dig.sh b/bin/tests/system/checkds/dig.sh
new file mode 100755
index 0000000..b7472ea
--- /dev/null
+++ b/bin/tests/system/checkds/dig.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id$
+
+
+while [ "$#" != 0 ]; do
+ case $1 in
+ +*) shift ;;
+ -t) shift ;;
+ DS|ds) ext=ds ; shift ;;
+ DLV|dlv) ext=dlv ; shift ;;
+ DNSKEY|dnskey) ext=dnskey ; shift ;;
+ *) file=$1 ; shift ;;
+ esac
+done
+
+cat ${file}.${ext}.db
diff --git a/bin/tests/system/checkds/missing.example.dlv.example.dlv.db b/bin/tests/system/checkds/missing.example.dlv.example.dlv.db
new file mode 100644
index 0000000..5dd9462
--- /dev/null
+++ b/bin/tests/system/checkds/missing.example.dlv.example.dlv.db
@@ -0,0 +1,2 @@
+missing.example.dlv.example. 3600 IN DLV 12892 5 1 9D4CD60491D372207FA584D2EE460CC51D7FF8A7
+missing.example.dlv.example. 3600 IN DLV 12892 5 2 EF59E5C70BC4153B7DB4C11F9C36B729577DA71474E0A5C9B8875173 6E583200
diff --git a/bin/tests/system/checkds/missing.example.dnskey.db b/bin/tests/system/checkds/missing.example.dnskey.db
new file mode 100644
index 0000000..e372130
--- /dev/null
+++ b/bin/tests/system/checkds/missing.example.dnskey.db
@@ -0,0 +1,3 @@
+missing.example. 3600 IN DNSKEY 257 3 5 AwEAAc6Cz10GXEh5lxA9ujTY/QarTajcUOBwwBYIeldjRsgoouK/UioY FYgxEFL0O5JK6YCRUoGzl3EgLr5GvNyhIp1PZpOpHf7o/4MVOZTGJzm/ sHWP5B+KcYjQOxJiDb433iCmRM4DpHPUUoxw0QbZglzAzl5MfKBoyZud lH59DdT/50bkBg8iVu35EzuW0SYt31k70hxHBSb2wAGWeqxEPKJ1nQiI UcrWNDeem7byrqjPN9wyZhq0XkQ9qbcYxAkRNd8Y7P0FyR1YKJMc6SWZ Ru7muvxqTHgCtJVgxVz4qndCFKdYidiDeKe2/X/z5gf7pyYl3549O8JR tWdNKqutppk=
+missing.example. 3600 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjG rhhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA +u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy 347cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQ zBkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysy LKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/b ByBNsO70aEFTd
+missing.example. 3600 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkds/missing.example.ds.db b/bin/tests/system/checkds/missing.example.ds.db
new file mode 100644
index 0000000..540ec0b
--- /dev/null
+++ b/bin/tests/system/checkds/missing.example.ds.db
@@ -0,0 +1,2 @@
+missing.example. 3600 IN DS 12892 5 2 EF59E5C70BC4153B7DB4C11F9C36B729577DA71474E0A5C9B8875173 6E583200
+missing.example. 3600 IN DS 12892 5 1 9D4CD60491D372207FA584D2EE460CC51D7FF8A7
diff --git a/bin/tests/system/checkds/none.example.dlv.example.dlv.db b/bin/tests/system/checkds/none.example.dlv.example.dlv.db
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/checkds/none.example.dlv.example.dlv.db
diff --git a/bin/tests/system/checkds/none.example.dnskey.db b/bin/tests/system/checkds/none.example.dnskey.db
new file mode 100644
index 0000000..76ae905
--- /dev/null
+++ b/bin/tests/system/checkds/none.example.dnskey.db
@@ -0,0 +1,3 @@
+none.example. 3600 IN DNSKEY 257 3 5 AwEAAc6Cz10GXEh5lxA9ujTY/QarTajcUOBwwBYIeldjRsgoouK/UioY FYgxEFL0O5JK6YCRUoGzl3EgLr5GvNyhIp1PZpOpHf7o/4MVOZTGJzm/ sHWP5B+KcYjQOxJiDb433iCmRM4DpHPUUoxw0QbZglzAzl5MfKBoyZud lH59DdT/50bkBg8iVu35EzuW0SYt31k70hxHBSb2wAGWeqxEPKJ1nQiI UcrWNDeem7byrqjPN9wyZhq0XkQ9qbcYxAkRNd8Y7P0FyR1YKJMc6SWZ Ru7muvxqTHgCtJVgxVz4qndCFKdYidiDeKe2/X/z5gf7pyYl3549O8JR tWdNKqutppk=
+none.example. 3600 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjG rhhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA +u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy 347cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQ zBkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysy LKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/b ByBNsO70aEFTd
+none.example. 3600 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkds/none.example.ds.db b/bin/tests/system/checkds/none.example.ds.db
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/checkds/none.example.ds.db
diff --git a/bin/tests/system/checkds/ok.example.dlv.example.dlv.db b/bin/tests/system/checkds/ok.example.dlv.example.dlv.db
new file mode 100644
index 0000000..5896bcc
--- /dev/null
+++ b/bin/tests/system/checkds/ok.example.dlv.example.dlv.db
@@ -0,0 +1,2 @@
+ok.example.dlv.example. 3600 IN DLV 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
+ok.example.dlv.example. 3600 IN DLV 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
diff --git a/bin/tests/system/checkds/ok.example.dnskey.db b/bin/tests/system/checkds/ok.example.dnskey.db
new file mode 100644
index 0000000..c767c8f
--- /dev/null
+++ b/bin/tests/system/checkds/ok.example.dnskey.db
@@ -0,0 +1,2 @@
+ok.example. 625 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjGr hhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA+ u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy3 47cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQz Bkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysyL KOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/bB yBNsO70aEFTd
+ok.example. 625 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkds/ok.example.ds.db b/bin/tests/system/checkds/ok.example.ds.db
new file mode 100644
index 0000000..96b159b
--- /dev/null
+++ b/bin/tests/system/checkds/ok.example.ds.db
@@ -0,0 +1,2 @@
+ok.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ok.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
diff --git a/bin/tests/system/checkds/setup.sh b/bin/tests/system/checkds/setup.sh
new file mode 100644
index 0000000..1405375
--- /dev/null
+++ b/bin/tests/system/checkds/setup.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
diff --git a/bin/tests/system/checkds/tests.sh b/bin/tests/system/checkds/tests.sh
new file mode 100644
index 0000000..141d83b
--- /dev/null
+++ b/bin/tests/system/checkds/tests.sh
@@ -0,0 +1,179 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if [ "$CYGWIN" ]; then
+ DIG=".\dig.bat"
+ WINDSFROMKEY=`cygpath -w $DSFROMKEY`
+ CHECKDS="$CHECKDS -d $DIG -D $WINDSFROMKEY"
+else
+ DIG="./dig.sh"
+ CHECKDS="$CHECKDS -d $DIG -D $DSFROMKEY"
+fi
+chmod +x $DIG
+
+status=0
+n=1
+
+echo_i "checking for correct DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS ok.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for correct DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f ok.example.dnskey.db ok.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for correct DLV, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS -l dlv.example ok.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for correct DLV, obtaining key from file ($n)"
+ret=0
+$CHECKDS -l dlv.example -f ok.example.dnskey.db ok.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for incorrect DS, lowronging up key via 'dig' ($n)"
+ret=0
+$CHECKDS wrong.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for incorrect DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f wrong.example.dnskey.db wrong.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for incorrect DLV, lowronging up key via 'dig' ($n)"
+ret=0
+$CHECKDS -l dlv.example wrong.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for incorrect DLV, obtaining key from file ($n)"
+ret=0
+$CHECKDS -l dlv.example -f wrong.example.dnskey.db wrong.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+
+echo_i "checking for partially missing DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS missing.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for partially missing DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for partially missing DLV, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS -l dlv.example missing.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for partially missing DLV, obtaining key from file ($n)"
+ret=0
+$CHECKDS -l dlv.example -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for entirely missing DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS none.example > checkds.out.$n 2>&1 && ret=1
+grep 'No DS' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for entirely missing DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f none.example.dnskey.db none.example > checkds.out.$n 2>&1 && ret=1
+grep 'No DS' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for entirely missing DLV, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS -l dlv.example none.example > checkds.out.$n 2>&1 && ret=1
+grep 'No DLV' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for entirely missing DLV, obtaining key from file ($n)"
+ret=0
+$CHECKDS -l dlv.example -f none.example.dnskey.db none.example > checkds.out.$n 2>&1 && ret=1
+grep 'No DLV' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ $status = 0 ]; then $SHELL clean.sh; fi
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkds/wrong.example.dlv.example.dlv.db b/bin/tests/system/checkds/wrong.example.dlv.example.dlv.db
new file mode 100644
index 0000000..096969b
--- /dev/null
+++ b/bin/tests/system/checkds/wrong.example.dlv.example.dlv.db
@@ -0,0 +1,2 @@
+wrong.example.dlv.example. 3600 IN DLV 1192 5 1 684BB5119673C9272A0A7582AF8576561B5D80EC
+wrong.example.dlv.example. 3600 IN DLV 1192 5 2 14E4A873360E512CD2E8C2C331C4472F5EDAB0736669901F4D42E976 3D7B1F5C
diff --git a/bin/tests/system/checkds/wrong.example.dnskey.db b/bin/tests/system/checkds/wrong.example.dnskey.db
new file mode 100644
index 0000000..cc5bfd6
--- /dev/null
+++ b/bin/tests/system/checkds/wrong.example.dnskey.db
@@ -0,0 +1,2 @@
+wrong.example. 3600 IN DNSKEY 257 3 5 AwEAAc6Cz10GXEh5lxA9ujTY/QarTajcUOBwwBYIeldjRsgoouK/UioY FYgxEFL0O5JK6YCRUoGzl3EgLr5GvNyhIp1PZpOpHf7o/4MVOZTGJzm/ sHWP5B+KcYjQOxJiDb433iCmRM4DpHPUUoxw0QbZglzAzl5MfKBoyZud lH59DdT/50bkBg8iVu35EzuW0SYt31k70hxHBSb2wAGWeqxEPKJ1nQiI UcrWNDeem7byrqjPN9wyZhq0XkQ9qbcYxAkRNd8Y7P0FyR1YKJMc6SWZ Ru7muvxqTHgCtJVgxVz4qndCFKdYidiDeKe2/X/z5gf7pyYl3549O8JR tWdNKqutppk=
+wrong.example. 3600 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkds/wrong.example.ds.db b/bin/tests/system/checkds/wrong.example.ds.db
new file mode 100644
index 0000000..d7df610
--- /dev/null
+++ b/bin/tests/system/checkds/wrong.example.ds.db
@@ -0,0 +1,2 @@
+wrong.example. 3600 IN DS 1192 5 1 684BB5119673C9272A0A7582AF8576561B5D80EC
+wrong.example. 3600 IN DS 1192 5 2 14E4A873360E512CD2E8C2C331C4472F5EDAB0736669901F4D42E976 3D7B1F5C
diff --git a/bin/tests/system/checknames/clean.sh b/bin/tests/system/checknames/clean.sh
new file mode 100644
index 0000000..83073f9
--- /dev/null
+++ b/bin/tests/system/checknames/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f 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 */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
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..a984471
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/fail.example.db.in
@@ -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 http://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..218f6bc
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/fail.update.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..050041e
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/ignore.example.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..f7864ab
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/ignore.update.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..99b8004
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/named.conf.in
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ check-integrity no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "ignore.example" {
+ type master;
+ file "ignore.example.db";
+ check-names ignore;
+};
+
+zone "warn.example" {
+ type master;
+ file "warn.example.db";
+ check-names warn;
+};
+
+zone "fail.example" {
+ type master;
+ file "fail.example.db";
+ check-names fail;
+};
+
+zone "ignore.update" {
+ type master;
+ file "ignore.update.db";
+ allow-update { any; };
+ check-names ignore;
+};
+
+zone "warn.update" {
+ type master;
+ file "warn.update.db";
+ allow-update { any; };
+ check-names warn;
+};
+
+zone "fail.update" {
+ type master;
+ 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..1a0d44b
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..bc4d1c0
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/warn.example.db.in
@@ -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 http://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..1bf280a
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/warn.update.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..bdec53d
--- /dev/null
+++ b/bin/tests/system/checknames/ns2/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ acache-enable 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..962d33d
--- /dev/null
+++ b/bin/tests/system/checknames/ns2/root.hints
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..d4a3cd9
--- /dev/null
+++ b/bin/tests/system/checknames/ns3/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ acache-enable 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..962d33d
--- /dev/null
+++ b/bin/tests/system/checknames/ns3/root.hints
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns4/master-ignore.update.db.in b/bin/tests/system/checknames/ns4/master-ignore.update.db.in
new file mode 100644
index 0000000..f7864ab
--- /dev/null
+++ b/bin/tests/system/checknames/ns4/master-ignore.update.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/ns4/named.conf.in b/bin/tests/system/checknames/ns4/named.conf.in
new file mode 100644
index 0000000..5a97d49
--- /dev/null
+++ b/bin/tests/system/checknames/ns4/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ check-names master ignore;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+zone "master-ignore.update" {
+ type master;
+ file "master-ignore.update.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/checknames/ns4/root.hints b/bin/tests/system/checknames/ns4/root.hints
new file mode 100644
index 0000000..962d33d
--- /dev/null
+++ b/bin/tests/system/checknames/ns4/root.hints
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..28d0c44
--- /dev/null
+++ b/bin/tests/system/checknames/setup.sh
@@ -0,0 +1,28 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/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
+
+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/master-ignore.update.db.in ns4/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..74f783e
--- /dev/null
+++ b/bin/tests/system/checknames/tests.sh
@@ -0,0 +1,148 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+
+# 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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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.4 ${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)" ns1/named.run > /dev/null || not=0
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.master-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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkzone/clean.sh b/bin/tests/system/checkzone/clean.sh
new file mode 100644
index 0000000..95d3caa
--- /dev/null
+++ b/bin/tests/system/checkzone/clean.sh
@@ -0,0 +1,11 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f test.* good1.db.map good1.db.raw named-compilezone
+rm -f ns*/named.lock
diff --git a/bin/tests/system/checkzone/setup.sh b/bin/tests/system/checkzone/setup.sh
new file mode 100644
index 0000000..5fde7f6
--- /dev/null
+++ b/bin/tests/system/checkzone/setup.sh
@@ -0,0 +1,19 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+rm -f named-compilezone
+ln -s $CHECKZONE named-compilezone
+
+./named-compilezone -D -F raw -o good1.db.raw example \
+ zones/good1.db > /dev/null 2>&1
+./named-compilezone -D -F map -o good1.db.map example \
+ zones/good1.db > /dev/null 2>&1
diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh
new file mode 100644
index 0000000..9621566
--- /dev/null
+++ b/bin/tests/system/checkzone/tests.sh
@@ -0,0 +1,185 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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)
+ $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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+done
+
+for db in zones/bad*.db
+do
+ echo_i "checking $db ($n)"
+ ret=0
+ case $db in
+ zones/bad-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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking with max ttl (map) ($n)"
+ret=0
+$CHECKZONE -f map -l 300 example good1.db.map > test.out1.$n 2>&1 && ret=1
+$CHECKZONE -f map -l 600 example good1.db.map > test.out2.$n 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/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..9d22cd3
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-caa-rr.db
Binary files differ
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..9635a7a
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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-generate-tkey.db b/bin/tests/system/checkzone/zones/bad-generate-tkey.db
new file mode 100644
index 0000000..f86f15c
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-generate-tkey.db
@@ -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 http://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-nsap-empty.db b/bin/tests/system/checkzone/zones/bad-nsap-empty.db
new file mode 100644
index 0000000..3ed2451
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsap-empty.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..f8c82f5
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..77d8ead
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsec3-padded.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f9bbb6
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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-tkey.db b/bin/tests/system/checkzone/zones/bad-tkey.db
new file mode 100644
index 0000000..00f25db
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-tkey.db
@@ -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 http://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 b/bin/tests/system/checkzone/zones/bad-tsig.db
new file mode 100644
index 0000000..76af2e9
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-tsig.db
@@ -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 http://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 hmac-sha1. 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..2352ff9
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-unspec.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c17ab0c
--- /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..e6afacd
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad2.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..44e45e5
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad3.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4e6ec79
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad4.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..43fb41a
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/badttl.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL
+@ 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..c390d0c
--- /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 http://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.
+ 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..d26f51b
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/good-dns-sd-reverse.db b/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db
new file mode 100644
index 0000000..566ce5b
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cf9bc74
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-gc-msdcs.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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-nsap.db b/bin/tests/system/checkzone/zones/good-nsap.db
new file mode 100644
index 0000000..c7bc655
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-nsap.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4b4d4e4
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..caa7856
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..bdc8c6b
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/good1.db b/bin/tests/system/checkzone/zones/good1.db
new file mode 100644
index 0000000..f77f3ec
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good1.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..61c9d2a
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/inherit.db
@@ -0,0 +1,10 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+ 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..4083210
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..7e65e57
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/ns-address-below-dname.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..6c0e7e5
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/spf.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..bb75d3c
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/test1.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..cee52ca
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/test2.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..5057cd9
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/warn.inherit.origin.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..0879149
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/warn.inherited.owner.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+$INCLUDE "zones/inherit.db" @
diff --git a/bin/tests/system/clean.sh b/bin/tests/system/clean.sh
new file mode 100644
index 0000000..2306ac6
--- /dev/null
+++ b/bin/tests/system/clean.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after a specified system test.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+# See if the "-r" flag is present. This will usually be set when all the tests
+# are run (e.g. from "runall.sh") and tells the script not to delete the
+# test.output file created by run.sh. This is because the script running all
+# the tests will call "testsummary.sh", which will concatenate all test output
+# files into a single systests.output.
+
+runall=0
+
+while getopts "r" flag; do
+ case $flag in
+ r) runall=1 ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+if [ $# -eq 0 ]; then
+ echo "usage: $0 [-r] test-directory" >&2
+ exit 1
+fi
+
+systest=$1
+shift
+
+if [ $runall -eq 0 ]; then
+ rm -f $systest/test.output
+fi
+
+if [ -f $systest/clean.sh ]; then
+ ( cd $systest && $SHELL clean.sh "$@" )
+else
+ echo "Test directory $systest does not exist" >&2
+ exit 1
+fi
diff --git a/bin/tests/system/cleanall.sh b/bin/tests/system/cleanall.sh
new file mode 100644
index 0000000..80acf7e
--- /dev/null
+++ b/bin/tests/system/cleanall.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after system tests.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/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 lwresd.run -o -name ans.run \
+ -o -name '*-valgrind-*.log' \) -print | xargs rm -f
+
+status=0
+
+rm -f $SYSTEMTESTTOP/random.data
+
+for d in $SUBDIRS
+do
+ test ! -f $d/clean.sh || ( cd $d && $SHELL clean.sh )
+ test -f $d/test.output && rm $d/test.output
+ test -d $d && find $d -type d -exec rmdir '{}' \; 2> /dev/null
+done
diff --git a/bin/tests/system/cleanpkcs11.sh b/bin/tests/system/cleanpkcs11.sh
new file mode 100644
index 0000000..b974708
--- /dev/null
+++ b/bin/tests/system/cleanpkcs11.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+if [ ! -x ../../pkcs11/pkcs11-destroy ]; then exit 1; fi
+
+$PK11DEL -w0 > /dev/null 2>&1
diff --git a/bin/tests/system/common/controls.conf b/bin/tests/system/common/controls.conf
new file mode 100644
index 0000000..8cd709c
--- /dev/null
+++ b/bin/tests/system/common/controls.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
+
diff --git a/bin/tests/system/common/controls.conf.in b/bin/tests/system/common/controls.conf.in
new file mode 100644
index 0000000..6958115
--- /dev/null
+++ b/bin/tests/system/common/controls.conf.in
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..8fe0bc3
--- /dev/null
+++ b/bin/tests/system/common/rndc.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..b9def8e
--- /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 http://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..418ea96
--- /dev/null
+++ b/bin/tests/system/common/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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.in b/bin/tests/system/conf.sh.in
new file mode 100644
index 0000000..564c084
--- /dev/null
+++ b/bin/tests/system/conf.sh.in
@@ -0,0 +1,366 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Common configuration data for system tests, to be sourced into
+# other shell scripts.
+#
+
+# Find the top of the BIND9 tree.
+TOP=${SYSTEMTESTTOP:=.}/../../..
+
+# Make it absolute so that it continues to work after we cd.
+TOP=`cd $TOP && pwd`
+
+NAMED=$TOP/bin/named/named
+# We must use "named -l" instead of "lwresd" because argv[0] is lost
+# if the program is libtoolized.
+LWRESD="$TOP/bin/named/named -l"
+DIG=$TOP/bin/dig/dig
+DELV=$TOP/bin/delv/delv
+RNDC=$TOP/bin/rndc/rndc
+NSUPDATE=$TOP/bin/nsupdate/nsupdate
+DDNSCONFGEN=$TOP/bin/confgen/ddns-confgen
+TSIGKEYGEN=$TOP/bin/confgen/tsig-keygen
+RNDCCONFGEN=$TOP/bin/confgen/rndc-confgen
+KEYGEN=$TOP/bin/dnssec/dnssec-keygen
+KEYFRLAB=$TOP/bin/dnssec/dnssec-keyfromlabel
+SIGNER=$TOP/bin/dnssec/dnssec-signzone
+REVOKE=$TOP/bin/dnssec/dnssec-revoke
+SETTIME=$TOP/bin/dnssec/dnssec-settime
+DSFROMKEY=$TOP/bin/dnssec/dnssec-dsfromkey
+IMPORTKEY=$TOP/bin/dnssec/dnssec-importkey
+CHECKDS=$TOP/bin/python/dnssec-checkds
+COVERAGE=$TOP/bin/python/dnssec-coverage
+KEYMGR=$TOP/bin/python/dnssec-keymgr
+CHECKZONE=$TOP/bin/check/named-checkzone
+CHECKCONF=$TOP/bin/check/named-checkconf
+PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -q -s ${SLOT:-0} -p ${HSMPIN:-1234}"
+PK11LIST="$TOP/bin/pkcs11/pkcs11-list -s ${SLOT:-0} -p ${HSMPIN:-1234}"
+PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s ${SLOT:-0} -p ${HSMPIN:-1234} -w 0"
+JOURNALPRINT=$TOP/bin/tools/named-journalprint
+VERIFY=$TOP/bin/dnssec/dnssec-verify
+ARPANAME=$TOP/bin/tools/arpaname
+RESOLVE=$TOP/lib/samples/resolve
+RRCHECKER=$TOP/bin/tools/named-rrchecker
+GENRANDOM=$TOP/bin/tools/genrandom
+NSLOOKUP=$TOP/bin/dig/nslookup
+DNSTAPREAD=$TOP/bin/tools/dnstap-read
+MDIG=$TOP/bin/tools/mdig
+NZD2NZF=$TOP/bin/tools/named-nzd2nzf
+FSTRM_CAPTURE=@FSTRM_CAPTURE@
+FEATURETEST=$TOP/bin/tests/system/feature-test
+
+RANDFILE=$TOP/bin/tests/system/random.data
+
+BIGKEY=$TOP/bin/tests/system/rsabigexponent/bigkey
+GENCHECK=$TOP/bin/tests/system/rndc/gencheck
+KEYCREATE=$TOP/bin/tests/system/tkey/keycreate
+KEYDELETE=$TOP/bin/tests/system/tkey/keydelete
+LWTEST=$TOP/bin/tests/system/lwresd/lwtest
+MAKEJOURNAL=$TOP/bin/tests/makejournal
+PIPEQUERIES=$TOP/bin/tests/system/pipelined/pipequeries
+SAMPLEUPDATE=$TOP/lib/samples/sample-update
+
+# we don't want a KRB5_CONFIG setting breaking the tests
+KRB5_CONFIG=/dev/null
+
+# The "stress" test is not run by default since it creates enough
+# load on the machine to make it unusable to other users.
+# The "dialup", "delzone", and "dupsigs" tests are also not run by
+# default because they take a very long time to complete.
+#
+# List of tests hard-coded to use ports 5300 and 9953. For this
+# reason, these must be run sequentially.
+SEQUENTIALDIRS="ecdsa eddsa gost lwresd @PKCS11_TEST@ tkey"
+
+# List of tests that use ports assigned by caller (other than 5300
+# and 9953). Because separate blocks of ports can be used for teach
+# test, these tests can be run in parallel.
+#
+# This symbol must be kept in step with the PARALLEL macro in Makefile.in
+PARALLELDIRS="acl additional addzone allow-query autosign \
+ builtin cacheclean case catz chain \
+ checkconf checknames checkzone \
+ @CHECKDS@ @COVERAGE@ @KEYMGR@ \
+ cookie database digdelv dlv dlz dlzexternal \
+ dns64 dnssec @DNSTAP@ dscp dsdigest dyndb \
+ ednscompliance emptyzones \
+ fetchlimit filter-aaaa formerr forward \
+ geoip glue idna inline integrity ixfr \
+ legacy limits logfileconfig lwresd \
+ masterfile masterformat metadata mkeys \
+ names notify nslookup nsupdate nzd2nzf \
+ pending pipelined \
+ reclimit redirect resolver rndc rootkeysentinel rpz rpzrecurse \
+ rrchecker rrl rrsetorder rsabigexponent runtime \
+ sfcache smartsign sortlist \
+ spf staticstub statistics statschannel stub \
+ tcp tools tsig tsiggss \
+ unknown upforwd verify views wildcard \
+ xfer xferquota zero zonechecks"
+
+SUBDIRS="$SEQUENTIALDIRS $PARALLELDIRS"
+
+
+# Things that are different on Windows
+KILL=kill
+DIFF=diff
+DOS2UNIX=true
+# There's no trailing period on Windows
+TP=.
+
+# Use the CONFIG_SHELL detected by configure for tests
+SHELL=@SHELL@
+
+# CURL will be empty if no program was found by configure
+CURL=@CURL@
+
+# XMLLINT will be empty if no program was found by configure
+XMLLINT=@XMLLINT@
+
+# PERL will be an empty string if no perl interpreter was found.
+PERL=@PERL@
+
+if test -n "$PERL"
+then
+ if $PERL -e "use IO::Socket::INET6;" 2> /dev/null
+ then
+ TESTSOCK6="$PERL $TOP/bin/tests/system/testsock6.pl"
+ else
+ TESTSOCK6=false
+ fi
+else
+ TESTSOCK6=false
+fi
+
+if grep "^#define WANT_IPV6 1" $TOP/config.h > /dev/null 2>&1 ; then
+ TESTSOCK6="$TESTSOCK6"
+else
+ TESTSOCK6=false
+fi
+
+
+PYTHON=@PYTHON@
+
+#
+# Determine if we support various optional features.
+#
+CHECK_DSA=@CHECK_DSA@
+HAVEXMLSTATS=@XMLSTATS@
+HAVEJSONSTATS=@JSONSTATS@
+ZLIB=@ZLIB@
+NZD=@NZD_TOOLS@
+
+. ${TOP}/version
+
+#
+# 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
+ COLOR_END=`tput setaf 4` # blue
+ COLOR_FAIL=`tput setaf 1` # red
+ COLOR_INFO=`tput bold` # bold
+ COLOR_NONE=`tput sgr0`
+ COLOR_PASS=`tput setaf 2` # green
+ COLOR_START=`tput setaf 4` # blue
+ COLOR_WARN=`tput setaf 3` # yellow
+else
+ # set to empty strings so printf succeeds
+ COLOR_END=''
+ COLOR_FAIL=''
+ COLOR_INFO=''
+ COLOR_NONE=''
+ COLOR_PASS=''
+ COLOR_START=''
+ COLOR_WARN=''
+fi
+
+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" "$*"
+ }
+else
+ echofail () {
+ echo "$*"
+ }
+ echowarn () {
+ echo "$*"
+ }
+ echopass () {
+ echo "$*"
+ }
+ echoinfo () {
+ echo "$*"
+ }
+ echostart () {
+ echo "$*"
+ }
+ echoend () {
+ echo "$*"
+ }
+fi
+
+SYSTESTDIR="`basename $PWD`"
+
+echo_i() {
+ echo "$@" | while read LINE ; do
+ echoinfo "I:$SYSTESTDIR:$LINE"
+ done
+}
+
+echo_ic() {
+ echo "$@" | while read LINE ; do
+ echoinfo "I:$SYSTESTDIR: $LINE"
+ done
+}
+
+cat_i() {
+ while read LINE ; do
+ echoinfo "I:$SYSTESTDIR:$LINE"
+ done
+}
+
+digcomp() {
+ output=`$PERL $SYSTEMTESTTOP/digcomp.pl "$@"`
+ result=$?
+ [ -n "$output" ] && { echo "digcomp failed:"; echo "$output"; } | cat_i
+ return $result
+}
+
+#
+# Useful functions in test scripts
+#
+
+# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
+# converts keyfile data into a configuration section using the supplied
+# parameters
+keyfile_to_keys_section() {
+ 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_trusted_keys: convert key data contained in the keyfile(s)
+# provided to a "trusted-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_trusted_keys() {
+ keyfile_to_keys_section "trusted-keys" "" $*
+}
+
+# keyfile_to_managed_keys: convert key data contained in the keyfile(s)
+# provided to a "managed-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_managed_keys() {
+ keyfile_to_keys_section "managed-keys" "initial-key " $*
+}
+
+# nextpart: read everything that's been appended to a file since the
+# last time 'nextpart' was called.
+nextpart () {
+ [ -f $1.prev ] || echo "0" > $1.prev
+ prev=`cat $1.prev`
+ awk "NR > $prev "'{ print }
+ END { print NR > "/dev/stderr" }' $1 2> $1.prev
+}
+
+# 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 "run.sh", which calls the
+# scripts invoking this function.)
+#
+# Usage:
+# copy_setports infile outfile
+
+copy_setports() {
+ sed -e "s/@PORT@/${PORT}/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" $1 > $2
+}
+
+#
+# Export command paths
+#
+export ARPANAME
+export BIGKEY
+export CHECKZONE
+export DESCRIPTION
+export DIG
+export FEATURETEST
+export FSTRM_CAPTURE
+export GENCHECK
+export JOURNALPRINT
+export KEYCREATE
+export KEYDELETE
+export KEYFRLAB
+export KEYGEN
+export KEYSETTOOL
+export KEYSIGNER
+export KRB5_CONFIG
+export LWRESD
+export LWTEST
+export MAKEJOURNAL
+export MDIG
+export NAMED
+export NSLOOKUP
+export NSUPDATE
+export NZD2NZF
+export PERL
+export PIPEQUERIES
+export PK11DEL
+export PK11GEN
+export PK11LIST
+export PYTHON
+export RANDFILE
+export RESOLVE
+export RNDC
+export RRCHECKER
+export SAMPLEUPDATE
+export SIGNER
+export SUBDIRS
+export TESTSOCK6
diff --git a/bin/tests/system/conf.sh.win32 b/bin/tests/system/conf.sh.win32
new file mode 100644
index 0000000..589dab5
--- /dev/null
+++ b/bin/tests/system/conf.sh.win32
@@ -0,0 +1,344 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Common configuration data for system tests, to be sourced into
+# other shell scripts.
+#
+
+# For specific stuff (currently kill HUP -> rdnc reload in notify)
+CYGWIN=1
+
+# Find the top of the BIND9 tree.
+TOP=${SYSTEMTESTTOP:=.}/../../..
+
+# Make it absolute so that it continues to work after we cd.
+TOP=`cd $TOP && pwd`
+
+# Visual Studio build configurations are Release and Debug
+VSCONF=Debug
+
+ARPANAME=$TOP/Build/$VSCONF/arpaname@EXEEXT@
+CHECKCONF=$TOP/Build/$VSCONF/named-checkconf@EXEEXT@
+CHECKDS="$PYTHON `cygpath -w $TOP/bin/python/dnssec-checkds.py`"
+CHECKZONE=$TOP/Build/$VSCONF/named-checkzone@EXEEXT@
+COVERAGE="$PYTHON `cygpath -w $TOP/bin/python/dnssec-coverage.py`"
+DDNSCONFGEN=$TOP/Build/$VSCONF/ddns-confgen@EXEEXT@
+DELV=$TOP/Build/$VSCONF/delv@EXEEXT@
+DIG=$TOP/Build/$VSCONF/dig@EXEEXT@
+DNSTAPREAD=$TOP/Build/$VSCONF/dnstap-read@EXEEXT@
+DSFROMKEY=$TOP/Build/$VSCONF/dnssec-dsfromkey@EXEEXT@
+FEATURETEST=$TOP/Build/$VSCONF/feature-test@EXEEXT@
+FSTRM_CAPTURE=@FSTRM_CAPTURE@
+GENRANDOM=$TOP/Build/$VSCONF/genrandom@EXEEXT@
+IMPORTKEY=$TOP/Build/$VSCONF/dnssec-importkey@EXEEXT@
+JOURNALPRINT=$TOP/Build/$VSCONF/named-journalprint@EXEEXT@
+KEYFRLAB=$TOP/Build/$VSCONF/dnssec-keyfromlabel@EXEEXT@
+KEYGEN=$TOP/Build/$VSCONF/dnssec-keygen@EXEEXT@
+KEYMGR="$PYTHON `cygpath -w $TOP/bin/python/dnssec-keymgr.py`"
+# We must use "named -l" instead of "lwresd" because argv[0] is lost
+# if the program is libtoolized.
+LWRESD="$TOP/Build/$VSCONF/named@EXEEXT@ -l"
+MDIG=$TOP/Build/$VSCONF/mdig@EXEEXT@
+NAMED=$TOP/Build/$VSCONF/named@EXEEXT@
+NSLOOKUP=$TOP/Build/$VSCONF/nslookup@EXEEXT@
+NSUPDATE=$TOP/Build/$VSCONF/nsupdate@EXEEXT@
+NZD2NZF=$TOP/Build/$VSCONF/named-nzd2nzf@EXEEXT@
+PK11DEL="$TOP/Build/$VSCONF/pkcs11-destroy@EXEEXT@ -s ${SLOT:-0} -p ${HSMPIN:-1234} -w 0"
+PK11GEN="$TOP/Build/$VSCONF/pkcs11-keygen@EXEEXT@ -q -s ${SLOT:-0} -p ${HSMPIN:-1234}"
+PK11LIST="$TOP/Build/$VSCONF/pkcs11-list@EXEEXT@ -s ${SLOT:-0} -p ${HSMPIN:-1234}"
+RESOLVE=$TOP/lib/samples/resolve
+REVOKE=$TOP/Build/$VSCONF/dnssec-revoke@EXEEXT@
+RNDC=$TOP/Build/$VSCONF/rndc@EXEEXT@
+RNDCCONFGEN=$TOP/Build/$VSCONF/rndc-confgen@EXEEXT@
+RRCHECKER=$TOP/Build/$VSCONF/named-rrchecker@EXEEXT@
+SAMPLEUPDATE=$TOP/Build/$VSCONF/update@EXEEXT@
+SETTIME=$TOP/Build/$VSCONF/dnssec-settime@EXEEXT@
+SIGNER=$TOP/Build/$VSCONF/dnssec-signzone@EXEEXT@
+TSIGKEYGEN=$TOP/Build/$VSCONF/tsig-keygen@EXEEXT@
+VERIFY=$TOP/Build/$VSCONF/dnssec-verify@EXEEXT@
+
+# to port WIRETEST=$TOP/Build/$VSCONF/wire_test@EXEEXT@
+
+# this is given as argument to native WIN32 executables
+RANDFILE=`cygpath -w $TOP/bin/tests/system/random.data`
+
+BIGKEY=$TOP/Build/$VSCONF/bigkey@EXEEXT@
+GENCHECK=$TOP/Build/$VSCONF/gencheck@EXEEXT@
+KEYCREATE=$TOP/Build/$VSCONF/keycreate@EXEEXT@
+KEYDELETE=$TOP/Build/$VSCONF/keydelete@EXEEXT@
+LWTEST=$TOP/Build/$VSCONF/lwtest@EXEEXT@
+MAKEJOURNAL=$TOP/Build/$VSCONF/makejournal@EXEEXT@
+PIPEQUERIES=$TOP/Build/$VSCONF/pipequeries@EXEEXT@
+# to port SAMPLEUPDATE=$TOP/lib/samples/sample-update
+
+# we don't want a KRB5_CONFIG setting breaking the tests
+KRB5_CONFIG=NUL
+
+# The "stress" test is not run by default since it creates enough
+# load on the machine to make it unusable to other users.
+# The "dialup", "delzone", and "dupsigs" tests are also not run by
+# default because they take a very long time to complete.
+#
+# List of tests that use ports 5300 and 9953. For this reason, these must
+# be run sequentially.
+SEQUENTIALDIRS="acl additional addzone autosign builtin \
+ cacheclean case \
+ checkconf @CHECKDS@ checknames checkzone cookie @COVERAGE@ \
+ database digdelv dlv dlvauto dlz dlzexternal \
+ dns64 dnssec @DNSTAP@ dscp dsdigest dyndb ecdsa eddsa \
+ ednscompliance emptyzones \
+ fetchlimit filter-aaaa formerr forward geoip glue gost idna inline ixfr \
+ @KEYMGR@ legacy limits logfileconfig lwresd masterfile masterformat \
+ metadata mkeys names notify nslookup nsupdate nzd2nzf pending \
+ @PKCS11_TEST@ pipelined reclimit redirect resolver rndc rpz \
+ rrchecker rrl rrsetorder rsabigexponent runtime sfcache \
+ smartsign sortlist spf staticstub statistics statschannel stub tcp \
+ tkey tsig tsiggss unknown upforwd verify views wildcard xfer \
+ xferquota zero zonechecks"
+
+# List of tests that use unique ports (other than 5300 and 9953). These
+# tests can be run in parallel.
+#
+# This symbol must be kept in step with the PARALLEL macro in Makefile.in
+PARALLELDIRS="allow_query catz rpzrecurse"
+
+SUBDIRS="$SEQUENTIALDIRS $PARALLELDIRS"
+
+# missing: chain integrity
+# extra: dname ednscompliance forward
+
+#Things that are different on Windows
+KILL="/bin/kill -f"
+DIFF="diff --strip-trailing-cr"
+DOS2UNIX=dos2unix
+# No trailing period
+TP=
+
+# Configure is launched from native environment, but tests are run in Cygwin -
+# so any detection is unreliable.
+SHELL="/bin/bash -o igncr"
+CURL=/usr/bin/curl
+XMLLINT=/usr/bin/xmllint
+PERL=/usr/bin/perl
+
+if test -n "$PERL"
+then
+ if $PERL -e "use IO::Socket::INET6;" 2> /dev/null
+ then
+ TESTSOCK6="$PERL $TOP/bin/tests/system/testsock6.pl"
+ else
+ TESTSOCK6=false
+ fi
+else
+ TESTSOCK6=false
+fi
+
+if grep "^#define WANT_IPV6 1" $TOP/config.h > /dev/null 2>&1 ; then
+ TESTSOCK6="$TESTSOCK6"
+else
+ TESTSOCK6=false
+fi
+
+
+PYTHON=@PYTHON@
+
+#
+# Determine if we support various optional features.
+#
+CHECK_DSA=@CHECK_DSA@
+HAVEXMLSTATS=@XMLSTATS@
+HAVEJSONSTATS=@JSONSTATS@
+ZLIB=@ZLIB@
+NZD=@NZD_TOOLS@
+
+. ${TOP}/version
+
+#
+# Set up color-coded test output
+#
+if test -t 1 && type tput > /dev/null; then
+ COLOR_END=`tput setaf 4` # blue
+ COLOR_FAIL=`tput setaf 1` # red
+ COLOR_INFO=`tput bold` # bold
+ COLOR_NONE=`tput sgr0`
+ COLOR_PASS=`tput setaf 2` # green
+ COLOR_START=`tput setaf 4` # blue
+ COLOR_WARN=`tput setaf 3` # yellow
+else
+ # set to empty strings so printf succeeds
+ COLOR_END=''
+ COLOR_FAIL=''
+ COLOR_INFO=''
+ COLOR_NONE=''
+ COLOR_PASS=''
+ COLOR_START=''
+ COLOR_WARN=''
+fi
+
+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" "$*"
+}
+
+TESTNAME="`basename $PWD`"
+
+echo_i() {
+ echo "$@" | while read LINE ; do
+ echoinfo "I:$TESTNAME:$LINE"
+ done
+}
+
+cat_i() {
+ while read LINE ; do
+ echoinfo "I:$SYSTESTDIR:$LINE"
+ done
+}
+
+digcomp() {
+ output=`$PERL $SYSTEMTESTTOP/digcomp.pl "$@"`
+ result=$?
+ [ -n "$output" ] && { echo "digcomp failed:"; echo "$output"; } | cat_i
+ return $result
+}
+
+#
+# Useful functions in test scripts
+#
+
+# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
+# converts keyfile data into a configuration section using the supplied
+# parameters
+keyfile_to_keys_section() {
+ 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_trusted_keys: convert key data contained in the keyfile(s)
+# provided to a "trusted-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_trusted_keys() {
+ keyfile_to_keys_section "trusted-keys" "" $*
+}
+
+# keyfile_to_managed_keys: convert key data contained in the keyfile(s)
+# provided to a "managed-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_managed_keys() {
+ keyfile_to_keys_section "managed-keys" "initial-key " $*
+}
+
+# nextpart: read everything that's been appended to a file since the
+# last time 'nextpart' was called.
+nextpart () {
+ [ -f $1.prev ] || echo "0" > $1.prev
+ prev=`cat $1.prev`
+ awk "NR > $prev "'{ print }
+ END { print NR > "/dev/stderr" }' $1 2> $1.prev
+}
+
+# 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 "run.sh", which calls the
+# scripts invoking this function.)
+#
+# Usage:
+# copy_setports infile outfile
+
+copy_setports() {
+ # The indirect method of handling the substitution of the PORT variables
+ # (defining "atsign" then substituting for it in the "sed" statement) is
+ # required because to prevent the "Configure" script (in the the
+ # bin9/win32utils directory) replacing the the <at>PORT<at> substitution
+ # tokens when it processes this file and produces conf.sh.
+ atsign="@"
+ sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \
+ -e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
+ -e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/g" \
+ -e "s/${atsign}EXTRAPORT3${atsign}/${EXTRAPORT3}/g" \
+ -e "s/${atsign}EXTRAPORT4${atsign}/${EXTRAPORT4}/g" \
+ -e "s/${atsign}EXTRAPORT5${atsign}/${EXTRAPORT5}/g" \
+ -e "s/${atsign}EXTRAPORT6${atsign}/${EXTRAPORT6}/g" \
+ -e "s/${atsign}EXTRAPORT7${atsign}/${EXTRAPORT7}/g" \
+ -e "s/${atsign}EXTRAPORT8${atsign}/${EXTRAPORT8}/g" \
+ -e "s/${atsign}CONTROLPORT${atsign}/${CONTROLPORT}/g" $1 > $2
+}
+
+#
+# Export command paths
+#
+export ARPANAME
+export BIGKEY
+export CHECKZONE
+export DESCRIPTION
+export DIG
+export FEATURETEST
+export FSTRM_CAPTURE
+export GENCHECK
+export JOURNALPRINT
+export KEYCREATE
+export KEYDELETE
+export KEYFRLAB
+export KEYGEN
+export KEYSETTOOL
+export KEYSIGNER
+export KRB5_CONFIG
+export LWRESD
+export LWTEST
+export MAKEJOURNAL
+export MDIG
+export NAMED
+export NSLOOKUP
+export NSUPDATE
+export NZD2NZF
+export PERL
+export PIPEQUERIES
+export PK11DEL
+export PK11GEN
+export PK11LIST
+export PYTHON
+export RANDFILE
+export RESOLVE
+export RNDC
+export RRCHECKER
+export SAMPLEUPDATE
+export SIGNER
+export SUBDIRS
+export TESTSOCK6
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..318425f
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badhex.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-secret "012345678901234567890123456789012345678901234567890123456789012";
+};
diff --git a/bin/tests/system/cookie/bad-cookie-badsha1.conf b/bin/tests/system/cookie/bad-cookie-badsha1.conf
new file mode 100644
index 0000000..f22dd49
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badsha1.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm sha1;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272fff"; // 168 bits
+};
diff --git a/bin/tests/system/cookie/bad-cookie-badsha256.conf b/bin/tests/system/cookie/bad-cookie-badsha256.conf
new file mode 100644
index 0000000..3442099
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badsha256.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm sha256;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272f"; // 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..3171b3c
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-toolong.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..01abbc8
--- /dev/null
+++ b/bin/tests/system/cookie/clean.sh
@@ -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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f dig.out.*
+rm -f ns1/named_dump.db
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.lock
diff --git a/bin/tests/system/cookie/good-cookie-sha1.conf b/bin/tests/system/cookie/good-cookie-sha1.conf
new file mode 100644
index 0000000..315732b
--- /dev/null
+++ b/bin/tests/system/cookie/good-cookie-sha1.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm sha1;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272f"; // 160 bits
+};
diff --git a/bin/tests/system/cookie/good-cookie-sha256.conf b/bin/tests/system/cookie/good-cookie-sha256.conf
new file mode 100644
index 0000000..2fe68f2
--- /dev/null
+++ b/bin/tests/system/cookie/good-cookie-sha256.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm sha256;
+ cookie-secret "b174e3800b6734f73268f15831c957860a8ee1229cfb9039c1514836f53efbed";
+};
diff --git a/bin/tests/system/cookie/ns1/example.db b/bin/tests/system/cookie/ns1/example.db
new file mode 100644
index 0000000..fae6856
--- /dev/null
+++ b/bin/tests/system/cookie/ns1/example.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..6548f2d
--- /dev/null
+++ b/bin/tests/system/cookie/ns1/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.1 dscp 1;
+ notify-source 10.53.0.1 dscp 2;
+ transfer-source 10.53.0.1 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable 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 master;
+ 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..64769b9
--- /dev/null
+++ b/bin/tests/system/cookie/ns1/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..08dcf49
--- /dev/null
+++ b/bin/tests/system/cookie/ns2/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2 dscp 1;
+ notify-source 10.53.0.2 dscp 2;
+ transfer-source 10.53.0.2 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ acache-enable yes;
+ send-cookie yes;
+ nocookie-udp-size 512;
+};
+
+zone "." {
+ type master;
+ 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..96410ee
--- /dev/null
+++ b/bin/tests/system/cookie/ns2/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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/ns3/named.conf.in b/bin/tests/system/cookie/ns3/named.conf.in
new file mode 100644
index 0000000..12500f5
--- /dev/null
+++ b/bin/tests/system/cookie/ns3/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.3 dscp 1;
+ notify-source 10.53.0.3 dscp 2;
+ transfer-source 10.53.0.3 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable 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 master;
+ 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..64769b9
--- /dev/null
+++ b/bin/tests/system/cookie/ns3/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..cd7c07f
--- /dev/null
+++ b/bin/tests/system/cookie/ns4/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ cookie-algorithm sha1;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+ 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..64769b9
--- /dev/null
+++ b/bin/tests/system/cookie/ns4/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..0d050a6
--- /dev/null
+++ b/bin/tests/system/cookie/ns5/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ cookie-algorithm sha1;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+ 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..64769b9
--- /dev/null
+++ b/bin/tests/system/cookie/ns5/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..634a939
--- /dev/null
+++ b/bin/tests/system/cookie/ns6/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ cookie-algorithm sha1;
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+ 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..64769b9
--- /dev/null
+++ b/bin/tests/system/cookie/ns6/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..9c25220
--- /dev/null
+++ b/bin/tests/system/cookie/ns7/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7 dscp 1;
+ notify-source 10.53.0.7 dscp 2;
+ transfer-source 10.53.0.7 dscp 3;
+ 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;
+};
+
+zone "." {
+ type master;
+ 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..96410ee
--- /dev/null
+++ b/bin/tests/system/cookie/ns7/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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/setup.sh b/bin/tests/system/cookie/setup.sh
new file mode 100644
index 0000000..fa6de38
--- /dev/null
+++ b/bin/tests/system/cookie/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/cookie/tests.sh b/bin/tests/system/cookie/tests.sh
new file mode 100755
index 0000000..816f6a3
--- /dev/null
+++ b/bin/tests/system/cookie/tests.sh
@@ -0,0 +1,273 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+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=`expr $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=`expr $status + $ret`
+done
+
+for good in good*.conf
+do
+ n=`expr $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=`expr $status + $ret`
+done
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+havetc dig.out.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+cookie=`getcookie dig.out.test$n.l`
+$DIG $DIGOPTS +qr +cookie=$cookie large.example txt @10.53.0.1 +ignore > dig.out.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking for COOKIE value in adb ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 dumpdb
+sleep 1
+grep "10.53.0.2.*\[cookie=" ns1/named_dump.db > /dev/null|| ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+#
+# Test shared cookie-secret support.
+#
+# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+#
+# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3"; (alternate)
+#
+# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+#
+# 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=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/coverage/01-ksk-inactive/README b/bin/tests/system/coverage/01-ksk-inactive/README
new file mode 100644
index 0000000..8102593
--- /dev/null
+++ b/bin/tests/system/coverage/01-ksk-inactive/README
@@ -0,0 +1,10 @@
+This set includes one KSK rollover. The KSK is deactivated prior to
+its replacement being activated. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+ERROR: After 2012-31-Jul (20:59:14):
+ Inactive: example.com/007/45435 (KSK)
+No KSK's are active
+
+Checking ZSK events for zone example.com, algorithm 7:
+OK
diff --git a/bin/tests/system/coverage/01-ksk-inactive/expect b/bin/tests/system/coverage/01-ksk-inactive/expect
new file mode 100644
index 0000000..3d342b1
--- /dev/null
+++ b/bin/tests/system/coverage/01-ksk-inactive/expect
@@ -0,0 +1,6 @@
+args="-d 1h -m 2h"
+warn=0
+error=1
+ok=1
+retcode=1
+match="No KSK's are active"
diff --git a/bin/tests/system/coverage/02-zsk-inactive/README b/bin/tests/system/coverage/02-zsk-inactive/README
new file mode 100644
index 0000000..5d3fed1
--- /dev/null
+++ b/bin/tests/system/coverage/02-zsk-inactive/README
@@ -0,0 +1,10 @@
+This set includes one ZSK rollover. The first ZSK is deactivated
+prior to its replacement being activated. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+OK
+
+Checking ZSK events for zone example.com, algorithm 7:
+ERROR: After 2012-05-Dec (20:39:32):
+ Inactive: example.com/005/08376 (ZSK)
+No ZSK's are active
diff --git a/bin/tests/system/coverage/02-zsk-inactive/expect b/bin/tests/system/coverage/02-zsk-inactive/expect
new file mode 100644
index 0000000..a905b58
--- /dev/null
+++ b/bin/tests/system/coverage/02-zsk-inactive/expect
@@ -0,0 +1,6 @@
+args="-d 1h -m 2h"
+warn=0
+error=1
+ok=1
+retcode=1
+match="No ZSK's are active"
diff --git a/bin/tests/system/coverage/03-ksk-unpublished/README b/bin/tests/system/coverage/03-ksk-unpublished/README
new file mode 100644
index 0000000..7d8a301
--- /dev/null
+++ b/bin/tests/system/coverage/03-ksk-unpublished/README
@@ -0,0 +1,10 @@
+This set contains one KSK rollover. The KSK is unpublished before its
+successor is published. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+ERROR: After 2012-06-Oct (21:07:57):
+ Delete: example.com/007/23040 (KSK)
+No KSK's are published
+
+Checking ZSK events for zone example.com, algorithm 7:
+OK
diff --git a/bin/tests/system/coverage/03-ksk-unpublished/expect b/bin/tests/system/coverage/03-ksk-unpublished/expect
new file mode 100644
index 0000000..07bbff1
--- /dev/null
+++ b/bin/tests/system/coverage/03-ksk-unpublished/expect
@@ -0,0 +1,8 @@
+args="-d 1h -m 2h"
+warn=1
+error=1
+ok=1
+retcode=1
+match="WARNING: Key .* (KSK) is scheduled for
+deletion before inactivation
+No KSK's are published"
diff --git a/bin/tests/system/coverage/04-zsk-unpublished/README b/bin/tests/system/coverage/04-zsk-unpublished/README
new file mode 100644
index 0000000..5077abf
--- /dev/null
+++ b/bin/tests/system/coverage/04-zsk-unpublished/README
@@ -0,0 +1,10 @@
+This set contains one ZSK rollover. The ZSK is unpublished before its
+successor is published. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+OK
+
+Checking ZSK events for zone example.com, algorithm 7:
+ERROR: After 2012-06-Oct (21:13:45):
+ Delete: example.com/007/25967 (ZSK)
+No ZSK's are published
diff --git a/bin/tests/system/coverage/04-zsk-unpublished/expect b/bin/tests/system/coverage/04-zsk-unpublished/expect
new file mode 100644
index 0000000..450ec24
--- /dev/null
+++ b/bin/tests/system/coverage/04-zsk-unpublished/expect
@@ -0,0 +1,8 @@
+args="-d 1h -m 2h"
+warn=1
+error=1
+ok=1
+retcode=1
+match="WARNING: Key .* (ZSK) is scheduled for
+deletion before inactivation
+No ZSK's are published"
diff --git a/bin/tests/system/coverage/05-ksk-unpub-active/README b/bin/tests/system/coverage/05-ksk-unpub-active/README
new file mode 100644
index 0000000..119c1b2
--- /dev/null
+++ b/bin/tests/system/coverage/05-ksk-unpub-active/README
@@ -0,0 +1,12 @@
+This set includes one KSK rollover. The first KSK is deleted
+and its successor published prior to the first KSK being deactivated
+and its successor activated. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+ERROR: After 2012-05-Dec (21:22:19):
+ Delete: example.com/007/06219 (KSK)
+ Publish: example.com/007/20559 (KSK)
+No KSK's are both active and published
+
+Checking ZSK events for zone example.com, algorithm 7:
+OK
diff --git a/bin/tests/system/coverage/05-ksk-unpub-active/expect b/bin/tests/system/coverage/05-ksk-unpub-active/expect
new file mode 100644
index 0000000..2edfa0e
--- /dev/null
+++ b/bin/tests/system/coverage/05-ksk-unpub-active/expect
@@ -0,0 +1,8 @@
+args="-d 1h -m 2h"
+warn=1
+error=1
+ok=1
+retcode=1
+match="WARNING: Key .* (KSK) is scheduled for
+deletion before inactivation
+No KSK's are both active and published"
diff --git a/bin/tests/system/coverage/06-zsk-unpub-active/README b/bin/tests/system/coverage/06-zsk-unpub-active/README
new file mode 100644
index 0000000..84833f8
--- /dev/null
+++ b/bin/tests/system/coverage/06-zsk-unpub-active/README
@@ -0,0 +1,12 @@
+This set includes one KSK rollover. The first KSK is deleted
+and its successor published prior to the first KSK being deactivated
+and its successor activated. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+OK
+
+Checking ZSK events for zone example.com, algorithm 7:
+ERROR: After 2012-05-Dec (20:44:18):
+ Delete: example.com/007/26369 (ZSK)
+ Publish: example.com/007/21029 (ZSK)
+No ZSK's are both active and published
diff --git a/bin/tests/system/coverage/06-zsk-unpub-active/expect b/bin/tests/system/coverage/06-zsk-unpub-active/expect
new file mode 100644
index 0000000..0ef5b15
--- /dev/null
+++ b/bin/tests/system/coverage/06-zsk-unpub-active/expect
@@ -0,0 +1,8 @@
+args="-d 1h -m 2h"
+warn=1
+error=1
+ok=1
+retcode=1
+match="WARNING: Key .* (ZSK) is scheduled for
+deletion before inactivation
+No ZSK's are both active and published"
diff --git a/bin/tests/system/coverage/07-ksk-ttl/README b/bin/tests/system/coverage/07-ksk-ttl/README
new file mode 100644
index 0000000..2659099
--- /dev/null
+++ b/bin/tests/system/coverage/07-ksk-ttl/README
@@ -0,0 +1,4 @@
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
+
+Expected tool output TBD.
diff --git a/bin/tests/system/coverage/07-ksk-ttl/expect b/bin/tests/system/coverage/07-ksk-ttl/expect
new file mode 100644
index 0000000..eade21a
--- /dev/null
+++ b/bin/tests/system/coverage/07-ksk-ttl/expect
@@ -0,0 +1,9 @@
+args="-d 1w -m 2w"
+warn=1
+error=0
+ok=2
+retcode=0
+match="WARNING: Key .* (KSK) is activated too soon
+after publication
+Activation should be at least 7 days after
+publication."
diff --git a/bin/tests/system/coverage/08-zsk-ttl/README b/bin/tests/system/coverage/08-zsk-ttl/README
new file mode 100644
index 0000000..2659099
--- /dev/null
+++ b/bin/tests/system/coverage/08-zsk-ttl/README
@@ -0,0 +1,4 @@
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
+
+Expected tool output TBD.
diff --git a/bin/tests/system/coverage/08-zsk-ttl/expect b/bin/tests/system/coverage/08-zsk-ttl/expect
new file mode 100644
index 0000000..150c9cd
--- /dev/null
+++ b/bin/tests/system/coverage/08-zsk-ttl/expect
@@ -0,0 +1,9 @@
+args="-d 1w -m 2w"
+warn=1
+error=0
+ok=2
+retcode=0
+match="WARNING: Key .* (ZSK) is activated too soon
+after publication
+Activation should be at least 7 days after
+publication."
diff --git a/bin/tests/system/coverage/09-check-zsk/README b/bin/tests/system/coverage/09-check-zsk/README
new file mode 100644
index 0000000..bc5edc8
--- /dev/null
+++ b/bin/tests/system/coverage/09-check-zsk/README
@@ -0,0 +1,6 @@
+This set includes one KSK rollover. The KSK is deactivated prior to
+its replacement being activated; however, as we are only checking ZSK's,
+we should not detect the error. Tool output should resemble:
+
+Checking ZSK events for zone example.com, algorithm 7:
+OK
diff --git a/bin/tests/system/coverage/09-check-zsk/expect b/bin/tests/system/coverage/09-check-zsk/expect
new file mode 100644
index 0000000..d56c4bf
--- /dev/null
+++ b/bin/tests/system/coverage/09-check-zsk/expect
@@ -0,0 +1,6 @@
+args="-z -d 1h -m 2h"
+warn=0
+error=0
+ok=1
+retcode=0
+match=""
diff --git a/bin/tests/system/coverage/10-check-ksk/README b/bin/tests/system/coverage/10-check-ksk/README
new file mode 100644
index 0000000..948364d
--- /dev/null
+++ b/bin/tests/system/coverage/10-check-ksk/README
@@ -0,0 +1,7 @@
+This set includes one ZSK rollover. The first ZSK is deactivated
+prior to its replacement being activated; however, as we are only
+checking KSKs, we should not detect the error. Tool output should
+resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+OK
diff --git a/bin/tests/system/coverage/10-check-ksk/expect b/bin/tests/system/coverage/10-check-ksk/expect
new file mode 100644
index 0000000..a03d2aa
--- /dev/null
+++ b/bin/tests/system/coverage/10-check-ksk/expect
@@ -0,0 +1,6 @@
+args="-k -d 1h -m 2h"
+warn=0
+error=0
+ok=1
+retcode=0
+match=""
diff --git a/bin/tests/system/coverage/11-cutoff/README b/bin/tests/system/coverage/11-cutoff/README
new file mode 100644
index 0000000..8102593
--- /dev/null
+++ b/bin/tests/system/coverage/11-cutoff/README
@@ -0,0 +1,10 @@
+This set includes one KSK rollover. The KSK is deactivated prior to
+its replacement being activated. Tool output should resemble:
+
+Checking KSK events for zone example.com, algorithm 7:
+ERROR: After 2012-31-Jul (20:59:14):
+ Inactive: example.com/007/45435 (KSK)
+No KSK's are active
+
+Checking ZSK events for zone example.com, algorithm 7:
+OK
diff --git a/bin/tests/system/coverage/11-cutoff/expect b/bin/tests/system/coverage/11-cutoff/expect
new file mode 100644
index 0000000..bdf29d0
--- /dev/null
+++ b/bin/tests/system/coverage/11-cutoff/expect
@@ -0,0 +1,6 @@
+args="-l 1y -d 1h -m 2h"
+warn=0
+error=0
+ok=2
+retcode=0
+match=""
diff --git a/bin/tests/system/coverage/clean.sh b/bin/tests/system/coverage/clean.sh
new file mode 100644
index 0000000..253e8aa
--- /dev/null
+++ b/bin/tests/system/coverage/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f named-compilezone
+rm -f */K*.key
+rm -f */K*.private
+rm -rf coverage.*
+rm -f ns*/named.lock
diff --git a/bin/tests/system/coverage/prereq.sh b/bin/tests/system/coverage/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/coverage/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/coverage/setup.sh b/bin/tests/system/coverage/setup.sh
new file mode 100644
index 0000000..84ca137
--- /dev/null
+++ b/bin/tests/system/coverage/setup.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+KEYGEN="$KEYGEN -qr $RANDFILE"
+
+$SHELL clean.sh
+
+ln -s $CHECKZONE named-compilezone
+
+# Test 1: KSK goes inactive before successor is active
+dir=01-ksk-inactive
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -I +7mo $ksk1 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 2: ZSK goes inactive before successor is active
+dir=02-zsk-inactive
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -I +7mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 3: KSK is unpublished before its successor is published
+dir=03-ksk-unpublished
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -D +6mo $ksk1 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 4: ZSK is unpublished before its successor is published
+dir=04-zsk-unpublished
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -D +6mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 5: KSK deleted and successor published before KSK is deactivated
+# and successor activated.
+dir=05-ksk-unpub-active
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +8mo $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 6: ZSK deleted and successor published before ZSK is deactivated
+# and successor activated.
+dir=06-zsk-unpub-active
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +8mo $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 7: KSK rolled with insufficient delay after prepublication.
+dir=07-ksk-ttl
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+# allow only 1 day between publication and activation
+$SETTIME -K $dir -P +269d $ksk2 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 8: ZSK rolled with insufficient delay after prepublication.
+dir=08-zsk-ttl
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+# allow only 1 day between publication and activation
+$SETTIME -K $dir -P +269d $zsk2 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 9: KSK goes inactive before successor is active, but checking ZSKs
+dir=09-check-zsk
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -I +7mo $ksk1 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 10: ZSK goes inactive before successor is active, but checking KSKs
+dir=10-check-ksk
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -I +7mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 11: ZSK goes inactive before successor is active, but after cutoff
+dir=11-cutoff
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +18mo -D +2y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -I +16mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
diff --git a/bin/tests/system/coverage/tests.sh b/bin/tests/system/coverage/tests.sh
new file mode 100644
index 0000000..c5ba211
--- /dev/null
+++ b/bin/tests/system/coverage/tests.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+COVERAGE="$COVERAGE -c ./named-compilezone"
+
+status=0
+n=1
+
+matchall () {
+ file=$1
+ echo "$2" | while read matchline; do
+ grep "$matchline" $file > /dev/null 2>&1 || {
+ echo "FAIL"
+ return
+ }
+ done
+}
+
+echo_i "checking for DNSSEC key coverage issues"
+ret=0
+for dir in [0-9][0-9]-*; do
+ ret=0
+ echo_i "$dir"
+ args= warn= error= ok= retcode= match=
+ . $dir/expect
+ $COVERAGE $args -K $dir example.com > coverage.$n 2>&1
+
+ # check that return code matches expectations
+ found=$?
+ if [ $found -ne $retcode ]; then
+ echo "retcode was $found expected $retcode"
+ ret=1
+ fi
+
+ # check for correct number of errors
+ found=`grep ERROR coverage.$n | wc -l`
+ if [ $found -ne $error ]; then
+ echo "error count was $found expected $error"
+ ret=1
+ fi
+
+ # check for correct number of warnings
+ found=`grep WARNING coverage.$n | wc -l`
+ if [ $found -ne $warn ]; then
+ echo "warning count was $found expected $warn"
+ ret=1
+ fi
+
+ # check for correct number of OKs
+ found=`grep "No errors found" coverage.$n | wc -l`
+ if [ $found -ne $ok ]; then
+ echo "good count was $found expected $ok"
+ ret=1
+ fi
+
+ found=`matchall coverage.$n "$match"`
+ if [ "$found" = "FAIL" ]; then
+ echo "no match on '$match'"
+ ret=1
+ fi
+
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+done
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/database/clean.sh b/bin/tests/system/database/clean.sh
new file mode 100644
index 0000000..5a08ae0
--- /dev/null
+++ b/bin/tests/system/database/clean.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/named.conf ns1/named.run ns1/named.memstats
+rm -f dig.out.*
+rm -f ns*/named.lock
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..8fa82ae
--- /dev/null
+++ b/bin/tests/system/database/ns1/named1.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "database" {
+ type master;
+ 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..8238f54
--- /dev/null
+++ b/bin/tests/system/database/ns1/named2.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "database" {
+ type master;
+ 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..083ebf3
--- /dev/null
+++ b/bin/tests/system/database/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..7fa9337
--- /dev/null
+++ b/bin/tests/system/database/tests.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $try + 1`
+ test $ret -eq 0 && break
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/delzone/clean.sh b/bin/tests/system/delzone/clean.sh
new file mode 100644
index 0000000..9a1c79f
--- /dev/null
+++ b/bin/tests/system/delzone/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f rndc.out*
+rm -f */named.memstats
+rm -f ns2/*.nzf
+rm -f ns2/*.nzd ns2/*nzd-lock
+rm -f ns2/core*
+rm -f ns2/inline.db.jbk
+rm -f ns2/inline.db.signed
+rm -f ns2/inlineslave.bk*
+rm -f ns*/named.lock
+rm -f ns2/nzf-*
diff --git a/bin/tests/system/delzone/ns1/inlineslave.db b/bin/tests/system/delzone/ns1/inlineslave.db
new file mode 100644
index 0000000..625349e
--- /dev/null
+++ b/bin/tests/system/delzone/ns1/inlineslave.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN inlineslave.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/delzone/ns1/named.conf b/bin/tests/system/delzone/ns1/named.conf
new file mode 100644
index 0000000..8b6c441
--- /dev/null
+++ b/bin/tests/system/delzone/ns1/named.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "inlineslave.example" {
+ type master;
+ file "inlineslave.db";
+};
diff --git a/bin/tests/system/delzone/ns2/added.db b/bin/tests/system/delzone/ns2/added.db
new file mode 100644
index 0000000..9b54d19
--- /dev/null
+++ b/bin/tests/system/delzone/ns2/added.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+;$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/delzone/ns2/named.args b/bin/tests/system/delzone/ns2/named.args
new file mode 100644
index 0000000..bff47a9
--- /dev/null
+++ b/bin/tests/system/delzone/ns2/named.args
@@ -0,0 +1 @@
+-D ns2 -X named.lock -m record,size,mctx -T clienttest -c named.conf -g -U 4
diff --git a/bin/tests/system/delzone/ns2/named.conf b/bin/tests/system/delzone/ns2/named.conf
new file mode 100644
index 0000000..8532e50
--- /dev/null
+++ b/bin/tests/system/delzone/ns2/named.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion no;
+ allow-new-zones yes;
+};
+
+include "../../common/controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type master;
+ file "normal.db";
+};
diff --git a/bin/tests/system/delzone/ns2/normal.db b/bin/tests/system/delzone/ns2/normal.db
new file mode 100644
index 0000000..5045092
--- /dev/null
+++ b/bin/tests/system/delzone/ns2/normal.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/delzone/setup.sh b/bin/tests/system/delzone/setup.sh
new file mode 100644
index 0000000..1405375
--- /dev/null
+++ b/bin/tests/system/delzone/setup.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
diff --git a/bin/tests/system/delzone/tests.sh b/bin/tests/system/delzone/tests.sh
new file mode 100755
index 0000000..dd0a2de
--- /dev/null
+++ b/bin/tests/system/delzone/tests.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p 5300"
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+if [ -x "$PYTHON" ]; then
+echo "I:adding and deleting 20000 new zones ($n)"
+ret=0
+ time (
+ echo "I:adding"
+ $PYTHON << EOF
+import sys
+sys.path.insert(0, '../../../../bin/python')
+from isc import rndc
+r = rndc(('10.53.0.2', 9953), 'hmac-sha256', '1234abcd8765')
+for i in range(20000):
+ res = r.call('addzone z%d.example { type master; file "added.db"; };' % i)
+ if 'text' in res:
+ print ('I:n2:' + res['text'])
+EOF
+ )
+ time (
+ echo "I:deleting"
+ $PYTHON << EOF
+import sys
+sys.path.insert(0, '../../../../bin/python')
+from isc import rndc
+r = rndc(('10.53.0.2', 9953), 'hmac-sha256', '1234abcd8765')
+for i in range(20000):
+ res = r.call('delzone z%d.example' % i)
+ if 'text' in res:
+ print ('I:n2:' + res['text'])
+EOF
+ )
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/dialup/ns1/example.db b/bin/tests/system/dialup/ns1/example.db
new file mode 100644
index 0000000..e1f203e
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/example.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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 b/bin/tests/system/dialup/ns1/named.conf
new file mode 100644
index 0000000..d184cd8
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example." {
+ type master;
+ 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..7baffd2
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/root.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..ffb6dcf
--- /dev/null
+++ b/bin/tests/system/dialup/ns2/hint.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 1200 NS ns1.example
+ns1.example A 10.53.0.1
diff --git a/bin/tests/system/dialup/ns2/named.conf b/bin/tests/system/dialup/ns2/named.conf
new file mode 100644
index 0000000..a71d685
--- /dev/null
+++ b/bin/tests/system/dialup/ns2/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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.db";
+};
+
+zone "example." {
+ type slave;
+ dialup passive;
+ notify no;
+ file "example.bk";
+ masters { 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..ffb6dcf
--- /dev/null
+++ b/bin/tests/system/dialup/ns3/hint.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 1200 NS ns1.example
+ns1.example A 10.53.0.1
diff --git a/bin/tests/system/dialup/ns3/named.conf b/bin/tests/system/dialup/ns3/named.conf
new file mode 100644
index 0000000..7a7b424
--- /dev/null
+++ b/bin/tests/system/dialup/ns3/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "example." {
+ type slave;
+ dialup refresh;
+ notify no;
+ file "example.bk";
+ masters { 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..d97a021
--- /dev/null
+++ b/bin/tests/system/dialup/setup.sh
@@ -0,0 +1,11 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns2/example.bk
+rm -f ns3/example.bk
diff --git a/bin/tests/system/dialup/tests.sh b/bin/tests/system/dialup/tests.sh
new file mode 100644
index 0000000..a910783
--- /dev/null
+++ b/bin/tests/system/dialup/tests.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+rm -f dig.out.*
+
+DIGOPTS="+norec +tcp +noadd +nosea +nostat +noquest +nocmd -p 5300"
+
+# 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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/digcomp.pl b/bin/tests/system/digcomp.pl
new file mode 100644
index 0000000..5c2e85c
--- /dev/null
+++ b/bin/tests/system/digcomp.pl
@@ -0,0 +1,118 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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"} = $_;
+ }
+ }
+}
+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;
+ }
+ }
+}
+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..e69de29
--- /dev/null
+++ b/bin/tests/system/digdelv/ans4/startme
diff --git a/bin/tests/system/digdelv/clean.sh b/bin/tests/system/digdelv/clean.sh
new file mode 100644
index 0000000..681c027
--- /dev/null
+++ b/bin/tests/system/digdelv/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*test*
+rm -f delv.out.test*
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f ns*/named.lock
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..92acac9
--- /dev/null
+++ b/bin/tests/system/digdelv/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ 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-enable no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type master;
+ 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..76ed2a0
--- /dev/null
+++ b/bin/tests/system/digdelv/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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 b/bin/tests/system/digdelv/ns2/example.db
new file mode 100644
index 0000000..f4e30f5
--- /dev/null
+++ b/bin/tests/system/digdelv/ns2/example.db
@@ -0,0 +1,57 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+
+xn--caf-dma A 10.1.2.3
+
+foo TXT "testing"
+foo A 10.0.1.0
+foo SSHFP 2 1 123456789abcdef67890123456789abcdef67890
+
+;;
+;; we are not testing DNSSEC behavior, so we don't care about the semantics
+;; of the following records.
+dnskey 300 DNSKEY 256 3 1 (
+ AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg
+ +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD
+ Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R
+ b9VIE5x7KNHAYTvTO5d4S8M=
+ )
+
+; 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..98bc5ac
--- /dev/null
+++ b/bin/tests/system/digdelv/ns2/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
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..2df5417
--- /dev/null
+++ b/bin/tests/system/digdelv/ns3/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3 dscp 1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable no;
+ dnssec-validation no;
+ server-id "ns3";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/digdelv/prereq.sh b/bin/tests/system/digdelv/prereq.sh
new file mode 100644
index 0000000..de147a4
--- /dev/null
+++ b/bin/tests/system/digdelv/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/digdelv/setup.sh b/bin/tests/system/digdelv/setup.sh
new file mode 100644
index 0000000..c9f645b
--- /dev/null
+++ b/bin/tests/system/digdelv/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh
new file mode 100644
index 0000000..95bd074
--- /dev/null
+++ b/bin/tests/system/digdelv/tests.sh
@@ -0,0 +1,652 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+DIGOPTS="-p ${PORT}"
+SENDCMD="$PERL $SYSTEMTESTTOP/send.pl 10.53.0.4 ${EXTRAPORT1}"
+
+if [ -x ${DIG} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking dig short form works ($n)"
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 +short a a.example > dig.out.test$n || ret=1
+ if test `wc -l < dig.out.test$n` != 1 ; then ret=1 ; fi
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig split width works ($n)"
+ ret=0
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +unknownformat works ($n)"
+ ret=0
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig with reverse lookup works ($n)"
+ ret=0
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig over TCP works ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +multi +norrcomments works for dnskey (when default is rrcomments)($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +multi +norrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +multi +norrcomments works for soa (when default is rrcomments)($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +multi +norrcomments SOA example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +rrcomments works for DNSKEY($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +short +rrcomments works for DNSKEY ($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +short +nosplit works($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +short +nosplit DNSKEY dnskey.example > dig.out.test$n || ret=1
+ grep "Z8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=$" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +short +rrcomments works($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1
+ grep "S8M= ; ZSK; alg = RSAMD5 ; key id = 30795$" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +noheader-only works ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +short +rrcomments works($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1
+ grep "S8M= ; ZSK; alg = RSAMD5 ; key id = 30795$" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ echo_i "checking dig +header-only works ($n)"
+ ret=0
+ $DIG $DIGOPTS +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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +header-only works (with class and type set) ($n)"
+ ret=0
+ $DIG $DIGOPTS +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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +zflag works, and that BIND properly ignores it ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +qr +ednsopt=08 does not cause an INSIST failure ($n)"
+ ret=0
+ $DIG $DIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ echo_i "checking dig +ttlunits works ($n)"
+ ret=0
+ $DIG $DIGOPTS +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 $DIGOPTS +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 $DIGOPTS +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 $DIGOPTS +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 $DIGOPTS +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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig respects precedence of options with +ttlunits ($n)"
+ ret=0
+ $DIG $DIGOPTS +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 $DIGOPTS +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 $DIGOPTS +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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $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
+ $DIG $DIGOPTS -d +tcp @10.53.0.4 +retry=1 +time=1 +domain=bar foo > dig.out.test$n 2>&1 && ret=1
+ l=`grep "trying origin bar" dig.out.test$n | wc -l`
+ [ ${l:-0} -eq 2 ] || ret=1
+ grep "using root origin" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig -6 -4 ($n)"
+ ret=0
+ $DIG $DIGOPTS +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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $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 $DIGOPTS +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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=`expr $n + 1`
+ echo_i "checking dig @IPv4addr -6 +mapped A a.example ($n)"
+ if $TESTSOCK6 fd92:7065:b8e:ffff::2 2>/dev/null && [ `uname -s` != "OpenBSD" ]
+ then
+ ret=0
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.2 -6 +mapped 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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ else
+ echo_i "IPv6 or IPv4-to-IPv6 mapping unavailable; skipping"
+ fi
+
+ n=`expr $n + 1`
+ echo_i "checking dig +tcp @IPv4addr -6 +nomapped A a.example ($n)"
+ if $TESTSOCK6 fd92:7065:b8e:ffff::2 2>/dev/null
+ then
+ ret=0
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.2 -6 +nomapped 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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+ n=`expr $n + 1`
+
+ echo_i "checking dig +notcp @IPv4addr -6 +nomapped A a.example ($n)"
+ if $TESTSOCK6 fd92:7065:b8e:ffff::2 2>/dev/null
+ then
+ ret=0
+ ret=0
+ $DIG $DIGOPTS +notcp @10.53.0.2 -6 +nomapped 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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=`expr $n + 1`
+ echo_i "checking dig +subnet ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +subnet +subnet ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $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 $DIGOPTS +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
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +subnet=0/0 ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +subnet=0 ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +subnet=::/0 ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +ednsopt=8:00000000 (family=0, source=0, scope=0) ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +ednsopt=8:00030000 (family=3, source=0, scope=0) ($n)"
+ ret=0
+ $DIG $DIGOPTS +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
+ lines=`grep "CLIENT-SUBNET: 00 03 00 00" dig.out.test$n | wc -l`
+ [ ${lines:-0} -eq 1 ] || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $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 $DIGOPTS +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
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +sp works as an abbreviated form of split ($n)"
+ ret=0
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig -c works ($n)"
+ ret=0
+ $DIG $DIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +dscp ($n)"
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 +dscp=32 a a.example > /dev/null 2>&1 || ret=1
+ $DIG $DIGOPTS @10.53.0.3 +dscp=-1 a a.example > /dev/null 2>&1 && ret=1
+ $DIG $DIGOPTS @10.53.0.3 +dscp=64 a a.example > /dev/null 2>&1 && ret=1
+ #TODO add a check to make sure dig is actually setting the dscp on the query
+ #we might have to add better logging to named for this
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +ednsopt with option number ($n)"
+ ret=0
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking dig +ednsopt with option name ($n)"
+ ret=0
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking that dig warns about .local queries ($n)"
+ ret=0
+ $DIG $DIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "check that dig processes +ednsopt=key-tag and FORMERR is returned ($n)"
+ $DIG $DIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "check that dig processes +ednsopt=key-tag:<value-list> ($n)"
+ $DIG $DIGOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "check that dig processes +ednsopt=key-tag:<malformed-value-list> and FORMERR is returned ($n)"
+ ret=0
+ $DIG $DIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "check that dig handles malformed option '+ednsopt=:' gracefully ($n)"
+ ret=0
+ $DIG $DIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+else
+ echo_i "$DIG is needed, so skipping these dig tests"
+fi
+
+MDIGOPTS="-p ${PORT}"
+if [ -x ${MDIG} ] ; then
+ n=`expr $n + 1`
+ echo_i "check that mdig handles malformed option '+ednsopt=:' gracefully ($n)"
+ ret=0
+ $MDIG $MDIGOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+else
+ echo_i "$MDIG is needed, so skipping these mdig tests"
+fi
+
+# using delv insecure mode as not testing dnssec here
+DELVOPTS="-i -p ${PORT}"
+
+if [ -x ${DELV} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking delv short form works ($n)"
+ ret=0
+ $DELV $DELVOPTS @10.53.0.3 +short a a.example > delv.out.test$n || ret=1
+ if test `wc -l < delv.out.test$n` != 1 ; then ret=1 ; fi
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv split width works ($n)"
+ ret=0
+ $DELV $DELVOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +unknownformat works ($n)"
+ ret=0
+ $DELV $DELVOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv -4 -6 ($n)"
+ ret=0
+ $DELV $DELVOPTS @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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $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 $DELVOPTS @fd92:7065:b8e:ffff::3 @10.53.0.3 -6 -t txt foo.example > delv.out.test$n 2>&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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=`expr $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 $DELVOPTS @10.53.0.3 @fd92:7065:b8e:ffff::3 -4 -t txt foo.example > delv.out.test$n 2>&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 != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=`expr $n + 1`
+ echo_i "checking delv with reverse lookup works ($n)"
+ ret=0
+ $DELV $DELVOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv over TCP works ($n)"
+ ret=0
+ $DELV $DELVOPTS +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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +multi +norrcomments works for dnskey (when default is rrcomments)($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +multi +norrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +multi +norrcomments works for soa (when default is rrcomments)($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +multi +norrcomments SOA example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +rrcomments works for DNSKEY($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +short +rrcomments works for DNSKEY ($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +short +rrcomments works ($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1
+ grep "S8M= ; ZSK; alg = RSAMD5 ; key id = 30795$" < delv.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +short +nosplit works ($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +short +nosplit DNSKEY dnskey.example > delv.out.test$n || ret=1
+ grep "Z8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=" < delv.out.test$n > /dev/null || ret=1
+ if test `wc -l < delv.out.test$n` != 1 ; then ret=1 ; fi
+ f=`awk '{print NF}' < delv.out.test$n`
+ test "${f:-0}" -eq 14 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +short +nosplit +norrcomments works ($n)"
+ ret=0
+ $DELV $DELVOPTS +tcp @10.53.0.3 +short +nosplit +norrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1
+ grep "Z8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=$" < delv.out.test$n > /dev/null || ret=1
+ if test `wc -l < delv.out.test$n` != 1 ; then ret=1 ; fi
+ f=`awk '{print NF}' < delv.out.test$n`
+ test "${f:-0}" -eq 4 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +sp works as an abbriviated form of split ($n)"
+ ret=0
+ $DELV $DELVOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv +sh works as an abbriviated form of short ($n)"
+ ret=0
+ $DELV $DELVOPTS @10.53.0.3 +sh a a.example > delv.out.test$n || ret=1
+ if test `wc -l < delv.out.test$n` != 1 ; then ret=1 ; fi
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv -c IN works ($n)"
+ ret=0
+ $DELV $DELVOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking delv -c CH is ignored, and treated like IN ($n)"
+ ret=0
+ $DELV $DELVOPTS @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
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+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/ditch.pl b/bin/tests/system/ditch.pl
new file mode 100644
index 0000000..8f1b652
--- /dev/null
+++ b/bin/tests/system/ditch.pl
@@ -0,0 +1,85 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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/dlv/clean.sh b/bin/tests/system/dlv/clean.sh
new file mode 100644
index 0000000..94cadc6
--- /dev/null
+++ b/bin/tests/system/dlv/clean.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.run
+rm -f ns*/named.conf
+rm -f ns1/K*
+rm -f ns1/dsset-*
+rm -f ns1/*.signed
+rm -f ns1/signer.err
+rm -f ns1/root.db
+rm -f ns2/K*
+rm -f ns2/dlvset-*
+rm -f ns2/dsset-*
+rm -f ns2/*.signed
+rm -f ns2/*.pre
+rm -f ns2/signer.err
+rm -f ns2/druz.db
+rm -f ns3/K*
+rm -f ns3/*.db
+rm -f ns3/*.signed
+rm -f ns3/dlvset-*
+rm -f ns3/dsset-*
+rm -f ns3/keyset-*
+rm -f ns1/trusted.conf ns5/trusted.conf
+rm -f ns3/trusted-dlv.conf ns5/trusted-dlv.conf
+rm -f ns3/signer.err
+rm -f ns6/K*
+rm -f ns6/*.db
+rm -f ns6/*.signed
+rm -f ns6/dsset-*
+rm -f ns6/signer.err
+rm -f */named.memstats
+rm -f dig.out.ns*.test*
+rm -f ns*/named.lock
diff --git a/bin/tests/system/dlv/ns1/named.conf.in b/bin/tests/system/dlv/ns1/named.conf.in
new file mode 100644
index 0000000..337558f
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-enable yes;
+};
+
+zone "." { type master; file "root.signed"; };
+zone "rootservers.utld" { type master; file "rootservers.utld.db"; };
diff --git a/bin/tests/system/dlv/ns1/root.db.in b/bin/tests/system/dlv/ns1/root.db.in
new file mode 100644
index 0000000..a4d4bd9
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/root.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.rootservers.utld hostmaster.ns.rootservers.utld (
+ 1 3600 1200 604800 60 )
+@ NS ns.rootservers.utld
+ns A 10.53.0.1
+;
+utld NS ns.utld
+ns.utld A 10.53.0.2
+druz NS ns.druz
+ns.druz A 10.53.0.2
diff --git a/bin/tests/system/dlv/ns1/rootservers.utld.db b/bin/tests/system/dlv/ns1/rootservers.utld.db
new file mode 100644
index 0000000..8491ed0
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/rootservers.utld.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns1/sign.sh b/bin/tests/system/dlv/ns1/sign.sh
new file mode 100755
index 0000000..b815162
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/sign.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=dlv
+
+(cd ../ns2 && $SHELL -e ./sign.sh || exit 1)
+
+echo_i "dlv/ns1/sign.sh"
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+outfile=root.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -g -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+
+echo_i "signed $zone"
+
+keyfile_to_trusted_keys $keyname2 > trusted.conf
+cp trusted.conf ../ns5
diff --git a/bin/tests/system/dlv/ns2/druz.db.in b/bin/tests/system/dlv/ns2/druz.db.in
new file mode 100644
index 0000000..4e0f892
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/druz.db.in
@@ -0,0 +1,47 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.2
+;
+rootservers NS ns.rootservers
+ns.rootservers A 10.53.0.1
+;
+;
+child1 NS ns.child1
+ns.child1 A 10.53.0.3
+;
+child2 NS ns.child2
+ns.child2 A 10.53.0.4
+;
+child3 NS ns.child3
+ns.child3 A 10.53.0.3
+;
+child4 NS ns.child4
+ns.child4 A 10.53.0.3
+;
+child5 NS ns.child5
+ns.child5 A 10.53.0.3
+;
+child6 NS ns.child6
+ns.child6 A 10.53.0.4
+;
+child7 NS ns.child7
+ns.child7 A 10.53.0.3
+;
+child8 NS ns.child8
+ns.child8 A 10.53.0.3
+;
+child9 NS ns.child9
+ns.child9 A 10.53.0.3
+;
+child10 NS ns.child10
+ns.child10 A 10.53.0.3
diff --git a/bin/tests/system/dlv/ns2/hints b/bin/tests/system/dlv/ns2/hints
new file mode 100644
index 0000000..381e86b
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns2/named.conf.in b/bin/tests/system/dlv/ns2/named.conf.in
new file mode 100644
index 0000000..b08bd13
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+};
+
+zone "." { type hint; file "hints"; };
+zone "utld" { type master; file "utld.db"; };
+zone "druz" { type master; file "druz.signed"; };
diff --git a/bin/tests/system/dlv/ns2/sign.sh b/bin/tests/system/dlv/ns2/sign.sh
new file mode 100755
index 0000000..6f84d7a
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/sign.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=dlv
+
+(cd ../ns3 && $SHELL -e ./sign.sh || exit 1)
+
+echo_i "dlv/ns2/sign.sh"
+
+zone=druz.
+infile=druz.db.in
+zonefile=druz.db
+outfile=druz.pre
+dlvzone=utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -g -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+
+$CHECKZONE -q -D -i none druz druz.pre |
+sed '/IN DNSKEY/s/\([a-z0-9A-Z/]\{10\}\)[a-z0-9A-Z/]\{16\}/\1XXXXXXXXXXXXXXXX/'> druz.signed
+
+echo_i "signed $zone"
diff --git a/bin/tests/system/dlv/ns2/utld.db b/bin/tests/system/dlv/ns2/utld.db
new file mode 100644
index 0000000..66f559d
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/utld.db
@@ -0,0 +1,49 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.2
+;
+rootservers NS ns.rootservers
+ns.rootservers A 10.53.0.1
+;
+dlv NS ns.dlv
+ns.dlv A 10.53.0.3
+;
+child1 NS ns.child1
+ns.child1 A 10.53.0.3
+;
+child2 NS ns.child2
+ns.child2 A 10.53.0.4
+;
+child3 NS ns.child3
+ns.child3 A 10.53.0.3
+;
+child4 NS ns.child4
+ns.child4 A 10.53.0.3
+;
+child5 NS ns.child5
+ns.child5 A 10.53.0.3
+;
+child6 NS ns.child6
+ns.child6 A 10.53.0.4
+;
+child7 NS ns.child7
+ns.child7 A 10.53.0.3
+;
+child8 NS ns.child8
+ns.child8 A 10.53.0.3
+;
+child9 NS ns.child9
+ns.child9 A 10.53.0.3
+;
+child10 NS ns.child10
+ns.child10 A 10.53.0.3
diff --git a/bin/tests/system/dlv/ns3/child.db.in b/bin/tests/system/dlv/ns3/child.db.in
new file mode 100644
index 0000000..11df807
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/child.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.3
+foo TXT foo
+bar TXT bar
+grand NS ns.grand
+ns.grand A 10.53.0.6
diff --git a/bin/tests/system/dlv/ns3/dlv.db.in b/bin/tests/system/dlv/ns3/dlv.db.in
new file mode 100644
index 0000000..fdc8ce9
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/dlv.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.3
diff --git a/bin/tests/system/dlv/ns3/hints b/bin/tests/system/dlv/ns3/hints
new file mode 100644
index 0000000..381e86b
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns3/named.conf.in b/bin/tests/system/dlv/ns3/named.conf.in
new file mode 100644
index 0000000..42d712b
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-enable yes;
+};
+
+zone "." { type hint; file "hints"; };
+zone "dlv.utld" { type master; file "dlv.signed"; };
+zone "child1.utld" { type master; file "child1.signed"; }; // dlv
+zone "child3.utld" { type master; file "child3.signed"; }; // dlv
+zone "child4.utld" { type master; file "child4.signed"; }; // dlv
+zone "child5.utld" { type master; file "child5.signed"; }; // dlv
+zone "child7.utld" { type master; file "child7.signed"; }; // no dlv
+zone "child8.utld" { type master; file "child8.signed"; }; // no dlv
+zone "child9.utld" { type master; file "child9.signed"; }; // dlv
+zone "child10.utld" { type master; file "child.db.in"; }; // dlv unsigned
+zone "child1.druz" { type master; file "child1.druz.signed"; }; // dlv
+zone "child3.druz" { type master; file "child3.druz.signed"; }; // dlv
+zone "child4.druz" { type master; file "child4.druz.signed"; }; // dlv
+zone "child5.druz" { type master; file "child5.druz.signed"; }; // dlv
+zone "child7.druz" { type master; file "child7.druz.signed"; }; // no dlv
+zone "child8.druz" { type master; file "child8.druz.signed"; }; // no dlv
+zone "child9.druz" { type master; file "child9.druz.signed"; }; // dlv
+zone "child10.druz" { type master; file "child.db.in"; }; // dlv unsigned
diff --git a/bin/tests/system/dlv/ns3/sign.sh b/bin/tests/system/dlv/ns3/sign.sh
new file mode 100755
index 0000000..bcc9922
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/sign.sh
@@ -0,0 +1,286 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+(cd ../ns6 && $SHELL -e ./sign.sh)
+
+echo_i "dlv/ns3/sign.sh"
+
+dlvzone=dlv.utld.
+dlvsets=
+dssets=
+
+zone=child1.utld.
+infile=child.db.in
+zonefile=child1.utld.db
+outfile=child1.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child3.utld.
+infile=child.db.in
+zonefile=child3.utld.db
+outfile=child3.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child4.utld.
+infile=child.db.in
+zonefile=child4.utld.db
+outfile=child4.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child5.utld.
+infile=child.db.in
+zonefile=child5.utld.db
+outfile=child5.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child7.utld.
+infile=child.db.in
+zonefile=child7.utld.db
+outfile=child7.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child8.utld.
+infile=child.db.in
+zonefile=child8.utld.db
+outfile=child8.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child9.utld.
+infile=child.db.in
+zonefile=child9.utld.db
+outfile=child9.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=child10.utld.
+infile=child.db.in
+zonefile=child10.utld.db
+outfile=child10.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=child1.druz.
+infile=child.db.in
+zonefile=child1.druz.db
+outfile=child1.druz.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child3.druz.
+infile=child.db.in
+zonefile=child3.druz.db
+outfile=child3.druz.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child4.druz.
+infile=child.db.in
+zonefile=child4.druz.db
+outfile=child4.druz.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child5.druz.
+infile=child.db.in
+zonefile=child5.druz.db
+outfile=child5.druz.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child7.druz.
+infile=child.db.in
+zonefile=child7.druz.db
+outfile=child7.druz.signed
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP
+cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child8.druz.
+infile=child.db.in
+zonefile=child8.druz.db
+outfile=child8.druz.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=child9.druz.
+infile=child.db.in
+zonefile=child9.druz.db
+outfile=child9.druz.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=child10.druz.
+infile=child.db.in
+zonefile=child10.druz.db
+outfile=child10.druz.signed
+dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP"
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=dlv.utld.
+infile=dlv.db.in
+zonefile=dlv.utld.db
+outfile=dlv.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $dlvsets $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_trusted_keys $keyname2 > trusted-dlv.conf
+cp trusted-dlv.conf ../ns5
+
+cp $dssets ../ns2
diff --git a/bin/tests/system/dlv/ns4/child.db b/bin/tests/system/dlv/ns4/child.db
new file mode 100644
index 0000000..c123f70
--- /dev/null
+++ b/bin/tests/system/dlv/ns4/child.db
@@ -0,0 +1,34 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.3
+;
+rootservers NS ns.rootservers
+ns.rootservers A 10.53.0.1
+;
+child1 NS ns.child1
+ns.child1 A 10.53.0.3
+;
+child2 NS ns.child2
+ns.child2 A 10.53.0.4
+;
+child3 NS ns.child3
+ns.child3 A 10.53.0.3
+;
+child4 NS ns.child4
+ns.child4 A 10.53.0.3
+;
+child5 NS ns.child5
+ns.child5 A 10.53.0.3
+;
+child6 NS ns.child5
+ns.child6 A 10.53.0.4
diff --git a/bin/tests/system/dlv/ns4/hints b/bin/tests/system/dlv/ns4/hints
new file mode 100644
index 0000000..381e86b
--- /dev/null
+++ b/bin/tests/system/dlv/ns4/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns4/named.conf.in b/bin/tests/system/dlv/ns4/named.conf.in
new file mode 100644
index 0000000..805b5f3
--- /dev/null
+++ b/bin/tests/system/dlv/ns4/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-enable no;
+};
+
+zone "." { type hint; file "hints"; };
+zone "child2.utld" { type master; file "child.db"; };
+zone "child6.utld" { type master; file "child.db"; };
diff --git a/bin/tests/system/dlv/ns5/hints b/bin/tests/system/dlv/ns5/hints
new file mode 100644
index 0000000..381e86b
--- /dev/null
+++ b/bin/tests/system/dlv/ns5/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns5/named.conf.in b/bin/tests/system/dlv/ns5/named.conf.in
new file mode 100644
index 0000000..9e3b195
--- /dev/null
+++ b/bin/tests/system/dlv/ns5/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "trusted.conf";
+include "trusted-dlv.conf";
+
+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;
+ acache-enable yes;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-lookaside "." trust-anchor "dlv.utld";
+};
+
+zone "." { type hint; file "hints"; };
diff --git a/bin/tests/system/dlv/ns5/rndc.conf b/bin/tests/system/dlv/ns5/rndc.conf
new file mode 100644
index 0000000..02bce92
--- /dev/null
+++ b/bin/tests/system/dlv/ns5/rndc.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key "cc64b3d1db63fc88d7cb5d2f9f57d258" {
+ algorithm hmac-sha256;
+ secret "34f88008d07deabbe65bd01f1d233d47";
+};
+
+options {
+ default-server 10.53.0.5;
+ default-port 5353;
+};
diff --git a/bin/tests/system/dlv/ns6/child.db.in b/bin/tests/system/dlv/ns6/child.db.in
new file mode 100644
index 0000000..09a942e
--- /dev/null
+++ b/bin/tests/system/dlv/ns6/child.db.in
@@ -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 http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns hostmaster.ns6 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.6
+foo TXT foo
+bar TXT bar
diff --git a/bin/tests/system/dlv/ns6/hints b/bin/tests/system/dlv/ns6/hints
new file mode 100644
index 0000000..381e86b
--- /dev/null
+++ b/bin/tests/system/dlv/ns6/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns6/named.conf.in b/bin/tests/system/dlv/ns6/named.conf.in
new file mode 100644
index 0000000..fe5c68d
--- /dev/null
+++ b/bin/tests/system/dlv/ns6/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ notify yes;
+ dnssec-enable yes;
+};
+
+zone "." { type hint; file "hints"; };
+zone "grand.child1.utld" { type master; file "grand.child1.signed"; };
+zone "grand.child3.utld" { type master; file "grand.child3.signed"; };
+zone "grand.child4.utld" { type master; file "grand.child4.signed"; };
+zone "grand.child5.utld" { type master; file "grand.child5.signed"; };
+zone "grand.child7.utld" { type master; file "grand.child7.signed"; };
+zone "grand.child8.utld" { type master; file "grand.child8.signed"; };
+zone "grand.child9.utld" { type master; file "grand.child9.signed"; };
+zone "grand.child10.utld" { type master; file "grand.child10.signed"; };
+zone "grand.child1.druz" { type master; file "grand.child1.druz.signed"; };
+zone "grand.child3.druz" { type master; file "grand.child3.druz.signed"; };
+zone "grand.child4.druz" { type master; file "grand.child4.druz.signed"; };
+zone "grand.child5.druz" { type master; file "grand.child5.druz.signed"; };
+zone "grand.child7.druz" { type master; file "grand.child7.druz.signed"; };
+zone "grand.child8.druz" { type master; file "grand.child8.druz.signed"; };
+zone "grand.child9.druz" { type master; file "grand.child9.druz.signed"; };
+zone "grand.child10.druz" { type master; file "grand.child10.druz.signed"; };
diff --git a/bin/tests/system/dlv/ns6/sign.sh b/bin/tests/system/dlv/ns6/sign.sh
new file mode 100755
index 0000000..1e39862
--- /dev/null
+++ b/bin/tests/system/dlv/ns6/sign.sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=dlv
+
+echo_i "dlv/ns6/sign.sh"
+
+zone=grand.child1.utld.
+infile=child.db.in
+zonefile=grand.child1.utld.db
+outfile=grand.child1.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child3.utld.
+infile=child.db.in
+zonefile=grand.child3.utld.db
+outfile=grand.child3.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child4.utld.
+infile=child.db.in
+zonefile=grand.child4.utld.db
+outfile=grand.child4.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child5.utld.
+infile=child.db.in
+zonefile=grand.child5.utld.db
+outfile=grand.child5.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child7.utld.
+infile=child.db.in
+zonefile=grand.child7.utld.db
+outfile=grand.child7.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child8.utld.
+infile=child.db.in
+zonefile=grand.child8.utld.db
+outfile=grand.child8.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child9.utld.
+infile=child.db.in
+zonefile=grand.child9.utld.db
+outfile=grand.child9.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=grand.child10.utld.
+infile=child.db.in
+zonefile=grand.child10.utld.db
+outfile=grand.child10.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=grand.child1.druz.
+infile=child.db.in
+zonefile=grand.child1.druz.db
+outfile=grand.child1.druz.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child3.druz.
+infile=child.db.in
+zonefile=grand.child3.druz.db
+outfile=grand.child3.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child4.druz.
+infile=child.db.in
+zonefile=grand.child4.druz.db
+outfile=grand.child4.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child5.druz.
+infile=child.db.in
+zonefile=grand.child5.druz.db
+outfile=grand.child5.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child7.druz.
+infile=child.db.in
+zonefile=grand.child7.druz.db
+outfile=grand.child7.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child8.druz.
+infile=child.db.in
+zonefile=grand.child8.druz.db
+outfile=grand.child8.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+
+zone=grand.child9.druz.
+infile=child.db.in
+zonefile=grand.child9.druz.db
+outfile=grand.child9.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=grand.child10.druz.
+infile=child.db.in
+zonefile=grand.child10.druz.db
+outfile=grand.child10.druz.signed
+dlvzone=dlv.druz.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
diff --git a/bin/tests/system/dlv/prereq.sh b/bin/tests/system/dlv/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/dlv/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/dlv/setup.sh b/bin/tests/system/dlv/setup.sh
new file mode 100644
index 0000000..0a2aad7
--- /dev/null
+++ b/bin/tests/system/dlv/setup.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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 -e sign.sh)
diff --git a/bin/tests/system/dlv/tests.sh b/bin/tests/system/dlv/tests.sh
new file mode 100644
index 0000000..fdf31d9
--- /dev/null
+++ b/bin/tests/system/dlv/tests.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+echo_i "checking that DNSKEY reference by DLV validates as secure ($n)"
+ret=0
+$DIG $DIGOPTS child1.utld dnskey @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that child DNSKEY reference by DLV validates as secure ($n)"
+ret=0
+$DIG $DIGOPTS grand.child1.utld dnskey @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that SOA reference by DLV in a DRUZ with DS validates as secure ($n)"
+ret=0
+$DIG $DIGOPTS child1.druz soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that child SOA reference by DLV in a DRUZ with DS validates as secure ($n)"
+ret=0
+$DIG $DIGOPTS grand.child1.druz soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dlz/clean.sh b/bin/tests/system/dlz/clean.sh
new file mode 100644
index 0000000..e38b806
--- /dev/null
+++ b/bin/tests/system/dlz/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/DNAME=10=example.net.= b/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/DNAME=10=example.net.=
new file mode 100644
index 0000000..be99eb3
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/DNAME=10=example.net.=
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file is not read by the filesystem driver.
+This is the file for "DNAME 10 example.net.".
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/NS=10=example.com.= b/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/NS=10=example.com.=
new file mode 100644
index 0000000..cca17c3
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/NS=10=example.com.=
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file is not read by the filesystem driver.
+This is the file for "NS 10 example.com.".
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/SOA=10=ns.example.com.=root.example.com.=None=None=None=None=None= b/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/SOA=10=ns.example.com.=root.example.com.=None=None=None=None=None=
new file mode 100644
index 0000000..f2ca5de
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/broken/dns.d/@/SOA=10=ns.example.com.=root.example.com.=None=None=None=None=None=
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file is not read by the filesystem driver.
+This is the file for "SOA 10 ns.example.com. root.example.com. 2010062900 None None None None" which is a malformed SOA record.
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/DNAME=10=example.net.= b/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/DNAME=10=example.net.=
new file mode 100644
index 0000000..be99eb3
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/DNAME=10=example.net.=
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file is not read by the filesystem driver.
+This is the file for "DNAME 10 example.net.".
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/NS=10=example.com.= b/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/NS=10=example.com.=
new file mode 100644
index 0000000..cca17c3
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/NS=10=example.com.=
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file is not read by the filesystem driver.
+This is the file for "NS 10 example.com.".
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/SOA=10=ns.example.com.=root.example.com.=2010062900=0=0=0=10= b/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/SOA=10=ns.example.com.=root.example.com.=2010062900=0=0=0=10=
new file mode 100644
index 0000000..bb5ebac
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/example/dns.d/@/SOA=10=ns.example.com.=root.example.com.=2010062900=0=0=0=10=
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file is not read by the filesystem driver.
+This is the file for "SOA 10 ns.example.com. root.example.com. 2010062900 0 0 0 10".
diff --git a/bin/tests/system/dlz/ns1/dns-root/com/example/xfr.d/10.53.0.1 b/bin/tests/system/dlz/ns1/dns-root/com/example/xfr.d/10.53.0.1
new file mode 100644
index 0000000..70deea6
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/dns-root/com/example/xfr.d/10.53.0.1
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The contents of this file are not read by the filesystem driver.
+The presence of this file allows 10.53.0.1 to transfer this zone.
diff --git a/bin/tests/system/dlz/ns1/named.conf.in b/bin/tests/system/dlz/ns1/named.conf.in
new file mode 100644
index 0000000..273ff02
--- /dev/null
+++ b/bin/tests/system/dlz/ns1/named.conf.in
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+dlz fszone {
+ database "filesystem dns-root/ dns.d xfr.d 0 =";
+};
diff --git a/bin/tests/system/dlz/prereq.sh.in b/bin/tests/system/dlz/prereq.sh.in
new file mode 100644
index 0000000..afec653
--- /dev/null
+++ b/bin/tests/system/dlz/prereq.sh.in
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if [ "@DLZ_SYSTEM_TEST@" != "filesystem" ]; then
+ echo_i "DLZ filesystem driver not supported"
+ exit 255
+fi
+exit 0
diff --git a/bin/tests/system/dlz/setup.sh b/bin/tests/system/dlz/setup.sh
new file mode 100644
index 0000000..7e60631
--- /dev/null
+++ b/bin/tests/system/dlz/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/dlz/tests.sh b/bin/tests/system/dlz/tests.sh
new file mode 100644
index 0000000..78f74dc
--- /dev/null
+++ b/bin/tests/system/dlz/tests.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+# Check the example.com. domain
+
+echo_i "checking DNAME at apex works ($n)"
+ret=0
+$DIG $DIGOPTS +norec foo.example.com. \
+ @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 "example.com..*DNAME.*example.net." dig.out.ns1.test$n > /dev/null || ret=1
+grep "foo.example.com..*CNAME.*foo.example.net." dig.out.ns1.test$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns1.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking DLZ IXFR=2010062899 (less than serial) ($n)"
+ret=0
+$DIG $DIGOPTS ixfr=2010062899 example.com @10.53.0.1 +all > dig.out.ns1.test$n
+grep "example.com..*IN.IXFR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "example.com..*10.IN.DNAME.example.net." dig.out.ns1.test$n > /dev/null || ret=1
+grep "example.com..*10.IN.NS.example.com." dig.out.ns1.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking DLZ IXFR=2010062900 (equal serial) ($n)"
+ret=0
+$DIG $DIGOPTS ixfr=2010062900 example.com @10.53.0.1 +all > dig.out.ns1.test$n
+grep "example.com..*IN.IXFR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "example.com..*10.IN.DNAME.example.net." dig.out.ns1.test$n > /dev/null && ret=1
+grep "example.com..*10.IN.NS.example.com." dig.out.ns1.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking DLZ IXFR=2010062901 (greater than serial) ($n)"
+ret=0
+$DIG $DIGOPTS ixfr=2010062901 example.com @10.53.0.1 +all > dig.out.ns1.test$n
+grep "example.com..*IN.IXFR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "example.com..*10.IN.DNAME.example.net." dig.out.ns1.test$n > /dev/null && ret=1
+grep "example.com..*10.IN.NS.example.com." dig.out.ns1.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking DLZ with a malformed SOA record"
+ret=0
+$DIG $DIGOPTS broken.com type600 @10.53.0.1 > dig.out.ns1.test$n
+grep status: dig.out.ns1.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dlzexternal/Makefile.in b/bin/tests/system/dlzexternal/Makefile.in
new file mode 100644
index 0000000..dd04bd7
--- /dev/null
+++ b/bin/tests/system/dlzexternal/Makefile.in
@@ -0,0 +1,46 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+CDEFINES = @CRYPTO@
+CWARNINGS =
+
+LIBS = @LIBS@
+
+SO_TARGETS = driver.@SO@
+TARGETS = @SO_TARGETS@
+
+SRCS = driver.c
+
+SO_OBJS = driver.@O@
+SO_SRCS = driver.c
+
+OBJS =
+
+@BIND9_MAKE_RULES@
+
+CFLAGS = @CFLAGS@ @SO_CFLAGS@
+SO_LDFLAGS = @LDFLAGS@ @SO_LDFLAGS@
+
+driver.@SO@: ${SO_OBJS}
+ ${LIBTOOL_MODE_LINK} @SO_LD@ ${SO_LDFLAGS} -o $@ driver.@O@
+
+clean distclean::
+ rm -f ${TARGETS}
+
+distclean::
+ rm -f ns1/named.conf
diff --git a/bin/tests/system/dlzexternal/clean.sh b/bin/tests/system/dlzexternal/clean.sh
new file mode 100644
index 0000000..3e6cb9e
--- /dev/null
+++ b/bin/tests/system/dlzexternal/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
diff --git a/bin/tests/system/dlzexternal/driver.c b/bin/tests/system/dlzexternal/driver.c
new file mode 100644
index 0000000..4a08dd6
--- /dev/null
+++ b/bin/tests/system/dlzexternal/driver.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This provides a very simple example of an external loadable DLZ
+ * driver, with update support.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/log.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/types.h>
+#include <dns/dlz_dlopen.h>
+
+#include "driver.h"
+
+#ifdef WIN32
+#define STRTOK_R(a, b, c) strtok_s(a, b, c)
+#elif defined(_REENTRANT)
+#define STRTOK_R(a, b, c) strtok_r(a, b, c)
+#else
+#define STRTOK_R(a, b, c) strtok(a, b)
+#endif
+
+#define CHECK(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+/* 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++) {
+ 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) {
+ if (state->log != NULL)
+ state->log(ISC_LOG_ERROR,
+ "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));
+ list[i].name[sizeof(list[i].name) - 1] = '\0';
+
+ strncpy(list[i].type, type, sizeof(list[i].type));
+ list[i].type[sizeof(list[i].type) - 1] = '\0';
+
+ strncpy(list[i].data, data, sizeof(list[i].data));
+ 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[100];
+ 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[1024];
+ const char *extra;
+ isc_result_t result;
+ int 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') {
+ if (state->log != NULL)
+ state->log(ISC_LOG_ERROR,
+ "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]);
+
+ if (strcmp(state->zone_name, ".") == 0)
+ extra = ".root";
+ else
+ extra = ".";
+
+ n = sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600",
+ state->zone_name, extra, state->zone_name);
+
+ if (n < 0)
+ CHECK(ISC_R_FAILURE);
+ if ((unsigned)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");
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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;
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO,
+ "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));
+ }
+
+ state->log(ISC_LOG_INFO,
+ "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);
+ }
+ state->log(ISC_LOG_INFO, "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 >= DNS_CLIENTINFO_VERSION) {
+ dbversion = clientinfo->dbversion;
+ if (dbversion != NULL && *(bool *)dbversion)
+ state->log(ISC_LOG_INFO,
+ "dlz_example: lookup against live "
+ "transaction");
+ }
+
+ if (strcmp(name, "source-addr") == 0) {
+ 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));
+ }
+
+ state->log(ISC_LOG_INFO,
+ "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) {
+ isc_result_t result;
+
+ result = dlz_findzonedb(dbdata, name, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (strcmp(client, "10.53.0.5") == 0) {
+ return (ISC_R_NOPERM);
+ }
+ 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) {
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO,
+ "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) {
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: transaction not "
+ "started for zone %s", zone);
+ *versionp = NULL;
+ return;
+ }
+
+ state->transaction_started = false;
+
+ *versionp = NULL;
+
+ if (commit) {
+ int i;
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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 {
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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;
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: starting configure");
+
+ if (state->writeable_zone == NULL) {
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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) {
+ if (state->log != NULL)
+ state->log(ISC_LOG_ERROR, "dlz_example: failed to "
+ "configure zone %s", state->zone_name);
+ return (result);
+ }
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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) {
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: denying update "
+ "of name=%s by %s", name, signer);
+ return (false);
+ }
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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;
+#if defined(WIN32) || defined(_REENTRANT)
+ char *saveptr = NULL;
+#endif
+
+ 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);
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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);
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "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);
+
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: deleting rdataset %s "
+ "of type %s", name, type);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/bin/tests/system/dlzexternal/driver.h b/bin/tests/system/dlzexternal/driver.h
new file mode 100644
index 0000000..7a0ec61
--- /dev/null
+++ b/bin/tests/system/dlzexternal/driver.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * 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/dlzs.conf.in b/bin/tests/system/dlzexternal/ns1/dlzs.conf.in
new file mode 100644
index 0000000..d583cb4
--- /dev/null
+++ b/bin/tests/system/dlzexternal/ns1/dlzs.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dlz "example one" {
+ database "dlopen ../driver.@SO@ example.nil";
+};
+
+dlz "example two" {
+ database "dlopen ../driver.@SO@ alternate.nil";
+};
+
+dlz "unsearched1" {
+ database "dlopen ../driver.@SO@ other.nil";
+ search no;
+};
+
+dlz "unsearched2" {
+ database "dlopen ../driver.@SO@ zone.nil";
+ search no;
+};
+
+dlz redzone {
+ database "dlopen ../driver.@SO@ .";
+ search no;
+};
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..d35061a
--- /dev/null
+++ b/bin/tests/system/dlzexternal/ns1/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+include "ddns.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "dlzs.conf";
+
+zone zone.nil {
+ type master;
+ dlz unsearched2;
+};
+
+zone "." {
+ type redirect;
+ dlz redzone;
+};
+
+zone "." {
+ type master;
+ 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..45a6b04
--- /dev/null
+++ b/bin/tests/system/dlzexternal/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..b3c73c3
--- /dev/null
+++ b/bin/tests/system/dlzexternal/prereq.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$FEATURETEST --have-dlopen || {
+ echo_i "dlopen() not supported - 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..e22e8aa
--- /dev/null
+++ b/bin/tests/system/dlzexternal/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+$DDNSCONFGEN -q -r $RANDFILE -z 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..1754aaa
--- /dev/null
+++ b/bin/tests/system/dlzexternal/tests.sh
@@ -0,0 +1,210 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+DIGOPTS="@10.53.0.1 -p ${PORT} +nocookie"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+newtest() {
+ n=`expr $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 | egrep "^$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=`expr $status + $ret`
+
+test_update testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || ret=1
+status=`expr $status + $ret`
+
+test_update testdc3.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1
+status=`expr $status + $ret`
+
+test_update deny.example.nil. TXT "86400 TXT helloworld" "helloworld" should_fail && ret=1
+status=`expr $status + $ret`
+
+newtest "testing nxrrset"
+$DIG $DIGOPTS testdc1.example.nil AAAA > dig.out.$n
+grep "status: NOERROR" dig.out.$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.$n > /dev/null || ret=1
+status=`expr $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=`expr $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=`expr $status + $ret`
+
+newtest "testing DLZ driver is cleaned up on reload"
+$RNDCCMD 10.53.0.1 reload 2>&1 | sed 's/^/ns1 /' | cat_i
+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=`expr $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=`expr $status + $ret`
+
+newtest "testing AXFR from DLZ drivers"
+$DIG $DIGOPTS +noall +answer axfr example.nil > dig.out.example.ns1.test$n
+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
+lines=`cat dig.out.alternate.ns1.test$n | wc -l`
+[ ${lines:-0} -eq 5 ] || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=`expr $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
+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
+grep "; Transfer failed" dig.out.alternate.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+newtest "testing unsearched/unregistered DLZ zone is not found"
+$DIG $DIGOPTS +noall +answer ns other.nil > dig.out.ns1.test$n
+grep "3600.IN.NS.other.nil." dig.out.ns1.test$n > /dev/null && ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+newtest "testing unsearched/registered DLZ zone is found"
+$DIG $DIGOPTS +noall +answer ns zone.nil > dig.out.ns1.test$n
+grep "3600.IN.NS.zone.nil." dig.out.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+newtest "testing unsearched/registered DLZ zone is found"
+$DIG $DIGOPTS +noall +answer ns zone.nil > dig.out.ns1.test$n
+grep "3600.IN.NS.zone.nil." dig.out.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dns64/clean.sh b/bin/tests/system/dns64/clean.sh
new file mode 100644
index 0000000..fdb0053
--- /dev/null
+++ b/bin/tests/system/dns64/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f 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
diff --git a/bin/tests/system/dns64/conf/bad1.conf b/bin/tests/system/dns64/conf/bad1.conf
new file mode 100644
index 0000000..3f74917
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad1.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/0 { };
+};
diff --git a/bin/tests/system/dns64/conf/bad2.conf b/bin/tests/system/dns64/conf/bad2.conf
new file mode 100644
index 0000000..79bc04f
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad2.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..76f1606
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad3.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..fbf60d1
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad4.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..fbf60d1
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad5.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..c29bb3e
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad6.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..06919f9
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad7.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..794ad7e
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad8.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..af4b6d9
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad9.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..8013b94
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good1.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..4bd4780
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good2.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..aa07886
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good3.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..7ba4307
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good4.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..8a558ba
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good5.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..d91fcce
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/example.db
@@ -0,0 +1,54 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/named.conf.in b/bin/tests/system/dns64/ns1/named.conf.in
new file mode 100644
index 0000000..d8faa11
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/named.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+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-enable 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 master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "signed" {
+ type master;
+ file "signed.db.signed";
+};
+
+// include "trusted.conf";
diff --git a/bin/tests/system/dns64/ns1/root.db b/bin/tests/system/dns64/ns1/root.db
new file mode 100644
index 0000000..532063c
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ac98493
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/sign.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=signed
+infile=example.db
+zonefile=signed.db
+
+key1=`$KEYGEN -q -r $RANDFILE $zone`
+key2=`$KEYGEN -q -r $RANDFILE -fk $zone`
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -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..070fdec
--- /dev/null
+++ b/bin/tests/system/dns64/ns2/named.conf.in
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable 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 master;
+ 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..d08a83b
--- /dev/null
+++ b/bin/tests/system/dns64/ns2/rpz.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/prereq.sh b/bin/tests/system/dns64/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/dns64/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/dns64/setup.sh b/bin/tests/system/dns64/setup.sh
new file mode 100644
index 0000000..11c74bc
--- /dev/null
+++ b/bin/tests/system/dns64/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+copy_setports ns1/named.conf.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..ce5287e
--- /dev/null
+++ b/bin/tests/system/dns64/tests.sh
@@ -0,0 +1,1404 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dnssec/README b/bin/tests/system/dnssec/README
new file mode 100644
index 0000000..c45bd71
--- /dev/null
+++ b/bin/tests/system/dnssec/README
@@ -0,0 +1,19 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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 a caching-only server configured to use DLV.
+
+ns7 is used for checking non-cacheable answers.
diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh
new file mode 100644
index 0000000..1873c4b
--- /dev/null
+++ b/bin/tests/system/dnssec/clean.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed
+rm -f */example.bk
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f */named.secroots
+rm -f */tmp* */*.jnl */*.bk */*.jbk
+rm -f */trusted.conf */managed.conf */revoked.conf
+rm -f Kexample.*
+rm -f canonical?.*
+rm -f delv.out*
+rm -f delve.out*
+rm -f dig.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*/named.lock
+rm -f ns1/managed.key.id
+rm -f ns1/root.db ns2/example.db ns3/secure.example.db
+rm -f ns2/algroll.db
+rm -f ns2/badparam.db ns2/badparam.db.bad
+rm -f ns2/cdnskey-update.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-update.secure.db ns2/cds-update.secure.db.jnl
+rm -f ns2/cds.secure.db
+rm -f ns2/dlv.db
+rm -f ns2/in-addr.arpa.db
+rm -f ns2/nsec3chain-test.db
+rm -f ns2/private.secure.example.db
+rm -f ns2/single-nsec3.db
+rm -f ns3/auto-nsec.example.db ns3/auto-nsec3.example.db
+rm -f ns3/badds.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/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/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/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/rsasha256.example.db ns3/rsasha512.example.db
+rm -f ns3/secure.below-cname.example.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/revkey.example.db
+rm -f ns3/managed-future.example.db
+rm -f ns4/managed-keys.bind*
+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 rndc.out.*
+rm -f signer/*.db
+rm -f signer/example.db.after signer/example.db.before
+rm -f signer/example.db.changed
+rm -f signer/nsec3param.out
+rm -f signer/signer.out.*
+rm -f signer/general/signed.zone
+rm -f signer/general/signer.out.*
+rm -f signer/general/dsset*
+rm -f signing.out*
+rm -f signer/*.signed.pre*
+rm -f signer/*.signed.post*
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..6b7412e
--- /dev/null
+++ b/bin/tests/system/dnssec/dnssec_update_test.pl
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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..4401f59
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ /* test that we can turn off trust-anchor-telemetry */
+ trust-anchor-telemetry no;
+};
+
+zone "." {
+ type master;
+ 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..5ad5d9e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/root.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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
+dlv. NS ns2.dlv.
+ns2.dlv. A 10.53.0.2
+algroll NS ns2.algroll
+ns2.algroll. 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.
diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh
new file mode 100644
index 0000000..198d60a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/sign.sh
@@ -0,0 +1,53 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh )
+(cd ../ns6 && $SHELL sign.sh )
+(cd ../ns7 && $SHELL sign.sh )
+
+cp ../ns2/dsset-example$TP .
+cp ../ns2/dsset-dlv$TP .
+cp ../ns2/dsset-in-addr.arpa$TP .
+
+grep "8 [12] " ../ns2/dsset-algroll$TP > dsset-algroll$TP
+cp ../ns6/dsset-optout-tld$TP .
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $keyname > 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
+
+# ...or with a managed key.
+keyfile_to_managed_keys $keyname > managed.conf
+cp managed.conf ../ns4/managed.conf
+
+#
+# Save keyid for managed key id test.
+#
+keyid=`expr $keyname : 'K.+001+\(.*\)'`
+keyid=`expr $keyid + 0`
+echo "$keyid" > 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..73c0d6b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/algroll.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..091e4ea
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/badparam.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..e42cb4a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e42cb4a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e42cb4a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e42cb4a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e42cb4a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds-update.secure.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e42cb4a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds.secure.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..8c7db65
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/child.nsec3.example.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8c7db65
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/child.optout.example.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/dlv.db.in b/bin/tests/system/dnssec/ns2/dlv.db.in
new file mode 100644
index 0000000..836359d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/dlv.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/dnssec/ns2/dst.example.db.in b/bin/tests/system/dnssec/ns2/dst.example.db.in
new file mode 100644
index 0000000..769d2b5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/dst.example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..0b831ec
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/example.db.in
@@ -0,0 +1,160 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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-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
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..0884ad0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..78f3325
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/insecure.secure.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/named.conf.in b/bin/tests/system/dnssec/ns2/named.conf.in
new file mode 100644
index 0000000..67cff87
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/named.conf.in
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+ notify-delay 1;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "dlv" {
+ type master;
+ file "dlv.db.signed";
+};
+
+zone "example" {
+ type master;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+zone "private.secure.example" {
+ type master;
+ file "private.secure.example.db.signed";
+ allow-update { any; };
+};
+
+zone "insecure.secure.example" {
+ type master;
+ file "insecure.secure.example.db";
+ allow-update { any; };
+};
+
+zone "rfc2335.example" {
+ type master;
+ file "rfc2335.example.db";
+};
+
+zone "child.nsec3.example" {
+ type master;
+ file "child.nsec3.example.db";
+ allow-update { none; };
+};
+
+zone "child.optout.example" {
+ type master;
+ file "child.optout.example.db";
+ allow-update { none; };
+};
+
+zone "badparam" {
+ type master;
+ file "badparam.db.bad";
+};
+
+zone "single-nsec3" {
+ type master;
+ file "single-nsec3.db.signed";
+};
+
+zone "algroll" {
+ type master;
+ file "algroll.db.signed";
+};
+
+zone "nsec3chain-test" {
+ type master;
+ file "nsec3chain-test.db.signed";
+ allow-update {any;};
+};
+
+zone "in-addr.arpa" {
+ type master;
+ file "in-addr.arpa.db.signed";
+};
+
+zone "cds.secure" {
+ type master;
+ file "cds.secure.db.signed";
+};
+
+zone "cds-update.secure" {
+ type master;
+ file "cds-update.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "cds-auto.secure" {
+ type master;
+ file "cds-auto.secure.db.signed";
+ auto-dnssec maintain;
+ allow-update { any; };
+};
+
+zone "cdnskey.secure" {
+ type master;
+ file "cdnskey.secure.db.signed";
+};
+
+zone "cdnskey-update.secure" {
+ type master;
+ file "cdnskey-update.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "cdnskey-auto.secure" {
+ type master;
+ file "cdnskey-auto.secure.db.signed";
+ auto-dnssec maintain;
+ allow-update { any; };
+};
+
+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..98b43a0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/private.secure.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..b8b477e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/rfc2335.example.db
@@ -0,0 +1,103 @@
+; 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..9078459
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/sign.sh
@@ -0,0 +1,239 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+# Have the child generate a zone key and pass it to us.
+
+( cd ../ns3 && $SHELL sign.sh )
+
+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-nsec3-unknown managed-future revkey
+do
+ cp ../ns3/dsset-$subdomain.example$TP .
+done
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+#
+# lower/uppercase the signature bits with the exception of the last characters
+# changing the last 4 characters will lead to a bad base64 encoding.
+#
+$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; }' > $zonefile.signed++ && mv $zonefile.signed++ $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 -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+$SIGNER -P -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+# Sign the privately secure file
+
+privzone=private.secure.example.
+privinfile=private.secure.example.db.in
+privzonefile=private.secure.example.db
+
+privkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $privzone`
+
+cat $privinfile $privkeyname.key >$privzonefile
+
+$SIGNER -P -g -r $RANDFILE -o $privzone -l dlv $privzonefile > /dev/null
+
+# Sign the DLV secure zone.
+
+
+dlvzone=dlv.
+dlvinfile=dlv.db.in
+dlvzonefile=dlv.db
+dlvsetfile=dlvset-`echo $privzone |sed -e "s/\.$//g"`$TP
+
+dlvkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $dlvzone`
+
+cat $dlvinfile $dlvkeyname.key $dlvsetfile > $dlvzonefile
+
+$SIGNER -P -g -r $RANDFILE -o $dlvzone $dlvzonefile > /dev/null
+
+# Sign the badparam secure file
+
+zone=badparam.
+infile=badparam.db.in
+zonefile=badparam.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone -f KSK $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -3 - -H 1 -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+sed '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 -r $RANDFILE -a RSASHA256 -b 1024 -n zone -f KSK $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -3 - -A -H 1 -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+#
+# 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 -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+keyold2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+keynew1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone -fk $zone`
+keynew2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+
+cat $infile $keynew1.key $keynew2.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone -k $keyold1 -k $keynew1 $zonefile $keyold1 $keyold2 $keynew1 $keynew2 > /dev/null
+
+#
+# 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
+awk 'END { for (i = 0; i < 300; i++)
+ print "host" i, 10, "NS", "ns.elsewhere"; }' < /dev/null >> $zonefile
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+cat $key1.key $key2.key >> $zonefile
+$SIGNER -P -3 - -A -H 1 -g -r $RANDFILE -o $zone -k $key1 $zonefile $key2 > /dev/null
+
+zone=cds.secure
+infile=cds.secure.db.in
+zonefile=cds.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+$DSFROMKEY -C $key1.key > $key1.cds
+cat $infile $key1.key $key2.key $key1.cds >$zonefile
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=cds-update.secure
+infile=cds-update.secure.db.in
+zonefile=cds-update.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+cat $infile $key1.key $key2.key > $zonefile
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=cds-auto.secure
+infile=cds-auto.secure.db.in
+zonefile=cds-auto.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+$DSFROMKEY -C $key1.key > $key1.cds
+cat $infile $key1.cds > $zonefile.signed
+
+zone=cdnskey.secure
+infile=cdnskey.secure.db.in
+zonefile=cdnskey.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+sed 's/DNSKEY/CDNSKEY/' $key1.key > $key1.cds
+cat $infile $key1.key $key2.key $key1.cds >$zonefile
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=cdnskey-update.secure
+infile=cdnskey-update.secure.db.in
+zonefile=cdnskey-update.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+cat $infile $key1.key $key2.key > $zonefile
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=cdnskey-auto.secure
+infile=cdnskey-auto.secure.db.in
+zonefile=cdnskey-auto.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+sed 's/DNSKEY/CDNSKEY/' $key1.key > $key1.cds
+cat $infile $key1.cds > $zonefile.signed
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..6fe1dd0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/single-nsec3.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/ns3/auto-nsec.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in
new file mode 100644
index 0000000..0e0e5e0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..0e0e5e0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8d49000
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/bogus.example.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/dnskey-nsec3-unknown.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in
new file mode 100644
index 0000000..e1475c5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$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..c9e7c2b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c7dab83
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dynamic.example.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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..af312f2
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/expired.example.db.in
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4d8db53
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/expiring.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ddda25d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/future.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..dd1778e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/generic.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/inline.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.nsec3.example.db b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db
new file mode 100644
index 0000000..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.optout.example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/kskonly.example.db.in b/bin/tests/system/dnssec/ns3/kskonly.example.db.in
new file mode 100644
index 0000000..cbfb691
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/kskonly.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7a3879f
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/lower.example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ddda25d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/managed-future.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c9e7c2b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/multiple.example.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..14ebbc8
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/named.conf.in
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ session-keyfile "session.key";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "secure.example" {
+ type master;
+ file "secure.example.db.signed";
+ allow-update { any; };
+};
+
+zone "bogus.example" {
+ type master;
+ file "bogus.example.db.signed";
+ allow-update { any; };
+};
+
+zone "badds.example" {
+ type master;
+ file "badds.example.db.signed";
+ allow-update { any; };
+};
+
+zone "dynamic.example" {
+ type master;
+ file "dynamic.example.db.signed";
+ allow-update { any; };
+};
+
+zone "insecure.example" {
+ type master;
+ file "insecure.example.db";
+ allow-update { any; };
+};
+
+zone "insecure.nsec3.example" {
+ type master;
+ file "insecure.nsec3.example.db";
+ allow-update { any; };
+};
+
+zone "insecure.optout.example" {
+ type master;
+ file "insecure.optout.example.db";
+ allow-update { any; };
+};
+
+zone "keyless.example" {
+ type master;
+ file "keyless.example.db.signed";
+};
+
+zone "nsec3.example" {
+ type master;
+ file "nsec3.example.db.signed";
+};
+
+zone "optout.nsec3.example" {
+ type master;
+ file "optout.nsec3.example.db.signed";
+};
+
+zone "nsec3.nsec3.example" {
+ type master;
+ file "nsec3.nsec3.example.db.signed";
+};
+
+zone "secure.nsec3.example" {
+ type master;
+ file "secure.nsec3.example.db.signed";
+};
+
+zone "optout.example" {
+ type master;
+ file "optout.example.db.signed";
+};
+
+zone "secure.optout.example" {
+ type master;
+ file "secure.optout.example.db.signed";
+};
+
+zone "nsec3.optout.example" {
+ type master;
+ file "nsec3.optout.example.db.signed";
+};
+
+zone "optout.optout.example" {
+ type master;
+ file "optout.optout.example.db.signed";
+};
+
+zone "nsec3-unknown.example" {
+ type master;
+ nsec3-test-zone yes;
+ file "nsec3-unknown.example.db.signed";
+};
+
+zone "optout-unknown.example" {
+ type master;
+ nsec3-test-zone yes;
+ file "optout-unknown.example.db.signed";
+};
+
+zone "dnskey-unknown.example" {
+ type master;
+ file "dnskey-unknown.example.db.signed";
+};
+
+zone "dnskey-nsec3-unknown.example" {
+ type master;
+ nsec3-test-zone yes;
+ file "dnskey-nsec3-unknown.example.db.signed";
+};
+
+zone "multiple.example" {
+ type master;
+ file "multiple.example.db.signed";
+ allow-update { any; };
+};
+
+zone "rfc2335.example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "rfc2335.example.bk";
+};
+
+zone "rsasha256.example" {
+ type master;
+ file "rsasha256.example.db.signed";
+};
+
+zone "rsasha512.example" {
+ type master;
+ file "rsasha512.example.db.signed";
+};
+
+zone "kskonly.example" {
+ type master;
+ file "kskonly.example.db.signed";
+};
+
+zone "expired.example" {
+ type master;
+ allow-update { none; };
+ file "expired.example.db.signed";
+};
+
+zone "update-nsec3.example" {
+ type master;
+ allow-update { any; };
+ file "update-nsec3.example.db.signed";
+};
+
+zone "auto-nsec.example" {
+ type master;
+ auto-dnssec maintain;
+ allow-update { !0.0.0.0; };
+ file "auto-nsec.example.db.signed";
+};
+
+zone "auto-nsec3.example" {
+ type master;
+ auto-dnssec maintain;
+ allow-update { !0.0.0.0; };
+ file "auto-nsec3.example.db.signed";
+};
+
+zone "insecure.below-cname.example" {
+ type master;
+ file "insecure.below-cname.example.db";
+};
+
+zone "secure.below-cname.example" {
+ type master;
+ file "secure.below-cname.example.db.signed";
+};
+
+zone "ttlpatch.example" {
+ type master;
+ file "ttlpatch.example.db.patched";
+};
+
+zone "split-dnssec.example" {
+ type master;
+ file "split-dnssec.example.db";
+};
+
+zone "split-smart.example" {
+ type master;
+ file "split-smart.example.db";
+};
+
+zone "nsec3chain-test" {
+ type slave;
+ file "nsec3chain-test.bk";
+ masters { 10.53.0.2; };
+};
+
+zone "expiring.example" {
+ type master;
+ allow-update { any; };
+ file "expiring.example.db.signed";
+};
+
+zone "nosign.example" {
+ type master;
+ allow-update { any; };
+ dnssec-update-mode no-resign;
+ file "nosign.example.db.signed";
+};
+
+zone "upper.example" {
+ type master;
+ file "upper.example.db.signed";
+};
+
+zone "LOWER.EXAMPLE" {
+ type master;
+ file "lower.example.db.signed";
+};
+
+zone "inline.example" {
+ type master;
+ file "inline.example.db";
+ inline-signing yes;
+ auto-dnssec maintain;
+};
+
+zone "publish-inactive.example" {
+ type master;
+ file "publish-inactive.example.db";
+ auto-dnssec maintain;
+ update-policy local;
+};
+
+zone "future.example" {
+ type master;
+ file "future.example.db.signed";
+};
+
+zone "managed-future.example" {
+ type master;
+ file "managed-future.example.db.signed";
+ allow-update { any; };
+};
+
+zone "revkey.example" {
+ type master;
+ file "revkey.example.db.signed";
+};
+
+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..f066e3c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nosign.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c9e7c2b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8761ebb
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.example.db.in
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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-unknown.example.db.in b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in
new file mode 100644
index 0000000..c9e7c2b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ddda25d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..862dadb
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/rsasha256.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..862dadb
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/rsasha512.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..9d310d8
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.example.db.in
@@ -0,0 +1,46 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+
+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..3f10748
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3f10748
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..703a306
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/siginterval.example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..092dcfa
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/siginterval1.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "siginterval.example" {
+ type master;
+ allow-update { any; };
+ sig-validity-interval 1 23;
+ 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..9fab130
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/siginterval2.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "siginterval.example" {
+ type master;
+ allow-update { any; };
+ sig-validity-interval 35 28;
+ 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..330abf7
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/sign.sh
@@ -0,0 +1,545 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=secure.example.
+infile=secure.example.db.in
+zonefile=secure.example.db
+
+cnameandkey=`$KEYGEN -T KEY -q -r $RANDFILE -a RSASHA1 -b 768 -n host cnameandkey.$zone`
+dnameandkey=`$KEYGEN -T KEY -q -r $RANDFILE -a RSASHA1 -b 768 -n host dnameandkey.$zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $cnameandkey.key $dnameandkey.key $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+zone=bogus.example.
+infile=bogus.example.db.in
+zonefile=bogus.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+zone=dynamic.example.
+infile=dynamic.example.db.in
+zonefile=dynamic.example.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 1024 -n zone -f KSK $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+zone=keyless.example.
+infile=generic.example.db.in
+zonefile=keyless.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+# Change the signer field of the a.b.keyless.example SIG A
+# to point to a provably nonexistent KEY record.
+mv $zonefile.signed $zonefile.tmp
+<$zonefile.tmp $PERL -p -e 's/ keyless.example/ b.keyless.example/
+ if /^a.b.keyless.example/../NXT/;' >$zonefile.signed
+rm -f $zonefile.tmp
+
+#
+# NSEC3/NSEC test zone
+#
+zone=secure.nsec3.example.
+infile=secure.nsec3.example.db.in
+zonefile=secure.nsec3.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# NSEC3/NSEC3 test zone
+#
+zone=nsec3.nsec3.example.
+infile=nsec3.nsec3.example.db.in
+zonefile=nsec3.nsec3.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# OPTOUT/NSEC3 test zone
+#
+zone=optout.nsec3.example.
+infile=optout.nsec3.example.db.in
+zonefile=optout.nsec3.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A nsec3 zone (non-optout).
+#
+zone=nsec3.example.
+infile=nsec3.example.db.in
+zonefile=nsec3.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -g -3 - -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# OPTOUT/NSEC test zone
+#
+zone=secure.optout.example.
+infile=secure.optout.example.db.in
+zonefile=secure.optout.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# OPTOUT/NSEC3 test zone
+#
+zone=nsec3.optout.example.
+infile=nsec3.optout.example.db.in
+zonefile=nsec3.optout.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# OPTOUT/OPTOUT test zone
+#
+zone=optout.optout.example.
+infile=optout.optout.example.db.in
+zonefile=optout.optout.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A optout nsec3 zone.
+#
+zone=optout.example.
+infile=optout.example.db.in
+zonefile=optout.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -g -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -U -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -U -A -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A zone with a 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 -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -r $RANDFILE -o $zone -O full -f ${zonefile}.tmp $zonefile > /dev/null 2>&1
+
+awk '$4 == "DNSKEY" { $7 = 100; print } $4 == "RRSIG" { $6 = 100; print } { print }' ${zonefile}.tmp > ${zonefile}.signed
+
+DSFILE=dsset-`echo ${zone} |sed -e "s/\.$//g"`$TP
+$DSFROMKEY -A -f ${zonefile}.signed $zone > $DSFILE
+
+#
+# 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 -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -r $RANDFILE -o $zone -U -O full -f ${zonefile}.tmp $zonefile > /dev/null 2>&1
+
+awk '$4 == "DNSKEY" { $7 = 100; print } $4 == "RRSIG" { $6 = 100; print } { print }' ${zonefile}.tmp > ${zonefile}.signed
+
+DSFILE=dsset-`echo ${zone} |sed -e "s/\.$//g"`$TP
+$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 -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+mv $zonefile.signed $zonefile
+$SIGNER -P -u3 - -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+mv $zonefile.signed $zonefile
+$SIGNER -P -u3 AAAA -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+mv $zonefile.signed $zonefile
+$SIGNER -P -u3 BBBB -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+mv $zonefile.signed $zonefile
+$SIGNER -P -u3 CCCC -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+mv $zonefile.signed $zonefile
+$SIGNER -P -u3 DDDD -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A RSASHA256 zone.
+#
+zone=rsasha256.example.
+infile=rsasha256.example.db.in
+zonefile=rsasha256.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A RSASHA512 zone.
+#
+zone=rsasha512.example.
+infile=rsasha512.example.db.in
+zonefile=rsasha512.example.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA512 -b 1024 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -x -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A zone with the expired signatures
+#
+zone=expired.example.
+infile=expired.example.db.in
+zonefile=expired.example.db
+
+kskname=`$KEYGEN -q -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -P -r $RANDFILE -o $zone -s -1d -e +1h $zonefile > /dev/null 2>&1
+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 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+kskname=`$KEYGEN -q -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
+kskname=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+cat $infile $keyname.key >$zonefile
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -f $signedfile -o $zone $zonefile > /dev/null 2>&1
+$CHECKZONE -D -s full $zone $signedfile 2> /dev/null | \
+ awk '{$2 = "3600"; print}' > $patchedfile
+
+#
+# Seperate 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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+cat $infile $keyname.key >$zonefile
+echo '$INCLUDE "'"$signedfile"'"' >> $zonefile
+: > $signedfile
+$SIGNER -P -r $RANDFILE -D -o $zone $zonefile > /dev/null 2>&1
+
+#
+# Seperate 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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+cp $infile $zonefile
+echo '$INCLUDE "'"$signedfile"'"' >> $zonefile
+: > $signedfile
+$SIGNER -P -S -r $RANDFILE -D -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE $zone`
+zskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
+cp $infile $zonefile
+$SIGNER -S -r $RANDFILE -e now+1mi -o $zone $zonefile > /dev/null 2>&1
+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 -r $RANDFILE $zone`
+zskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
+cp $infile $zonefile
+$SIGNER -P -S -r $RANDFILE -o $zone -f $lower $zonefile > /dev/null 2>/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 -r $RANDFILE $zone`
+zskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
+cp $infile $zonefile
+$SIGNER -P -S -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE $zone`
+zskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
+cp $infile $zonefile
+$SIGNER -S -r $RANDFILE -e now+1mi -o $zone $zonefile > /dev/null 2>&1
+# 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 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -3 -r $RANDFILE $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 -r $RANDFILE -f KSK $zone`
+kskname=`$KEYGEN -P $now+90s -A $now+3600s -q -r $RANDFILE -f KSK $zone`
+kskname=`$KEYGEN -I $now+90s -q -r $RANDFILE -f KSK $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cp $infile $zonefile
+$SIGNER -S -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# 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 -r $RANDFILE -fk $zone`
+zskname=`$KEYGEN -q -3 -r $RANDFILE $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 -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+sed -e 's/bogus/badds/g' < dsset-bogus.example$TP > dsset-badds.example$TP
+
+#
+# A zone with future signatures.
+#
+zone=future.example
+infile=future.example.db.in
+zonefile=future.example.db
+kskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -P -s +3600 -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+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 -r $RANDFILE -f KSK $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cat $infile $kskname.key $zskname.key >$zonefile
+$SIGNER -P -s +3600 -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A zone with a revoked key
+#
+zone=revkey.example.
+infile=generic.example.db.in
+zonefile=revkey.example.db
+
+ksk1=`$KEYGEN -q -r $RANDFILE -3fk $zone`
+ksk1=`$REVOKE $ksk1`
+ksk2=`$KEYGEN -q -r $RANDFILE -3fk $zone`
+zsk1=`$KEYGEN -q -r $RANDFILE -3 $zone`
+
+cat $infile ${ksk1}.key ${ksk2}.key ${zsk1}.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
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..8761ebb
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8761ebb
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/split-smart.example.db.in
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8655214
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/update-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in
new file mode 100644
index 0000000..0e0e5e0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..703a306
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/upper.example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/named1.conf.in b/bin/tests/system/dnssec/ns4/named1.conf.in
new file mode 100644
index 0000000..d3e221e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named1.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4 dscp 1;
+ notify-source 10.53.0.4 dscp 2;
+ transfer-source 10.53.0.4 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-must-be-secure mustbesecure.example yes;
+
+ nta-lifetime 12s;
+ nta-recheck 9s;
+
+ # 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 hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+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..da6f831
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named2.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4 dscp 4;
+ notify-source 10.53.0.4 dscp 5;
+ transfer-source 10.53.0.4 dscp 6;
+ dscp 16;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/dnssec/ns4/named3.conf.in b/bin/tests/system/dnssec/ns4/named3.conf.in
new file mode 100644
index 0000000..d6cfd45
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named3.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ dnssec-accept-expired yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/dnssec/ns4/named4.conf.in b/bin/tests/system/dnssec/ns4/named4.conf.in
new file mode 100644
index 0000000..017c540
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named4.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable no;
+ dnssec-enable yes;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ dnssec-accept-expired yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/dnssec/ns4/named5.conf.in b/bin/tests/system/dnssec/ns4/named5.conf.in
new file mode 100644
index 0000000..0878c15
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named5.conf.in
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key auth {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+include "trusted.conf";
+
+view rec {
+ match-recursive-only yes;
+ recursion yes;
+ acache-enable yes;
+ dnssec-validation yes;
+ dnssec-accept-expired yes;
+
+ 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 slave;
+ masters { 10.53.0.3; };
+ };
+
+ zone insecure.secure.example {
+ type slave;
+ masters { 10.53.0.2; };
+ };
+};
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..ddd0343
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/named1.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+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..8aa4e69
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/named2.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+};
+
+view root {
+ match-destinations { 127.0.0.1; };
+
+ zone "." {
+ type master;
+ 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..93ca676
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/sign.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=../ns1/root.db.in
+zonefile=root.db.signed
+
+keyname=`$KEYGEN -r $RANDFILE -qfk $zone`
+
+# copy the KSK out first, then revoke it
+keyfile_to_managed_keys $keyname > revoked.conf
+
+$SETTIME -R now ${keyname}.key > /dev/null
+
+# create a current set of keys, and sign the root zone
+$KEYGEN -r $RANDFILE -q $zone > /dev/null
+$KEYGEN -r $RANDFILE -qfk $zone > /dev/null
+$SIGNER -S -r $RANDFILE -o $zone -f $zonefile $infile > /dev/null 2>&1
diff --git a/bin/tests/system/dnssec/ns5/trusted.conf.bad b/bin/tests/system/dnssec/ns5/trusted.conf.bad
new file mode 100644
index 0000000..ed30460
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/trusted.conf.bad
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trusted-keys {
+ "." 256 3 1 "AQO6Cl+slAf+iuieDim9L3kujFHQD7s/IOj03ClMOpKYcTXtK4mRpuULVfvWxDi9Ew/gj0xLnnX7z9OJHIxLI+DSrAHd8Dm0XfBEAtVtJSn70GaPZgnLMw1rk5ap2DsEoWk=";
+};
diff --git a/bin/tests/system/dnssec/ns6/named.args b/bin/tests/system/dnssec/ns6/named.args
new file mode 100644
index 0000000..04cf949
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -c named.conf -d 99 -X named.lock -g -T nonearest -T clienttest -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..0fb1091
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ acache-enable yes;
+ notify yes;
+ disable-algorithms . { DSA; };
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-lookaside . trust-anchor dlv;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "optout-tld" {
+ type master;
+ 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..b90c9ea
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/optout-tld.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3092b5f
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/sign.sh
@@ -0,0 +1,23 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=optout-tld
+infile=optout-tld.db.in
+zonefile=optout-tld.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -A -r $RANDFILE -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..2dc2a9c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/named.conf.in
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.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-enable yes;
+ dnssec-validation yes;
+ minimal-responses yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "nsec3.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "nsec3.example.bk";
+};
+
+zone "optout.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "optout.example.bk";
+};
+
+zone "nsec3-unknown.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "nsec3-unknown.example.bk";
+};
+
+zone "optout-unknown.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "optout-unknown.example.bk";
+};
+
+zone "multiple.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "multiple.example.bk";
+};
+
+zone "nosoa.secure.example" {
+ type master;
+ file "nosoa.secure.example.db";
+};
+
+zone "split-rrsig" {
+ type master;
+ 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..a7af1dd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/named.nosoa
@@ -0,0 +1,5 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..e894947
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/nosoa.secure.example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..a4cf78f
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/sign.sh
@@ -0,0 +1,28 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=split-rrsig
+infile=split-rrsig.db.in
+zonefile=split-rrsig.db
+
+k1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 768 -n zone $zone`
+k2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 768 -n zone $zone`
+
+cat $infile $k1.key $k2.key >$zonefile
+
+$SIGNER -P -3 - -A -r $RANDFILE -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 }' $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..14300c3
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/split-rrsig.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+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/ntadiff.pl b/bin/tests/system/dnssec/ntadiff.pl
new file mode 100755
index 0000000..e49ae14
--- /dev/null
+++ b/bin/tests/system/dnssec/ntadiff.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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/prereq.sh b/bin/tests/system/dnssec/prereq.sh
new file mode 100644
index 0000000..9c1d276
--- /dev/null
+++ b/bin/tests/system/dnssec/prereq.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION >= 0.69 && $Net::DNS::VERSION <= 0.70);' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS versions 0.69 to 0.70 have bugs that cause this test to fail: please update." >&2
+ exit 1
+ fi
+fi
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh
new file mode 100644
index 0000000..6bf41a0
--- /dev/null
+++ b/bin/tests/system/dnssec/setup.sh
@@ -0,0 +1,41 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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
+
+cd ns1
+$SHELL sign.sh
+
+echo "a.bogus.example. A 10.0.0.22" >>../ns3/bogus.example.db.signed
+echo "b.bogus.example. A 10.0.0.23" >>../ns3/bogus.example.db.signed
+echo "c.bogus.example. A 10.0.0.23" >>../ns3/bogus.example.db.signed
+
+cd ../ns3
+cp -f siginterval1.conf siginterval.conf
+
+cd ../ns5
+cp -f trusted.conf.bad trusted.conf
+$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..dbf60c1
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/example.db.in
@@ -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 http://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.+005+07065.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.key
new file mode 100644
index 0000000..e4bdce2
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.key
@@ -0,0 +1 @@
+example.com. IN DNSKEY 256 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpZ
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.private
new file mode 100644
index 0000000..db928c5
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: oXTPXsN2QEAqJhJxU2rOypfDtXP8LHk4LDtP/pGdT8qIa/zXmSUfahvLBFlfZlwSD1HxJTNCI/3KBjSzXEXkgViLfYexZ+01XtX+A3A2sycYLSBXZ7c5rCxDYJhZllXA5uv9+Zwohe5jp5F0m3I6KUxGGW+ugl1dnDUJB2JzGlk=
+PublicExponent: AQAB
+PrivateExponent: QrbJmRabHiFlSSYFvbo8iGn9bFTotlfAZkZ732y72+SMSlLHo3g7atThJoLncJxKuhnZ0s1DXyvW9omAM3iN2lxfVDW58at1amj/lWRDYkjI0fM8z6eyrF4U2lHKDM2YEstg+sGAAs5DUZBbli4Y7+zHjhxSKLYvRf4AJvX8aoE=
+Prime1: 0259CgdF0JW+miedRZXC6tn3FijZJ4/j5edzd8IpTpdUSZupQg9hMP1ot7crreNq7MnzO0Z2ImbowUx8CDOuXQ==
+Prime2: w31/WLM2275Z1tsHEOhrntUQCUk55B4PNOCmM4hjp0vAvA/SVSgAYRNb7rc/ujaLf0DnxnDsnVsFAS2PmvQELQ==
+Exponent1: yKPhJNMh/X8dEUzmglJMVnHheLXq3RA/RL0PZmZqrJoO8os1Y+sUYFkaNr0sRie6IFrE50tGb/8YgdcDHQVuQQ==
+Exponent2: lVhDuGy5RSjnk1eiz0zwIthctutlOZupPFk/P3E7yGv74vAnXH0BxSe3/Oer3MOc0GuyZYyRhyko6px28AbpRQ==
+Coefficient: Hjup1nDnPFkQrxU2qLQBJrDz+ipw0RkNhsjWs6IgAq1Mq4sFV50bR9hOTLDd9oNhhtAwVjF+Oc0WIq+M1Mi6Ow==
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.key
new file mode 100644
index 0000000..6f4fec8
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.key
@@ -0,0 +1 @@
+example.com. IN DNSKEY 257 3 5 AwEAAbuWh5W3eGwixISqPwxszotQ0246KqhUB2Mb6JqNMJd6cWR66IrX YnevpIHsb6oanqJmVzOcJ6Yj3rXOIYtYYXgLbT7EJ8x7BNCZPHxG+w5C 7I1WsDbT6eGf//FLn2c4odKLOXaWCVITeNy61w43IlteIT9Q1egKdt+8 a7X9605j
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.private
new file mode 100644
index 0000000..2d299d0
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: u5aHlbd4bCLEhKo/DGzOi1DTbjoqqFQHYxvomo0wl3pxZHroitdid6+kgexvqhqeomZXM5wnpiPetc4hi1hheAttPsQnzHsE0Jk8fEb7DkLsjVawNtPp4Z//8UufZzih0os5dpYJUhN43LrXDjciW14hP1DV6Ap237xrtf3rTmM=
+PublicExponent: AQAB
+PrivateExponent: XZSssv3CL3/wtZYQuewV5d4+e8C8wxiYTtL/aQqCcS7+HnhKRelJEBgpYz9GPX/mH3Iakn6WMQW39s6MYW2HwXUnqhsvHoyabGX0Dbc/1LcY4J2VPgzVHwSXYm+j4unOByOOS4KoBtUAQxJsTBokVZrZ5pKsLUK9X2gdywYw+PE=
+Prime1: 9fB7PaygjKoT1nbbeEMy1KYNqetg3zmN49Mk6ilEWxzJXKSSjTIhdkiLGXtYmE8rDBLBiYm8YWNe7YdA9PbQ7Q==
+Prime2: w0L7mTOLDecH3XAkC/wvALv8K9KSoZ31ajidKBxV15u8awj5AxDG7gjerYgCLjU1fq1GulMr11j8r4ftQn3Cjw==
+Exponent1: Up52yEE1rgt0npdPIxdv+//Ml0h7QoITKHXF8OPsEq+Y9YZTtRsiIpo8IFNPb9somuWyHoImxpCbUzAcoi5IAQ==
+Exponent2: uYTbvYx+UsAt9dOFPCnnkqAJEK3qCUomET0m/CQn30mldGC7DpGTIDgnMeLmh3agk/IYIBHDtsBinHfeEe2guw==
+Coefficient: FiHAet8On9Yaz1ksEAlCWulwck3zPWIsgqJBM2J4kHhgHTm17mZyxtVxIzLAMBNMIBcFl40FCpmPmTLY5QK5mw==
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..af4640b
--- /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 7091
+;
+example.com. IN DNSKEY 257 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpz
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..2e53d5c
--- /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 7092
+;
+example.com. IN DNSKEY 256 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpz
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..8c11a0e
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test1.zone
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+07065.key
+$include Kexample.com.+005+23362.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..b603931
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test2.zone
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+07065.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..70f2a86
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test3.zone
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+23362.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..fb5b6c4
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test4.zone
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+07065.key
+$include Kexample.com.+005+23362.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..7f33e27
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test5.zone
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+07065.key
+$include Kexample.com.+005+23362.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..aad2838
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test6.zone
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+07065.key
+$include Kexample.com.+005+23362.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..e804f81
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test7.zone
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has two DNSKEY records, none of which have
+; existing private key files available. The resulting zone should fail
+; the consistancy 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..abfc58f
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test8.zone
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.+005+23362.key
+$include bogus-zsk.key
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..8e0fccd
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/remove.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..aa1d2f5
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/remove2.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..434869a
--- /dev/null
+++ b/bin/tests/system/dnssec/tests.sh
@@ -0,0 +1,3529 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+ADDITIONALOPTS="+noall +additional +dnssec -p ${PORT}"
+ANSWEROPTS="+noall +answer +dnssec -p ${PORT}"
+DELVOPTS="-a ns1/trusted.conf -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+# convert private-type records to readable form
+showprivate () {
+ echo "-- $@ --"
+ $DIG $DIGOPTS +nodnssec +short @$2 -t 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
+checkprivate () {
+ ret=0
+ x=`showprivate "$@"`
+ echo $x | grep incomplete >/dev/null 2>&1 && ret=1
+ [ $ret = 1 ] && {
+ echo "$x"
+ echo_i "failed"
+ }
+ return $ret
+}
+
+# check that a zone file is raw format, version 0
+israw0 () {
+ cat $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 () {
+ cat $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
+}
+
+# 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+ $DIG $DIGOPTS 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 = 0 ] && break
+ sleep 1
+done
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +noauth +noadd +nodnssec +adflag a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# test AD bit:
+# - dig +noadflag
+echo_i "checking that AD is not set without +adflag or +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for AD in authoritative answer ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking postive validation NSEC using dns_client ($n)"
+ $DELV $DELVOPTS @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 3 2 300 .*" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking positive validation NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @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 7 3 300.*" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking positive validation OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @10.53.0.4 a a.optout.example > delv.out$n || ret=1
+ grep "a.optout.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ grep "a.optout.example..*RRSIG.A 7 3 300.*" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking positive wildcard validation NSEC ($n)"
+ret=0
+$DIG $DIGOPTS a.wild.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking positive wildcard validation NSEC using dns_client ($n)"
+ $DELV $DELVOPTS @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 "a.wild.example..*RRSIG.A 3 2 300.*" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking positive wildcard answer NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking positive wildcard answer NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking positive wildcard validation NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking positive wildcard validation NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @10.53.0.4 a a.wild.nsec3.example > delv.out$n || ret=1
+ grep "a.wild.nsec3.example..*10.0.0.6" delv.out$n > /dev/null || ret=1
+ grep "a.wild.nsec3.example..*RRSIG.A 7 3 300.*" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking positive wildcard validation OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS a.wild.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking positive wildcard validation OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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 7 3 300.*" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative validation NXDOMAIN NSEC using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative validation NXDOMAIN NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative validation NXDOMAIN OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative validation NODATA NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking negative wildcard validation NSEC ($n)"
+ret=0
+$DIG $DIGOPTS b.wild.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative wildcard validation NSEC using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking negative wildcard validation NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS b.wild.nsec3.example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative wildcard validation NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking negative wildcard validation OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS b.wild.optout.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking negative wildcard validation OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+# 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking 1-server insecurity proof NSEC using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking 1-server insecurity proof NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking 1-server insecurity proof NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking 1-server insecurity proof OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.optout.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking 1-server insecurity proof OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking 1-server negative insecurity proof NSEC using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking 1-server negative insecurity proof NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.nsec3.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking 1-server negative insecurity proof NSEC3 using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking 1-server negative insecurity proof OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.optout.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking 1-server negative insecurity proof OPTOUT using dns_client ($n)"
+ $DELV $DELVOPTS @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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking 1-server negative insecurity proof with SOA hack NSEC ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking 1-server negative insecurity proof with SOA hack NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.nsec3.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.optout.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Check the bogus domain
+
+echo_i "checking failed validation ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking failed validation using dns_client ($n)"
+ $DELV $DELVOPTS +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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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 $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that negative validation fails with a misconfigured trusted key ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that insecurity proofs fail with a misconfigured trusted key ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that validation fails when key record is missing ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ -x ${DELV} ] ; then
+ ret=0
+ echo_i "checking that validation fails when key record is missing using dns_client ($n)"
+ $DELV $DELVOPTS +cd @10.53.0.4 a a.b.keyless.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: broken trust chain" delv.out$n > /dev/null || ret=1
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "checking that validation succeeds when a revoked key is encountered ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DELVOPTS +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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+echo_i "Checking that a bad CNAME signature is caught after a +CD query ($n)"
+ret=0
+#prime
+$DIG $DIGOPTS +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 $DIGOPTS +cd +nodnssec +short bad-cname.example. @10.53.0.4` || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+#check: requery without +CD. bogus cached data should be rejected.
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "Checking that a bad DNAME signature is caught after a +CD query ($n)"
+ret=0
+#prime
+$DIG $DIGOPTS +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 $DIGOPTS +cd +nodnssec +short a.bad-dname.example. @10.53.0.4` || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+#check: requery without +CD. bogus cached data should be rejected.
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking 2-server insecurity proof with a negative answer and SOA hack ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.secure.example. @10.53.0.2 soa > dig.out.ns2.test$n \
+ || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Check that the setting the cd bit works
+
+echo_i "checking cd bit on a positive answer ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking cd bit on a negative answer ($n)"
+ret=0
+$DIG $DIGOPTS q.example. soa @10.53.0.4 > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking positive validation with KSK-only DNSKEY signature ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.kskonly.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking cd bit on a query that should fail ($n)"
+ret=0
+$DIG $DIGOPTS a.bogus.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking cd bit on an insecurity proof ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking cd bit on a negative insecurity proof ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that validation of an ANY query works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth foo.example. any @10.53.0.2 > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that validation of a query returning a CNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cname1.example. txt @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that validation of a query returning a DNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth foo.dname1.example. txt @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that validation of an ANY query returning a CNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cname2.example. any @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that validation of an ANY query returning a DNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth foo.dname2.example. any @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that lookups succeed after disabling a algorithm works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking privately secure wildcard to nxdomain works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking a non-cachable NODATA works ($n)"
+ret=0
+$DIG $DIGOPTS +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 $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking a non-cachable NXDOMAIN works ($n)"
+ret=0
+$DIG $DIGOPTS +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 $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+#
+# private.secure.example is served by the same server as its
+# grand parent and there is not a secure delegation from secure.example
+# to private.secure.example. In addition secure.example is using a
+# algorithm which the validation does not support.
+#
+echo_i "checking dnssec-lookaside-validation works ($n)"
+ret=0
+$DIG $DIGOPTS private.secure.example. SOA @10.53.0.6 \
+ > dig.out.ns6.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns6.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that we can load a rfc2535 signed zone ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that we can transfer a rfc2535 signed zone ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "basic dnssec-signzone checks:"
+echo_i " two DNSKEYs ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test1.zone > signer.out.$n 2>&1
+test -f signed.zone
+) || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " one non-KSK DNSKEY ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test2.zone > signer.out.$n 2>&1
+test -f signed.zone
+) && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " one KSK DNSKEY ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test3.zone > signer.out.$n 2>&1
+test -f signed.zone
+) && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " three DNSKEY ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test4.zone > signer.out.$n 2>&1
+test -f signed.zone
+) || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " three DNSKEY, one private key missing ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test5.zone > signer.out.$n 2>&1
+test -f signed.zone
+) || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " four DNSKEY ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test6.zone > signer.out.$n 2>&1
+test -f signed.zone
+) || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " two DNSKEY, both private keys missing ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test7.zone > signer.out.$n 2>&1
+test -f signed.zone
+) && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i " two DNSKEY, one private key missing ($n)"
+ret=0
+(
+cd signer/general
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test8.zone > signer.out.$n 2>&1
+test -f signed.zone
+) && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+(
+cd signer
+cat example.db.in $key1.key $key2.key > example.db
+$SIGNER -o example -f example.db example.db > /dev/null 2>&1
+) || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+(
+cd signer
+cat example.db.in $key1.key $key2.key > example.db
+$SIGNER -3 - -H 10 -o example -f example.db example.db > /dev/null 2>&1
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking NSEC3 signing with empty nonterminals above a delegation ($n)"
+ret=0
+zone=example
+key1=`$KEYGEN -K signer -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+(
+cd signer
+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 2>&1
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that dnsssec-signzone updates originalttl on ttl changes ($n)"
+ret=0
+zone=example
+key1=`$KEYGEN -K signer -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a RSASHA1 -b 1024 -n zone $zone`
+(
+cd signer
+cat example.db.in $key1.key $key2.key > example.db
+$SIGNER -o example -f example.db.before example.db > /dev/null 2>&1
+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 2>&1
+)
+grep "SOA 5 1 50" signer/example.db.after > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone keeps valid signatures from removed keys ($n)"
+ret=0
+zone=example
+key1=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a RSASHA1 -b 1024 -n zone $zone`
+key2=`$KEYGEN -K signer -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+keyid2=`echo $key2 | sed 's/^Kexample.+005+0*\([0-9]\)/\1/'`
+key3=`$KEYGEN -K signer -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+keyid3=`echo $key3 | sed 's/^Kexample.+005+0*\([0-9]\)/\1/'`
+(
+cd signer
+cat example.db.in $key1.key $key2.key > example.db
+$SIGNER -D -o example example.db > /dev/null 2>&1
+
+# 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 2>&1
+) || ret=1
+grep " $keyid2 " signer/example.db.signed > /dev/null 2>&1 || ret=1
+grep " $keyid3 " signer/example.db.signed > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone -R purges signatures from removed keys ($n)"
+ret=0
+(
+cd signer
+$SIGNER -RD -o example example.db > /dev/null 2>&1
+) || ret=1
+grep " $keyid2 " signer/example.db.signed > /dev/null 2>&1 && ret=1
+grep " $keyid3 " signer/example.db.signed > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone keeps valid signatures from inactive keys ($n)"
+ret=0
+zone=example
+(
+cd signer
+cp -f example.db.in example.db
+$SIGNER -SD -o example example.db > /dev/null 2>&1
+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 2>&1
+) || ret=1
+grep " $keyid2 " signer/example.db.signed > /dev/null 2>&1 || ret=1
+grep " $keyid3 " signer/example.db.signed > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone -Q purges signatures from inactive keys ($n)"
+ret=0
+(
+cd signer
+$SIGNER -SDQ -o example example.db > /dev/null 2>&1
+) || ret=1
+grep " $keyid2 " signer/example.db.signed > /dev/null 2>&1 && ret=1
+grep " $keyid3 " signer/example.db.signed > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone retains unexpired signatures ($n)"
+ret=0
+(
+cd signer
+$SIGNER -Sxt -o example example.db > signer.out.1 2>&1
+$SIGNER -Sxt -o example -f example.db.signed example.db.signed > signer.out.2 2>&1
+) || ret=1
+gen1=`awk '/generated/ {print $3}' signer/signer.out.1`
+retain1=`awk '/retained/ {print $3}' signer/signer.out.1`
+drop1=`awk '/dropped/ {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 `expr "$gen1" + "$retain1"` ] || ret=1
+[ "$gen2" -eq 0 ] || ret=1
+[ "$drop2" -eq 0 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec) ($n)"
+ret=0
+(
+cd signer
+# 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 2>&1
+) || 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
+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 2>&1
+) || 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec3) ($n)"
+ret=0
+(
+cd signer
+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 2>&1
+) || 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
+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 2>&1
+) || 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone output format ($n)"
+ret=0
+(
+cd signer
+$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 2>&1
+$SIGNER -O raw=0 -f signer.out.6 -Sxt -o example example.db > /dev/null 2>&1
+$SIGNER -O raw -f - -Sxt -o example example.db > signer.out.7 2> /dev/null
+) || ret=1
+awk '/IN *SOA/ {if (NF != 11) exit(1)}' signer/signer.out.3 || ret=1
+awk '/IN *SOA/ {if (NF != 7) 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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone output format ($n)"
+ret=0
+(
+cd signer
+$SIGNER -O full -f - -Sxt -o example example.db > signer.out.3 2>&1
+$SIGNER -O text -f - -Sxt -o example example.db > signer.out.4 2>&1
+) || ret=1
+awk '/IN *SOA/ {if (NF != 11) exit(1)}' signer/signer.out.3 || ret=1
+awk '/IN *SOA/ {if (NF != 7) exit(1)}' signer/signer.out.4 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking TTLs are capped by dnssec-signzone -M ($n)"
+ret=0
+(
+cd signer
+$SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db > /dev/null 2>&1
+) || ret=1
+awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnssec-signzone -N date ($n)"
+ret=0
+(
+cd signer
+$SIGNER -O full -f signer.out.9 -S -N date -o example example2.db > /dev/null 2>&1
+) || ret=1
+now=`$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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking validated data are not cached longer than originalttl ($n)"
+ret=0
+$DIG $DIGOPTS +ttl +noauth a.ttlpatch.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Test that "rndc secroots" is able to dump trusted keys
+echo_i "checking rndc secroots ($n)"
+ret=0
+$RNDCCMD 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
+keyid=`cat ns1/managed.key.id`
+cp ns4/named.secroots named.secroots.test$n
+linecount=`grep "./RSAMD5/$keyid ; trusted" named.secroots.test$n | wc -l`
+[ "$linecount" -eq 1 ] || ret=1
+linecount=`cat named.secroots.test$n | wc -l`
+[ "$linecount" -eq 10 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS normalthenrrsig.secure.example. @10.53.0.4 a > /dev/null || ret=1
+ans=`$DIG $DIGOPTS +short normalthenrrsig.secure.example. @10.53.0.4 rrsig` || ret=1
+expect=`$DIG $DIGOPTS +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 $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +short rrsigonly.secure.example. @10.53.0.4 rrsig` || ret=1
+test -z "$ans" || ret=1
+# also check that RA is cleared
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+#
+# RT21868 regression test.
+#
+echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+#
+# RT22007 regression test.
+#
+echo_i "checking optout NSEC3 referral with only insecure delegations ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+status=`expr $status + $ret`
+echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a zone finishing the transition from RSASHA1 to RSASHA256 validates secure ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking positive and negative validation with negative trust anchors ($n)"
+ret=0
+
+#
+# check correct initial behavior
+#
+$DIG $DIGOPTS 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 $DIGOPTS 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 $DIGOPTS 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 != 0 ]; then echo_i "failed - checking initial state"; fi
+status=`expr $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 2 ] || 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
+$RNDCCMD 10.53.0.4 reload 2>&1 | sed 's/^/ns4 /' | cat_i
+$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
+lines=`wc -l < rndc.out.ns4.test$n.2`
+[ "$lines" -eq 4 ] || ret=1
+start=`$PERL -e 'print time()."\n";'`
+
+if [ $ret != 0 ]; then echo_i "failed - adding NTA's failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# check behavior with NTA's in place
+#
+$DIG $DIGOPTS 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 $DIGOPTS 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 $DIGOPTS 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 $DIGOPTS 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
+grep "bogus.example: expiry" ns4/named.secroots > /dev/null || ret=1
+grep "badds.example: expiry" ns4/named.secroots > /dev/null || ret=1
+grep "secure.example: expiry" ns4/named.secroots > /dev/null || ret=1
+grep "fakenode.secure.example: expiry" ns4/named.secroots > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed - with NTA's in place failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+echo_i "waiting for NTA rechecks/expirations"
+
+#
+# secure.example and badds.example used default nta-duration
+# (configured as 10s in ns4/named1.conf), but nta recheck interval
+# is configured to 7s, so at t=8 the NTAs for secure.example and
+# fakenode.secure.example should both be lifted, but badds.example
+# should still be going.
+#
+$PERL -e 'my $delay = '$start' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+$DIG $DIGOPTS 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 $DIGOPTS 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 $DIGOPTS 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 != 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# bogus.example was set to expire in 20s, so at t=11
+# it should still be NTA'd, but badds.example used the default
+# lifetime of 10s, so it should revert to SERVFAIL now.
+#
+$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=`wc -l < rndc.out.ns4.test$n._11`
+[ "$lines" -le 2 ] || ret=1
+grep "bogus.example: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1
+grep "badds.example: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1
+$DIG $DIGOPTS 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 $DIGOPTS 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 $DIGOPTS 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 != 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# at t=21, all the NTAs should have expired.
+#
+$PERL -e 'my $delay = '$start' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+# check correct behavior after bogus.example expiry
+$DIG $DIGOPTS 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 $DIGOPTS 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=`wc -l < rndc.out.ns4.test$n.3`
+[ "$lines" -eq 0 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi
+status=`expr $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: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1
+$DIG $DIGOPTS 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: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1
+$DIG $DIGOPTS 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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 "'nta' failed: not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+n=`expr $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
+grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# check NTA persistence across restarts
+#
+n=`expr $n + 1`
+echo_i " testing NTA persistence across restarts ($n)"
+$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
+lines=`wc -l < rndc.out.ns4.test$n.1`
+[ "$lines" -eq 0 ] || ret=1
+$RNDCCMD 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/I:ns4 /'
+$RNDCCMD 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/I:ns4 /'
+$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
+lines=`wc -l < rndc.out.ns4.test$n.2`
+[ "$lines" -eq 2 ] || ret=1
+start=`$PERL -e 'print time()."\n";'`
+
+if [ $ret != 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+echo_i "killing ns4 with SIGTERM"
+cd ns4
+$KILL -TERM `cat named.pid`
+rm -f named.pid
+cd ..
+
+#
+# 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"
+$PERL -e 'my $delay = '$start' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+
+if
+ $PERL $SYSTEMTESTTOP/start.pl --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 1 ] || ret=1
+grep "bogus.example: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1
+$DIG $DIGOPTS 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 $DIGOPTS 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 != 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# check "regular" attribute in NTA file works as expected at named
+# startup.
+#
+n=`expr $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 0 ] || ret=1
+# initially, secure.example. validates with AD=1
+$DIG $DIGOPTS 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"
+cd ns4
+$KILL -TERM `cat named.pid`
+rm -f named.pid
+cd ..
+
+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.
+#
+year=`date +%Y`
+future="`expr 20 + ${year}`0101010000"
+echo "secure.example. regular $future" > ns4/_default.nta
+start=`$PERL -e 'print time()."\n";'`
+
+if
+ $PERL $SYSTEMTESTTOP/start.pl --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 7s, so at t=10 the NTAs for
+# secure.example. should be lifted as it is not a forced NTA.
+echo_i "waiting till 10s have passed after ns4 was restarted"
+$PERL -e 'my $delay = '$start' + 10 - 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 $DIGOPTS 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 != 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# check "forced" attribute in NTA file works as expected at named
+# startup.
+#
+n=`expr $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 0 ] || ret=1
+# initially, secure.example. validates with AD=1
+$DIG $DIGOPTS 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"
+cd ns4
+$KILL -TERM `cat named.pid`
+rm -f named.pid
+cd ..
+
+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
+ $PERL $SYSTEMTESTTOP/start.pl --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 7s, but even at t=10 the NTAs for
+# secure.example. should not be lifted as it is a forced NTA.
+echo_i "waiting till 10s have passed after ns4 was restarted"
+$PERL -e 'my $delay = '$start' + 10 - 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 $DIGOPTS 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 != 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+#
+# check that NTA lifetime read from file is clamped to 1 week.
+#
+n=`expr $n + 1`
+echo_i "testing loading out of bounds lifetime from NTA file ($n)"
+
+echo_i "killing ns4 with SIGTERM"
+cd ns4
+$KILL -TERM `cat named.pid`
+rm -f named.pid
+cd ..
+
+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
+ $PERL $SYSTEMTESTTOP/start.pl --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
+$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
+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
+
+# cleanup
+$RNDCCMD 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.3 2>/dev/null
+
+if [ $ret != 0 ]; then echo_i "failed - NTA lifetime clamping failed"; fi
+status=`expr $status + $ret`
+ret=0
+
+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
+ {
+ $PERL dnssec_update_test.pl -s 10.53.0.3 -p ${PORT} dynamic.example. || ret=1
+ } | cat_i
+ [ $ret -eq 1 ] && status=1
+else
+ echo_i "The DNSSEC update test requires the Net::DNS library." >&2
+fi
+
+n=`expr $n + 1`
+echo_i "checking managed key maintenance has not started yet ($n)"
+ret=0
+[ -f "ns4/managed-keys.bind.jnl" ] && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Reconfigure caching server to use "dnssec-validation auto", and repeat
+# some of the DNSSEC validation tests to ensure that it works correctly.
+echo_i "switching to automatic root key configuration"
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking negative validation ($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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that root DS queries validate ($n)"
+ret=0
+$DIG $DIGOPTS +noauth . @10.53.0.1 ds > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that DS at a RFC 1918 empty zone lookup succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth 10.in-addr.arpa ds @10.53.0.6 >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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+status=`expr $status + $ret`
+echo_i "checking expired signatures do not validate ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+kskname=`$KEYGEN -q -3 -r $RANDFILE -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 $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that the NSEC record is properly generated when DNSKEY are added via auto-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that the NSEC3 record is properly generated when DNSKEY are added via auto-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}'`
+ [ -n "$salt" -a "$salt" != "-" ] && break
+ echo_i "sleeping ...."
+ sleep 1
+done;
+[ "$salt" != "-" ] || ret=1
+[ `expr "${salt}" : ".*"` -eq 16 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}'`
+ [ -n "$salt" -a "$salt" != "$oldsalt" ] && break
+ echo_i "sleeping ...."
+ sleep 1
+done;
+[ "$salt" != "$oldsalt" ] || ret=1
+[ `expr "$salt" : ".*"` -eq 16 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check rndc signing -list output ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -list dynamic.example 2>&1 > signing.out
+grep "No signing records found" signing.out > /dev/null 2>&1 || {
+ ret=1
+ sed 's/^/ns3 /' signing.out | cat_i
+}
+$RNDCCMD 10.53.0.3 signing -list update-nsec3.example 2>&1 > signing.out
+grep "Done signing with key .*/NSEC3RSASHA1" signing.out > /dev/null 2>&1 || {
+ ret=1
+ sed 's/^/ns3 /' signing.out | cat_i
+}
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "clear signing records ($n)"
+$RNDCCMD 10.53.0.3 signing -clear all update-nsec3.example > /dev/null || ret=1
+sleep 1
+$RNDCCMD 10.53.0.3 signing -list update-nsec3.example 2>&1 > signing.out
+grep "No signing records found" signing.out > /dev/null 2>&1 || {
+ ret=1
+ sed 's/^/ns3 /' signing.out | cat_i
+}
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a insecure zone beneath a cname resolves ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a secure zone beneath a cname resolves ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking dnskey query with no data still gets put in cache ($n)"
+ret=0
+myDIGOPTS="+noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT} @10.53.0.4"
+firstVal=`$DIG $myDIGOPTS insecure.example. dnskey| awk '$1 != ";;" { print $2 }'`
+sleep 1
+secondVal=`$DIG $myDIGOPTS insecure.example. dnskey| awk '$1 != ";;" { print $2 }'`
+if [ ${firstVal:-0} -eq ${secondVal:-0} ]
+then
+ sleep 1
+ thirdVal=`$DIG $myDIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that a split dnssec dnssec-signzone work ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that a smart split dnssec dnssec-signzone work ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS 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 != 0 ]; then echo_i "nsec3 chain generation not complete"; fi
+$DIG $DIGOPTS +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 $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check dnssec-dsfromkey from stdin ($n)"
+ret=0
+$DIG $DIGOPTS 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$TP > canonical2.$n || ret=1
+diff -b canonical1.$n canonical2.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 -q -r $RANDFILE 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)"
+ret=0
+$DIG $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing expiring records aren't resigned with 'no-resign' ($n)"
+ret=0
+$DIG $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
+cmp -s nosign.before dig.out.ns3.test$n || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+for file in K*.moved; do
+ mv $file `basename $file .moved`
+done
+$SIGNER -S -r $RANDFILE -N increment -e now+1mi -o expiring.example expiring.example.db > /dev/null 2>&1
+) || ret=1
+$RNDCCMD 10.53.0.3 reload expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i
+
+$RNDCCMD 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+$DIG $ANSWEROPTS +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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:-0} -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ ${ttl:-0} -le 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $ADDITIONALOPTS +cd expiring.example ns @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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:-0} -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ ${ttl:-0} -le 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $ADDITIONALOPTS +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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:-0} -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ ${ttl:-0} -le 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $ANSWEROPTS +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)"
+ret=0
+$DIG $ANSWEROPTS +cd expired.example soa @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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 -le 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+copy_setports ns4/named4.conf.in ns4/named.conf
+$RNDCCMD 10.53.0.4 reconfig 2>&1 | sed 's/^/I:ns4 /'
+sleep 3
+
+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 $ADDITIONALOPTS +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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 -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ $ttl -le 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with acache off; ($n)"
+ret=0
+$RNDCCMD 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+$DIG $ADDITIONALOPTS +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+$DIG $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 -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ $ttl -le 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing DNSKEY lookup via CNAME ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cnameandkey.secure.example. \
+ @10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing KEY lookup at CNAME (present) ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cnameandkey.secure.example. \
+ @10.53.0.3 key > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing KEY lookup at CNAME (not present) ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cnamenokey.secure.example. \
+ @10.53.0.3 key > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing DNSKEY lookup via DNAME ($n)"
+ret=0
+$DIG $DIGOPTS a.dnameandkey.secure.example. \
+ @10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "testing KEY lookup via DNAME ($n)"
+ret=0
+$DIG $DIGOPTS b.dnameandkey.secure.example. \
+ @10.53.0.3 key > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that named doesn't loop when all private keys are not available ($n)"
+ret=0
+lines=`grep "reading private key file expiring.example" ns3/named.run | wc -l`
+test ${lines:-1000} -lt 15 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check against against missing nearest provable proof ($n)"
+$DIG $DIGOPTS +norec b.c.d.optout-tld. \
+ @10.53.0.6 ds > dig.out.ds.ns6.test$n || ret=1
+nsec3=`grep "IN.NSEC3" dig.out.ds.ns6.test$n | wc -l`
+[ $nsec3 -eq 2 ] || ret=1
+$DIG $DIGOPTS +norec b.c.d.optout-tld. \
+ @10.53.0.6 A > dig.out.ns6.test$n || ret=1
+nsec3=`grep "IN.NSEC3" dig.out.ns6.test$n | wc -l`
+[ $nsec3 -eq 1 ] || ret=1
+$DIG $DIGOPTS 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 $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that key id are logged when dumping the cache ($n)"
+ret=0
+$RNDCCMD 10.53.0.4 dumpdb 2>&1 | sed 's/^/ns4 /' | cat_i
+sleep 1
+grep "; key id = " ns4/named_dump.db > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check dig's +nocrypto flag ($n)"
+ret=0
+$DIG $DIGOPTS +norec +nocrypto DNSKEY . \
+ @10.53.0.1 > dig.out.dnskey.ns1.test$n || ret=1
+grep '256 3 1 \[key id = [1-9][0-9]*]' dig.out.dnskey.ns1.test$n > /dev/null || ret=1
+grep 'RRSIG.* \[omitted]' dig.out.dnskey.ns1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +norec +nocrypto DS example \
+ @10.53.0.1 > dig.out.ds.ns1.test$n || ret=1
+grep 'DS.* 3 [12] \[omitted]' dig.out.ds.ns1.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check simultaneous inactivation and publishing of dnskeys removes inactive signature ($n)"
+ret=0
+cnt=0
+while :
+do
+$DIG $DIGOPTS 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=`expr $cnt + 1`
+test $cnt -gt 120 && break
+sleep 1
+done
+test $keys -gt 2 || ret=1
+sigs=`grep RRSIG dig.out.ns3.test$n | wc -l`
+sigs=`expr $sigs + 0`
+n=`expr $n + 1`
+test $sigs -eq 2 || ret=1
+if test $ret != 0 ; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that increasing the sig-validity-interval resigning triggers re-signing"
+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
+for i in 1 2 3 4 5 6 7 8 9 0
+do
+after=`$DIG axfr siginterval.example -p ${PORT} @10.53.0.3 | grep RRSIG.SOA`
+test "$before" != "$after" && break
+sleep 1
+done
+n=`expr $n + 1`
+if test "$before" = "$after" ; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+copy_setports ns4/named4.conf.in ns4/named.conf
+$RNDCCMD 10.53.0.4 reconfig 2>&1 | sed 's/^/I:ns4 /'
+sleep 3
+
+echo_i "check insecure delegation between static-stub zones ($n)"
+ret=0
+$DIG $DIGOPTS 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 $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+name=`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 $DIGOPTS +noall +answer $name @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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that split rrsigs are handled ($n)"
+ret=0
+$DIG $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)"
+ret=0
+alg=1
+until test $alg = 256
+do
+ size=
+ case $alg in
+ 1) size="-b 512";;
+ 2) # Diffie Helman
+ alg=`expr $alg + 1`
+ continue;;
+ 3) size="-b 512";;
+ 5) size="-b 512";;
+ 6) size="-b 512";;
+ 7) size="-b 512";;
+ 8) size="-b 512";;
+ 10) size="-b 1024";;
+ 157|160|161|162|163|164|165) # private - non standard
+ alg=`expr $alg + 1`
+ continue;;
+ esac
+ key1=`$KEYGEN -a $alg $size -n zone -r $RANDFILE example 2> keygen.err`
+ if grep "unsupported algorithm" keygen.err > /dev/null
+ then
+ alg=`expr $alg + 1`
+ continue
+ fi
+ if test -z "$key1"
+ then
+ echo_i "'$KEYGEN -a $alg': failed"
+ cat keygen.err
+ ret=1
+ alg=`expr $alg + 1`
+ continue
+ fi
+ $SETTIME -I now+4d $key1.private > /dev/null
+ key2=`$KEYGEN -v 10 -r $RANDFILE -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=`expr $alg + 1`
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)"
+ret=0
+$DIG $DIGOPTS +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:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+#
+# Test for +sigchase with a null set of trusted keys.
+#
+$DIG $DIGOPTS @10.53.0.3 +sigchase +trusted-key=/dev/null > dig.out.ns3.test$n 2>&1
+if grep "Invalid option: +sigchase" dig.out.ns3.test$n > /dev/null
+then
+ echo_i "Skipping 'dig +sigchase' tests"
+ n=`expr $n + 1`
+else
+ echo_i "checking that 'dig +sigchase' doesn't loop with future inception ($n)"
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 dnskey future.example +sigchase \
+ +trusted-key=ns3/trusted-future.key > dig.out.ns3.test$n &
+ pid=$!
+ sleep 1
+ $KILL -9 $pid 2> /dev/null
+ wait $pid
+ grep ";; No DNSKEY is valid to check the RRSIG of the RRset: FAILED" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ n=`expr $n + 1`
+fi
+
+echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA > dig.out.ns3.test$n
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that CDS records are signed using KSK by with dnssec-auto ($n)"
+ret=0
+$DIG $DIGOPTS +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:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that a lone non matching CDS record is rejected ($n)"
+ret=0
+(
+echo zone cds-update.secure
+echo server 10.53.0.2 ${PORT}
+echo update delete cds-update.secure CDS
+$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
+$DSFROMKEY -C -A -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+echo send
+) | $NSUPDATE > nsupdate.out.test$n 2>&1
+grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +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 0 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" |
+$DSFROMKEY -C -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+echo send
+) | $NSUPDATE
+$DIG $DIGOPTS +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:-0} -eq 2 || ret=1
+lines=`awk '$4 == "CDS" {print}' dig.out.test$n | wc -l`
+test ${lines:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA > dig.out.ns3.test$n
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" |
+$DSFROMKEY -C -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
+$DSFROMKEY -C -A -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+echo send
+) | $NSUPDATE
+$DIG $DIGOPTS +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:-0} -eq 2 || ret=1
+lines=`awk '$4 == "CDS" {print}' dig.out.test$n | wc -l`
+test ${lines:-0} -eq 4 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A > dig.out.ns3.test$n
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)"
+ret=0
+$DIG $DIGOPTS +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:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A > dig.out.ns3.test$n
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)"
+ret=0
+$DIG $DIGOPTS +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:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A > dig.out.ns3.test$n
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that a lone non matching CDNSKEY record is rejected ($n)"
+ret=0
+(
+echo zone cdnskey-update.secure
+echo server 10.53.0.2 ${PORT}
+echo update delete cdnskey-update.secure CDNSKEY
+echo send
+$DIG $DIGOPTS +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 > nsupdate.out.test$n 2>&1
+grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +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 0 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A > dig.out.ns3.test$n
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +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 $DIGOPTS +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:-0} -eq 2 || ret=1
+lines=`awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l`
+test ${lines:-0} -eq 1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +dnssec @10.53.0.5 SOA . > dig.out.ns5.test$n
+grep "status: SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
+sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
+$DIG $DIGOPTS +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 $DIGOPTS +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:-0} -eq 2 || ret=1
+lines=`awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l`
+test ${lines:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+$KEYGEN -q -r $RANDFILE -3 -fK remove > /dev/null
+$KEYGEN -q -r $RANDFILE -3 remove > /dev/null
+echo > remove.db.signed
+$SIGNER -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n 2>&1
+)
+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
+$SIGNER -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n 2>&1
+)
+grep "RRSIG MX" signer/remove.db.signed > /dev/null && {
+ ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
+}
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+echo > remove.db.signed
+$SIGNER -3 - -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n 2>&1
+)
+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
+$SIGNER -3 - -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n 2>&1
+)
+grep "RRSIG MX" signer/remove.db.signed > /dev/null && {
+ ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
+}
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 $DIGOPTS 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that KEY-TAG trust-anchor-telemetry queries are logged ($n)"
+ret=0
+$DIG $DIGOPTS . 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "check that multiple KEY-TAG trust-anchor-telemetry options don't leak memory ($n)"
+ret=0
+$DIG $DIGOPTS . 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
+$PERL $SYSTEMTESTTOP/stop.pl . ns1 || ret=1
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1 || ret=1
+n=$(($n+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/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..4f90895
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..14cfa3e
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..aac8dd9
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..9bca0c1
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..d04a1b0
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..35f8cf7
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..a82c42c
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..264dce8
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..a250f50
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ /*
+ * 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..ea6852a
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..e602bfc
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..acd1d7e
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 0;
+};
diff --git a/bin/tests/system/dnstap/clean.sh b/bin/tests/system/dnstap/clean.sh
new file mode 100644
index 0000000..261200b
--- /dev/null
+++ b/bin/tests/system/dnstap/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.stats
+rm -f dig.out*
+rm -f dnstap.out
+rm -f dnstap.out.save
+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*/named.lock
+rm -f ydump.out
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..abaaa73
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..dbc9364
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..1c3b5ef
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..e18ec38
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..05ad706
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..ef735a6
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..9f93bb6
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..fe6462b
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 5;
+};
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..441e37f
--- /dev/null
+++ b/bin/tests/system/dnstap/ns1/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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";
+ dnstap { all; };
+ send-cookie no;
+ require-server-cookie no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ 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..dab5cea
--- /dev/null
+++ b/bin/tests/system/dnstap/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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 b/bin/tests/system/dnstap/ns2/example.db
new file mode 100644
index 0000000..4073dc2
--- /dev/null
+++ b/bin/tests/system/dnstap/ns2/example.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..0ca67af
--- /dev/null
+++ b/bin/tests/system/dnstap/ns2/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ 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";
+ dnstap { all; };
+ send-cookie no;
+ require-server-cookie no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { any; };
+};
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..e19d189
--- /dev/null
+++ b/bin/tests/system/dnstap/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+server 10.53.0.1 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/dnstap/ns4/named.conf.in b/bin/tests/system/dnstap/ns4/named.conf.in
new file mode 100644
index 0000000..3aa9dd6
--- /dev/null
+++ b/bin/tests/system/dnstap/ns4/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+server 10.53.0.1 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/dnstap/setup.sh b/bin/tests/system/dnstap/setup.sh
new file mode 100644
index 0000000..3a14fe9
--- /dev/null
+++ b/bin/tests/system/dnstap/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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/dnstap/tests.sh b/bin/tests/system/dnstap/tests.sh
new file mode 100644
index 0000000..b09284c
--- /dev/null
+++ b/bin/tests/system/dnstap/tests.sh
@@ -0,0 +1,591 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+short -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+status=0
+
+for bad in bad-*.conf
+do
+ ret=0
+ echo_i "checking that named-checkconf detects error in $bad"
+ $CHECKCONF $bad > /dev/null 2>&1
+ if [ $? != 1 ]; then echo_i "failed"; ret=1; fi
+ status=`expr $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
+ if [ $? != 0 ]; then echo_i "failed"; ret=1; fi
+ status=`expr $status + $ret`
+done
+
+$DIG $DIGOPTS @10.53.0.3 a.example > dig.out
+
+# 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
+ $FSTRM_CAPTURE -t protobuf:dnstap.Dnstap -u ns4/dnstap.out \
+ -w dnstap.out > fstrm_capture.out 2>&1 &
+ fstrm_capture_pid=$!
+fi
+
+$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
+
+$DIG $DIGOPTS @10.53.0.3 a.example > dig.out
+
+# 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`
+
+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`
+
+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`
+
+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=`expr $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=`expr $status + $ret`
+
+echo_i "checking AUTH_QUERY message counts"
+ret=0
+[ $aq1 -eq 2 ] || {
+ echo_i "ns1 $aq1 exepcted 2"
+ ret=1
+}
+[ $aq2 -eq 1 ] || {
+ echo_i "ns2 $aq2 expected 1"
+ ret=1
+}
+[ $aq3 -eq 0 ] || {
+ echo_i "ns3 $aq3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $status + $ret`
+
+echo_i "checking CLIENT_QUERY message counts"
+ret=0
+[ $cq1 -eq 1 ] || {
+ echo_i "ns1 $cq1 expected 1"
+ ret=1
+}
+[ $cq2 -eq 1 ] || {
+ echo_i "ns2 $cq2 expected 1"
+ ret=1
+}
+[ $cq3 -eq 2 ] || {
+ echo_i "ns3 $cq3 expected 2"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $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=`expr $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=`expr $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`
+
+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`
+
+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`
+
+echo_i "checking UDP message counts"
+ret=0
+[ $udp1 -eq 0 ] || {
+ echo_i "ns1 $udp1 expected 0"
+ ret=1
+}
+[ $udp2 -eq 0 ] || {
+ echo_i "ns2 $udp2 expected 0"
+ ret=1
+}
+[ $udp3 -eq 2 ] || {
+ echo_i "ns3 $udp3 expected 2"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+HAS_PYYAML=0
+if [ -n "$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=`expr $status + $ret`
+fi
+
+if [ -n "$FSTRM_CAPTURE" ] ; then
+ $DIG $DIGOPTS @10.53.0.4 a.example > dig.out
+
+ echo_i "checking unix socket message counts"
+ sleep 2
+ 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`
+
+ 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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+ echo_i "checking RESOLVER_RESPONSE message counts"
+ ret=0
+ [ $rr4 -eq 0 ] || {
+ echo_i "ns4 $rr4 expected 0"
+ ret=1
+ }
+ mv dnstap.out dnstap.out.save
+ $FSTRM_CAPTURE -t protobuf:dnstap.Dnstap -u ns4/dnstap.out \
+ -w dnstap.out > fstrm_capture.out 2>&1 &
+ fstrm_capture_pid=$!
+ $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
+ 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`
+
+ 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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+ echo_i "checking RESOLVER_RESPONSE message counts"
+ ret=0
+ [ $rr4 -eq 0 ] || {
+ echo_i "ns4 $rr4 expected 0"
+ ret=1
+ }
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py
new file mode 100644
index 0000000..50ad791
--- /dev/null
+++ b/bin/tests/system/dnstap/ydump.py
@@ -0,0 +1,26 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+try:
+ import yaml
+except:
+ print("No python yaml module, skipping")
+ exit(1)
+
+import subprocess
+import pprint
+import sys
+
+DNSTAP_READ=sys.argv[1]
+DATAFILE=sys.argv[2]
+
+f = subprocess.Popen([DNSTAP_READ, '-y', DATAFILE], stdout=subprocess.PIPE)
+pprint.pprint([l for l in yaml.load_all(f.stdout)])
diff --git a/bin/tests/system/dscp/clean.sh b/bin/tests/system/dscp/clean.sh
new file mode 100644
index 0000000..b29303a
--- /dev/null
+++ b/bin/tests/system/dscp/clean.sh
@@ -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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */root.bk
+rm -f dig.out.10.53.0.?
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f ns*/named.lock
diff --git a/bin/tests/system/dscp/ns1/named.args b/bin/tests/system/dscp/ns1/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns1/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns1/named.conf.in b/bin/tests/system/dscp/ns1/named.conf.in
new file mode 100644
index 0000000..a6e8b41
--- /dev/null
+++ b/bin/tests/system/dscp/ns1/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 46;
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/dscp/ns1/root.db b/bin/tests/system/dscp/ns1/root.db
new file mode 100644
index 0000000..3bd5829
--- /dev/null
+++ b/bin/tests/system/dscp/ns1/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+. SOA ns1.nil-servers. marka.isc.org. 1 3600 1200 3600000 1200
+. NS ns1.nil-servers.
+. NS ns2.nil-servers.
+ns1.nil-servers. A 10.53.0.1
+ns2.nil-servers. A 10.53.0.2
+xxx.example. A 10.53.0.1
+xxx.tld. A 10.53.0.1
diff --git a/bin/tests/system/dscp/ns2/named.args b/bin/tests/system/dscp/ns2/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns2/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns2/named.conf.in b/bin/tests/system/dscp/ns2/named.conf.in
new file mode 100644
index 0000000..6419a01
--- /dev/null
+++ b/bin/tests/system/dscp/ns2/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 46;
+ 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;
+};
+
+zone "." {
+ type slave;
+ file "root.bk";
+ masters { 10.53.0.1; };
+};
diff --git a/bin/tests/system/dscp/ns3/hint.db b/bin/tests/system/dscp/ns3/hint.db
new file mode 100644
index 0000000..5fe03e7
--- /dev/null
+++ b/bin/tests/system/dscp/ns3/hint.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+. NS ns1.nil-servers.
+. NS ns2.nil-servers.
+ns1.nil-servers. A 10.53.0.1
+ns2.nil-servers. A 10.53.0.2
diff --git a/bin/tests/system/dscp/ns3/named.args b/bin/tests/system/dscp/ns3/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns3/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns3/named.conf.in b/bin/tests/system/dscp/ns3/named.conf.in
new file mode 100644
index 0000000..71d72cd
--- /dev/null
+++ b/bin/tests/system/dscp/ns3/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 46;
+ 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; };
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
diff --git a/bin/tests/system/dscp/ns4/named.args b/bin/tests/system/dscp/ns4/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns4/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns4/named.conf.in b/bin/tests/system/dscp/ns4/named.conf.in
new file mode 100644
index 0000000..70dd5e5
--- /dev/null
+++ b/bin/tests/system/dscp/ns4/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 47;
+ query-source dscp 46 address 10.53.0.4;
+ notify-source 10.53.0.4 dscp 46;
+ transfer-source 10.53.0.4 dscp 46;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on dscp 46 { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/dscp/ns4/root.db b/bin/tests/system/dscp/ns4/root.db
new file mode 100644
index 0000000..d1627db
--- /dev/null
+++ b/bin/tests/system/dscp/ns4/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+. SOA ns4.nil-servers. marka.isc.org. 1 3600 1200 3600000 1200
+. NS ns4.nil-servers.
+. NS ns5.nil-servers.
+ns4.nil-servers. A 10.53.0.4
+ns5.nil-servers. A 10.53.0.5
+xxx.example. A 10.53.0.1
+xxx.tld. A 10.53.0.1
diff --git a/bin/tests/system/dscp/ns5/named.args b/bin/tests/system/dscp/ns5/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns5/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns5/named.conf.in b/bin/tests/system/dscp/ns5/named.conf.in
new file mode 100644
index 0000000..e2726c3
--- /dev/null
+++ b/bin/tests/system/dscp/ns5/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 47;
+ query-source dscp 46 address 10.53.0.5;
+ notify-source 10.53.0.5 dscp 46;
+ transfer-source 10.53.0.5 dscp 46;
+ alt-transfer-source 10.53.0.5 dscp 46;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on dscp 46 { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type slave;
+ file "root.bk";
+ masters { 10.53.0.4; };
+};
diff --git a/bin/tests/system/dscp/ns6/hint.db b/bin/tests/system/dscp/ns6/hint.db
new file mode 100644
index 0000000..8c54e3a
--- /dev/null
+++ b/bin/tests/system/dscp/ns6/hint.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+. NS ns4.nil-servers.
+. NS ns5.nil-servers.
+ns4.nil-servers. A 10.53.0.4
+ns5.nil-servers. A 10.53.0.5
diff --git a/bin/tests/system/dscp/ns6/named.args b/bin/tests/system/dscp/ns6/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns6/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns6/named.conf.in b/bin/tests/system/dscp/ns6/named.conf.in
new file mode 100644
index 0000000..eedbab1
--- /dev/null
+++ b/bin/tests/system/dscp/ns6/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 47;
+ query-source dscp 46 address 10.53.0.6;
+ notify-source 10.53.0.6 dscp 46;
+ transfer-source 10.53.0.6 dscp 46;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on dscp 46 { 10.53.0.6; };
+ listen-on-v6 { none; };
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
diff --git a/bin/tests/system/dscp/ns7/named.args b/bin/tests/system/dscp/ns7/named.args
new file mode 100644
index 0000000..c9a0592
--- /dev/null
+++ b/bin/tests/system/dscp/ns7/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns7/named.conf.in b/bin/tests/system/dscp/ns7/named.conf.in
new file mode 100644
index 0000000..e7c9528
--- /dev/null
+++ b/bin/tests/system/dscp/ns7/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dscp 47;
+ query-source dscp 46 address 10.53.0.7;
+ notify-source 10.53.0.7 dscp 47;
+ transfer-source 10.53.0.7 dscp 47;
+ alt-transfer-source 10.53.0.7 dscp 47;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on dscp 46 { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type slave;
+ file "root.bk";
+ transfer-source 10.53.0.7 dscp 46;
+ notify-source 10.53.0.7 dscp 46;
+ alt-transfer-source 10.53.0.7 dscp 46;
+ masters { 10.53.0.4; };
+};
diff --git a/bin/tests/system/dscp/setup.sh b/bin/tests/system/dscp/setup.sh
new file mode 100644
index 0000000..fa6de38
--- /dev/null
+++ b/bin/tests/system/dscp/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/dscp/tests.sh b/bin/tests/system/dscp/tests.sh
new file mode 100644
index 0000000..e8a20f5
--- /dev/null
+++ b/bin/tests/system/dscp/tests.sh
@@ -0,0 +1,38 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest -p ${PORT}"
+
+status=0
+
+#
+# 10.53.0.1 10.53.0.2 10.53.0.3 have a global dscp setting;
+# 10.53.0.4 10.53.0.5 10.53.0.6 have dscp set in option *-source clauses;
+# 10.53.0.7 has dscp set in zone *-source clauses;
+#
+for server in 10.53.0.1 10.53.0.2 10.53.0.3 10.53.0.4 10.53.0.5 \
+ 10.53.0.6 10.53.0.7
+do
+ echo_i "testing root SOA lookup at $server"
+ for i in 0 1 2 3 4 5 6 7 8 9
+ do
+ ret=0
+ $DIG $DIGOPTS @$server soa . > dig.out.$server
+ grep "status: NOERROR" dig.out.$server > /dev/null || ret=1
+ test $ret = 0 && break
+ sleep 1
+ done
+ test $ret = 0 || { echo_i "failed"; status=`expr $status + $ret`; }
+done
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dsdigest/clean.sh b/bin/tests/system/dsdigest/clean.sh
new file mode 100644
index 0000000..bb40bcb
--- /dev/null
+++ b/bin/tests/system/dsdigest/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
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..215800c
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns1/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..5223279
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns1/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..81156c4
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns1/sign.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh)
+
+cp ../ns2/dsset-good$TP .
+cp ../ns2/dsset-bad$TP .
+
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 2048 -n zone -f KSK $zone`
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $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..ab5ce91
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/bad.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ab5ce91
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/good.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..73a41ba
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "good" {
+ type master;
+ file "good.db.signed";
+};
+
+zone "bad" {
+ type master;
+ 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..2c52d3b
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/sign.sh
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone1=good.
+infile1=good.db.in
+zonefile1=good.db
+zone2=bad.
+infile2=bad.db.in
+zonefile2=bad.db
+
+keyname11=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone1`
+keyname12=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone -f KSK $zone1`
+keyname21=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone2`
+keyname22=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone -f KSK $zone2`
+
+cat $infile1 $keyname11.key $keyname12.key >$zonefile1
+cat $infile2 $keyname21.key $keyname22.key >$zonefile2
+
+$SIGNER -P -g -r $RANDFILE -o $zone1 $zonefile1 > /dev/null
+$SIGNER -P -g -r $RANDFILE -o $zone2 $zonefile2 > /dev/null
+
+DSFILENAME1=dsset-`echo $zone1 |sed -e "s/\.$//g"`$TP
+DSFILENAME2=dsset-`echo $zone2 |sed -e "s/\.$//g"`$TP
+$DSFROMKEY -a SHA-256 $keyname12 > $DSFILENAME1
+$DSFROMKEY -a SHA-256 $keyname22 > $DSFILENAME2
+
+supported=`cat ../supported`
+case "$supported" in
+ gost) algo=GOST ;;
+ *) algo=SHA-384 ;;
+esac
+
+$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..1bc6215
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns3/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+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-enable yes;
+ dnssec-validation yes;
+ dnssec-must-be-secure . yes;
+ /* only SHA-256 is enabled */
+ disable-ds-digests . { SHA-1; GOST; 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..b5a4959
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns4/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+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-enable yes;
+ dnssec-validation yes;
+ /* only SHA-256 is enabled */
+ disable-ds-digests . { SHA-1; GOST; SHA-384; 5; 6; 7; 8; 9; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dsdigest/prereq.sh b/bin/tests/system/dsdigest/prereq.sh
new file mode 100644
index 0000000..1febbd5
--- /dev/null
+++ b/bin/tests/system/dsdigest/prereq.sh
@@ -0,0 +1,28 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+gostfail=0 ecdsafail=0
+$SHELL ../testcrypto.sh -q gost || gostfail=1
+$SHELL ../testcrypto.sh -q ecdsa || ecdsafail=1
+
+if [ $gostfail = 0 -a $ecdsafail = 0 ]; then
+ echo both > supported
+elif [ $gostfail = 1 -a $ecdsafail = 1 ]; then
+ echo_i "This test requires support for ECDSA or GOST cryptography." >&2
+ exit 255
+elif [ $gostfail = 0 ]; then
+ echo gost > supported
+else
+ echo ecdsa > supported
+fi
diff --git a/bin/tests/system/dsdigest/setup.sh b/bin/tests/system/dsdigest/setup.sh
new file mode 100644
index 0000000..71e16a6
--- /dev/null
+++ b/bin/tests/system/dsdigest/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..8f9eb58
--- /dev/null
+++ b/bin/tests/system/dsdigest/tests.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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=`expr $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=`expr $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=`expr $status + $ret`
+echo_i "exit status: $status"
+
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dupsigs/check_journal.pl b/bin/tests/system/dupsigs/check_journal.pl
new file mode 100644
index 0000000..972ea8b
--- /dev/null
+++ b/bin/tests/system/dupsigs/check_journal.pl
@@ -0,0 +1,209 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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( $rrsig_id =~ /:DNSKEY$/ ) {
+ if( $n_signing_keys != 2 ) {
+ print "at serial $newserial $rrsig_id was signed $n_signing_keys time(s) when it should have been signed twice\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..7a6d78e
--- /dev/null
+++ b/bin/tests/system/dupsigs/clean.sh
@@ -0,0 +1,19 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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..c7cab8a
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/named.args
@@ -0,0 +1 @@
+-D dupsigs-ns1 -X named.lock -m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -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..296ad0e
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ recursion no;
+ max-journal-size unlimited;
+ port @PORT@;
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ pid-file "named.pid";
+};
+
+zone "signing.test" {
+ type master;
+ 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 120 30;
+};
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..f03503f
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/reset_keys.sh
@@ -0,0 +1,97 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+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 -b 1024 -K $KEYDIR -q -f KSK $zone`
+
+ZSK0=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK1=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK2=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK3=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK4=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK5=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK6=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK7=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK8=`$KEYGEN -a RSASHA256 -b 1024 -K $KEYDIR -q $zone`
+ZSK9=`$KEYGEN -a RSASHA256 -b 1024 -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=`expr $BASE + 300`
+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=`expr $R1 + 300`
+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
+# this isn't long enough for the signing to complete
+R3=`expr $R2 + 60`
+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
+R4=`expr $R3 + 30`
+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..072efe1
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/signing.test.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA ns root.ns 1996072700 3600 1800 86400 60
+@ NS ns
+ns A 127.0.0.1
+ns AAAA ::1
+
+$GENERATE 0-1999 a${0,4,d} AAAA ::$
diff --git a/bin/tests/system/dupsigs/prereq.sh b/bin/tests/system/dupsigs/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/dupsigs/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/dupsigs/setup.sh b/bin/tests/system/dupsigs/setup.sh
new file mode 100644
index 0000000..0c37928
--- /dev/null
+++ b/bin/tests/system/dupsigs/setup.sh
@@ -0,0 +1,20 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -f clean.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..80ddaea
--- /dev/null
+++ b/bin/tests/system/dupsigs/tests.sh
@@ -0,0 +1,35 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+start=`date +%s`
+end=`expr $start + 1200`
+now=$start
+while test $now -lt $end
+do
+ et=`expr $now - $start`
+ echo "=============== $et ============"
+ $JOURNALPRINT ns1/signing.test.db.signed.jnl | $PERL check_journal.pl
+ $DIG axfr signing.test -p 5300 @10.53.0.1 > dig.out.at$et
+ awk '$4 == "RRSIG" { print $11 }' dig.out.at$et | sort | uniq -c
+ lines=`awk '$4 == "RRSIG" { print}' dig.out.at$et | wc -l`
+ if [ ${et} -ne 0 -a ${lines} -ne 4009 ]
+ then
+ echo_i "failed"
+ status=`expr $status + 1`
+ fi
+ sleep 20
+ now=`date +%s`
+done
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dyndb/Makefile.in b/bin/tests/system/dyndb/Makefile.in
new file mode 100644
index 0000000..e975337
--- /dev/null
+++ b/bin/tests/system/dyndb/Makefile.in
@@ -0,0 +1,21 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+SUBDIRS = driver
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/bin/tests/system/dyndb/clean.sh b/bin/tests/system/dyndb/clean.sh
new file mode 100644
index 0000000..6344947
--- /dev/null
+++ b/bin/tests/system/dyndb/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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.*
diff --git a/bin/tests/system/dyndb/driver/AUTHORS b/bin/tests/system/dyndb/driver/AUTHORS
new file mode 100644
index 0000000..acc109c
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/AUTHORS
@@ -0,0 +1,8 @@
+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/COPYING b/bin/tests/system/dyndb/driver/COPYING
new file mode 100644
index 0000000..e383928
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/COPYING
@@ -0,0 +1,19 @@
+Copyright (C) 1999-2014 Internet Systems Consortium, Inc. ("ISC")
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+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.
diff --git a/bin/tests/system/dyndb/driver/Makefile.in b/bin/tests/system/dyndb/driver/Makefile.in
new file mode 100644
index 0000000..e62b247
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/Makefile.in
@@ -0,0 +1,57 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@
+CWARNINGS =
+
+DNSLIBS = ../../../../../lib/dns/libdns.@A@
+ISCLIBS = ../../../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+
+SRCS = db.c driver.c instance.c \
+ lock.c log.c syncptr.c zone.c
+
+OBJS = db.@O@ driver.@O@ instance.@O@ \
+ lock.@O@ log.@O@ syncptr.@O@ zone.@O@
+
+SO_TARGETS = lib/sample.@SO@
+TARGETS = @SO_TARGETS@
+SO_STRIP = @SO_STRIP@
+
+@BIND9_MAKE_RULES@
+
+CFLAGS = @CFLAGS@ @SO_CFLAGS@
+SO_LDFLAGS = @LDFLAGS@ @SO_LDFLAGS@
+
+lib/sample.@SO@: sample.@SO@
+ $(SHELL) ${top_srcdir}/mkinstalldirs `pwd`/lib
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL} sample.@SO@ `pwd`/lib
+
+sample.@SO@: ${OBJS} ${DNSDEPLIBS} ${ISCDEPLIBS}
+ CLEANED=`echo "${DNSLIBS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS}" | ${SO_STRIP}`; \
+ ${LIBTOOL_MODE_LINK} @SO_LD@ ${SO_LDFLAGS} -o $@ ${OBJS} \
+ $${CLEANED}
+
+clean distclean::
+ rm -f ${OBJS} sample.so lib/sample.so
diff --git a/bin/tests/system/dyndb/driver/README b/bin/tests/system/dyndb/driver/README
new file mode 100644
index 0000000..9aac0a6
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/README
@@ -0,0 +1,65 @@
+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..02aa6ab
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/db.c
@@ -0,0 +1,822 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+#include <config.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 "db.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, NULL);
+ *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) {
+ sampledb_t *sampledb = (sampledb_t *)(*dbp);
+ unsigned int refs;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ isc_refcount_decrement(&sampledb->refs, &refs);
+ if (refs == 0)
+ free_sampledb(sampledb);
+ *dbp = NULL;
+}
+
+/*
+ * 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
+serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file) {
+ sampledb_t *sampledb = (sampledb_t *) db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_serialize(sampledb->rbtdb, version, file));
+}
+
+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, 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, 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, dns_name_t *name, 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_findzonecut(sampledb->rbtdb, name, options,
+ now, nodep, foundname, 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,
+ 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,
+ 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) {
+ sampledb_t *sampledb = (sampledb_t *) db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_nodecount(sampledb->rbtdb));
+}
+
+/*
+ * 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, 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 void
+rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) {
+ sampledb_t *sampledb = (sampledb_t *) db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_rpz_attach(sampledb->rbtdb, rpzs, rpz_num);
+}
+
+static isc_result_t
+rpz_ready(dns_db_t *db) {
+ sampledb_t *sampledb = (sampledb_t *) db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_rpz_ready(sampledb->rbtdb));
+}
+
+static isc_result_t
+findnodeext(dns_db_t *db, 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, 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,
+ serialize,
+ 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,
+ rpz_attach,
+ rpz_ready,
+ findnodeext,
+ findext,
+ setcachestats,
+ hashsize,
+ NULL,
+ NULL,
+};
+
+/* 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, dns_name_t *name,
+ dns_name_t *origin, 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, dns_name_t *name,
+ 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, 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, 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);
+ isc_ondestroy_init(&sampledb->common.ondest);
+
+ 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));
+
+ CHECK(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..80693a7
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/db.h
@@ -0,0 +1,15 @@
+/**
+ * Database API implementation.
+ *
+ * Copyright (C) 2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef DB_H_
+#define DB_H_
+
+isc_result_t
+create_db(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp);
+
+#endif /* DB_H_ */
diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c
new file mode 100644
index 0000000..bef6acb
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/driver.c
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#include <config.h>
+
+#include <isc/commandline.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/lib.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dyndb.h>
+#include <dns/lib.h>
+#include <dns/types.h>
+
+#include "db.h"
+#include "log.h"
+#include "instance.h"
+#include "util.h"
+
+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);
+
+ /*
+ * Depending on how dlopen() was called, we may not have
+ * access to named's global namespace, in which case we need
+ * to initialize libisc/libdns
+ */
+ if (dctx->refvar != &isc_bind9) {
+ isc_lib_register();
+ isc_log_setcontext(dctx->lctx);
+ dns_log_setcontext(dctx->lctx);
+ }
+
+ isc_hash_set_initializer(dctx->hashinit);
+
+ s = isc_mem_strdup(mctx, parameters);
+ if (s == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ log_write(ISC_LOG_DEBUG(9),
+ "loading params for dyndb '%s' from %s:%lu",
+ name, file, line);
+
+ /* Finally, create the instance. */
+ CHECK(new_sample_instance(mctx, name, argc, argv, dctx, &sample_inst));
+
+ /*
+ * This is an example so we create and load zones
+ * right now. This step can be arbitrarily postponed.
+ */
+ CHECK(load_sample_instance_zones(sample_inst));
+
+ *instp = sample_inst;
+
+ cleanup:
+ if (s != NULL)
+ 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 betwen 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..f1bd84e
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/instance.c
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2008-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#include <config.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 "util.h"
+#include "instance.h"
+#include "log.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;
+ }
+ CHECK(dns_name_fromstring2(z1, argv[0], dns_rootname, 0, mctx));
+ CHECK(dns_name_fromstring2(z2, argv[1], dns_rootname, 0, mctx));
+
+ 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);
+ if (inst->db_name == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ inst->zone1_name = dns_fixedname_initname(&inst->zone1_fn);
+ inst->zone2_name = dns_fixedname_initname(&inst->zone2_fn);
+
+ CHECK(parse_params(mctx, argc, argv,
+ inst->zone1_name, inst->zone2_name));
+
+ 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. */
+ CHECK(dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp));
+
+ *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;
+
+ CHECK(create_zone(inst, inst->zone1_name, &inst->zone1));
+ CHECK(activate_zone(inst, inst->zone1));
+
+ CHECK(create_zone(inst, inst->zone2_name, &inst->zone2));
+ CHECK(activate_zone(inst, inst->zone2));
+
+cleanup:
+ return (result);
+}
+
+void
+destroy_sample_instance(sample_instance_t **instp) {
+ sample_instance_t *inst;
+ REQUIRE(instp != NULL);
+
+ inst = *instp;
+ 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);
+
+ *instp = NULL;
+}
diff --git a/bin/tests/system/dyndb/driver/instance.h b/bin/tests/system/dyndb/driver/instance.h
new file mode 100644
index 0000000..6658cbb
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/instance.h
@@ -0,0 +1,49 @@
+/**
+ * Driver instance object.
+ *
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef _LD_INSTANCE_H_
+#define _LD_INSTANCE_H_
+
+#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);
+
+#endif /* !_LD_INSTANCE_H_ */
diff --git a/bin/tests/system/dyndb/driver/lock.c b/bin/tests/system/dyndb/driver/lock.c
new file mode 100644
index 0000000..c97c490
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/lock.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#include <config.h>
+
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include "lock.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..35c9c84
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/lock.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef LOCK_H_
+#define LOCK_H_
+
+#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);
+
+#endif /* LOCK_H_ */
diff --git a/bin/tests/system/dyndb/driver/log.c b/bin/tests/system/dyndb/driver/log.c
new file mode 100644
index 0000000..1098042
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/log.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <dns/log.h>
+
+#include "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..27b38c8
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/log.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009--2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef _LD_LOG_H_
+#define _LD_LOG_H_
+
+#include <isc/error.h>
+#include <dns/log.h>
+#include <dns/result.h>
+
+#define fatal_error(...) \
+ isc_error_fatal(__FILE__, __LINE__, __VA_ARGS__)
+
+#define log_error_r(fmt, ...) \
+ log_error(fmt ": %s", ##__VA_ARGS__, dns_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);
+
+#endif /* !_LD_LOG_H_ */
diff --git a/bin/tests/system/dyndb/driver/syncptr.c b/bin/tests/system/dyndb/driver/syncptr.c
new file mode 100644
index 0000000..e184fd2
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/syncptr.c
@@ -0,0 +1,266 @@
+/*
+ * Automatic A/AAAA/PTR record synchronization.
+ *
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#include <config.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 "syncptr.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);
+
+ CHECK(dns_zone_getdb(pevent->zone, &db));
+ CHECK(dns_db_newversion(db, &version));
+ CHECK(dns_diff_apply(&pevent->diff, db, version));
+
+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
+ */
+ CHECK(dns_byaddr_createptrname2(&isc_ip, 0, name));
+
+ /* 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)
+ goto cleanup;
+
+ /* Make sure that the zone is managed by this driver. */
+ if (*zone != inst->zone1 && *zone != inst->zone2) {
+ dns_zone_detach(zone);
+ 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));
+ if (pevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ 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 synchonization 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);
+ CHECK(dns_name_copy(name, dns_fixedname_name(&pevent->ptr_target_name),
+ NULL));
+ dns_name_clone(dns_fixedname_name(&pevent->ptr_target_name),
+ &ptr_struct.ptr);
+ dns_diff_init(inst->mctx, &pevent->diff);
+ CHECK(dns_rdata_fromstruct(&ptr_rdata, dns_rdataclass_in,
+ dns_rdatatype_ptr, &ptr_struct, &pevent->b));
+
+ /* Create diff */
+ CHECK(dns_difftuple_create(mctx, op, dns_fixedname_name(&ptr_name),
+ ttl, &ptr_rdata, &tp));
+ 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..2f9b3a6
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/syncptr.h
@@ -0,0 +1,15 @@
+/*
+ * Sync PTR records
+ *
+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef SYNCPTR_H_
+#define SYNCPTR_H_
+
+#include <dns/diff.h>
+isc_result_t
+syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_diffop_t op);
+
+#endif /* SYNCPTR_H_ */
diff --git a/bin/tests/system/dyndb/driver/util.h b/bin/tests/system/dyndb/driver/util.h
new file mode 100644
index 0000000..2a00fe3
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/util.h
@@ -0,0 +1,57 @@
+/*
+ * Memory allocation and error handling utilities.
+ *
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef _LD_UTIL_H_
+#define _LD_UTIL_H_
+
+#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)))
+
+#endif /* !_LD_UTIL_H_ */
diff --git a/bin/tests/system/dyndb/driver/zone.c b/bin/tests/system/dyndb/driver/zone.c
new file mode 100644
index 0000000..47e4c15
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/zone.c
@@ -0,0 +1,194 @@
+/*
+ * Zone management.
+ *
+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/util.h>
+
+#include <dns/dyndb.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include "util.h"
+#include "instance.h"
+#include "lock.h"
+#include "log.h"
+#include "zone.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;
+
+ CHECK(dns_zone_create(&raw, inst->mctx));
+ CHECK(dns_zone_setorigin(raw, name));
+ dns_zone_setclass(raw, dns_rdataclass_in);
+ dns_zone_settype(raw, dns_zone_master);
+ CHECK(dns_zone_setdbtype(raw, 1, zone_argv));
+ CHECK(dns_zonemgr_managezone(inst->zmgr, raw));
+
+ /* This is completely insecure - use some sensible values instead! */
+ CHECK(dns_acl_any(inst->mctx, &acl_any));
+ 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);
+ CHECK(dns_view_addzone(inst->view, zone));
+
+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);
+ 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);
+
+ CHECK(dns_zone_getserial2(zone, &serial));
+ 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",
+ dns_result_totext(result));
+ goto cleanup;
+ }
+
+ CHECK(load_zone(raw));
+
+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..a862691
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/zone.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license
+ */
+
+#ifndef ZONE_H_
+#define ZONE_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);
+
+#endif /* ZONE_H_ */
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..dde4a4d
--- /dev/null
+++ b/bin/tests/system/dyndb/ns1/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+dyndb sample "../driver/lib/sample.so" { ipv4.example.nil. in-addr.arpa. };
+dyndb sample2 "../driver/lib/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..76af465
--- /dev/null
+++ b/bin/tests/system/dyndb/prereq.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$FEATURETEST --have-dlopen || {
+ echo_i "dlopen() not supported - 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..7e60631
--- /dev/null
+++ b/bin/tests/system/dyndb/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..6b10357
--- /dev/null
+++ b/bin/tests/system/dyndb/tests.sh
@@ -0,0 +1,153 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+DIGOPTS="@10.53.0.1 -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+newtest() {
+ n=`expr $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
+ }
+
+ out=`$DIG $DIGOPTS +noall +answer -x $ip`
+ echo $out > added.ptr.out.$n
+ lines=`echo "$out" | grep "$host" | wc -l`
+ [ $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
+ }
+
+ out=`$DIG $DIGOPTS +noall +answer -x $ip`
+ echo $out > deleted.ptr.out.$n
+ lines=`echo "$out" | grep "$host" | wc -l`
+ [ $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=`expr $status + $ret`
+
+test_add test2.ipv4.example.nil. A "10.53.0.11" || ret=1
+status=`expr $status + $ret`
+
+test_add test3.ipv4.example.nil. A "10.53.0.12" || ret=1
+status=`expr $status + $ret`
+
+test_add test4.ipv6.example.nil. AAAA "2001:db8::1" || ret=1
+status=`expr $status + $ret`
+
+test_del test1.ipv4.example.nil. A || ret=1
+status=`expr $status + $ret`
+
+test_del test2.ipv4.example.nil. A || ret=1
+status=`expr $status + $ret`
+
+test_del test3.ipv4.example.nil. A || ret=1
+status=`expr $status + $ret`
+
+test_del test4.ipv6.example.nil. AAAA || ret=1
+status=`expr $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=`expr $status + $ret`
+
+echo_i "checking dyndb still works after reload"
+$RNDCCMD 10.53.0.1 reload 2>&1 | sed 's/^/ns1 /' | cat_i
+
+test_add test5.ipv4.example.nil. A "10.53.0.10" || ret=1
+status=`expr $status + $ret`
+
+test_add test6.ipv6.example.nil. AAAA "2001:db8::1" || ret=1
+status=`expr $status + $ret`
+
+test_del test5.ipv4.example.nil. A || ret=1
+status=`expr $status + $ret`
+
+test_del test6.ipv6.example.nil. AAAA || ret=1
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/ecdsa/clean.sh b/bin/tests/system/ecdsa/clean.sh
new file mode 100644
index 0000000..3779676
--- /dev/null
+++ b/bin/tests/system/ecdsa/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */dsset-* */*.signed */trusted.conf
+rm -f ns1/root.db
+rm -f ns1/signer.err
+rm -f dig.out*
+rm -f */named.run
+rm -f */named.memstats
+rm -f ns*/named.lock
diff --git a/bin/tests/system/ecdsa/ns1/named.conf b/bin/tests/system/ecdsa/ns1/named.conf
new file mode 100644
index 0000000..715f7d3
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns1/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..c0d7a83
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns1/root.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..176efcc
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns1/sign.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+key1=`$KEYGEN -q -r $RANDFILE -a ECDSAP256SHA256 -n zone $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a ECDSAP384SHA384 -n zone -f KSK $zone`
+$DSFROMKEY -a sha-384 $key2.key > dsset-384
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $key1 > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
diff --git a/bin/tests/system/ecdsa/ns2/named.conf b/bin/tests/system/ecdsa/ns2/named.conf
new file mode 100644
index 0000000..50621a5
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns2/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 yes;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/ecdsa/prereq.sh b/bin/tests/system/ecdsa/prereq.sh
new file mode 100644
index 0000000..f01828f
--- /dev/null
+++ b/bin/tests/system/ecdsa/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh ecdsa
diff --git a/bin/tests/system/ecdsa/setup.sh b/bin/tests/system/ecdsa/setup.sh
new file mode 100644
index 0000000..96b421c
--- /dev/null
+++ b/bin/tests/system/ecdsa/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..c4ceefc
--- /dev/null
+++ b/bin/tests/system/ecdsa/tests.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noau +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+# Check the example. domain
+
+echo "I:checking that positive validation works ($n)"
+ret=0
+$DIG $DIGOPTS . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS . @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
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/eddsa/clean.sh b/bin/tests/system/eddsa/clean.sh
new file mode 100644
index 0000000..0bcd0ac
--- /dev/null
+++ b/bin/tests/system/eddsa/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */dsset-* */*.signed */trusted.conf
+rm -f ns1/root.db
+rm -f ns*/signer.err
+rm -f dig.out*
+rm -f */named.run
+rm -f */named.memstats
+rm -f ns*/named.lock
diff --git a/bin/tests/system/eddsa/ns1/named.conf b/bin/tests/system/eddsa/ns1/named.conf
new file mode 100644
index 0000000..715f7d3
--- /dev/null
+++ b/bin/tests/system/eddsa/ns1/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..c0d7a83
--- /dev/null
+++ b/bin/tests/system/eddsa/ns1/root.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ee0b309
--- /dev/null
+++ b/bin/tests/system/eddsa/ns1/sign.sh
@@ -0,0 +1,32 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+key1=`$KEYGEN -q -r $RANDFILE -a ED25519 -n zone $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a ED25519 -n zone -f KSK $zone`
+#key2=`$KEYGEN -q -r $RANDFILE -a ED448 -n zone -f KSK $zone`
+$DSFROMKEY -a sha-256 $key2.key > dsset-256
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $key1 > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+
+cd ../ns2 && $SHELL sign.sh
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 b/bin/tests/system/eddsa/ns2/example.com.db
new file mode 100644
index 0000000..8a2b6cd
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/example.com.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+;
+$INCLUDE Kexample.com.+015+03613.key
+$INCLUDE Kexample.com.+015+35217.key
diff --git a/bin/tests/system/eddsa/ns2/named.conf b/bin/tests/system/eddsa/ns2/named.conf
new file mode 100644
index 0000000..50621a5
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 yes;
+ notify yes;
+ dnssec-enable 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..76f5e5d
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/sign.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.com.
+zonefile=example.com.db
+starttime=20150729220000
+endtime=20150819220000
+
+for i in Xexample.com.+015+03613.key Xexample.com.+015+03613.private \
+ Xexample.com.+015+35217.key Xexample.com.+015+35217.private
+do
+ cp $i `echo $i | sed s/X/K/`
+done
+
+$SIGNER -P -z -s $starttime -e $endtime -r $RANDFILE -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..648f97d
--- /dev/null
+++ b/bin/tests/system/eddsa/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh eddsa
diff --git a/bin/tests/system/eddsa/setup.sh b/bin/tests/system/eddsa/setup.sh
new file mode 100644
index 0000000..c48b526
--- /dev/null
+++ b/bin/tests/system/eddsa/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 800 $RANDFILE
+
+cd ns1 && $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..361380c
--- /dev/null
+++ b/bin/tests/system/eddsa/tests.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noau +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+# Check the example. domain
+
+echo "I:checking that positive validation works ($n)"
+ret=0
+$DIG $DIGOPTS . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS . @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
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check test vectors (RFC 8080 + errata)
+
+echo "I:checking that 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
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/ednscompliance/clean.sh b/bin/tests/system/ednscompliance/clean.sh
new file mode 100644
index 0000000..037fccf
--- /dev/null
+++ b/bin/tests/system/ednscompliance/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out*
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/named.run
+rm -f ns*/named.memstats
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..b24ceaa
--- /dev/null
+++ b/bin/tests/system/ednscompliance/ns1/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {
+ type master;
+ 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..93306db
--- /dev/null
+++ b/bin/tests/system/ednscompliance/ns1/root.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7e60631
--- /dev/null
+++ b/bin/tests/system/ednscompliance/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..acede9d
--- /dev/null
+++ b/bin/tests/system/ednscompliance/tests.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+norec -p ${PORT}"
+
+status=0
+n=0
+zone=.
+
+n=`expr $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
+grep "EDNS: version: 100," dig.out$n > /dev/null || { ret=1; reason="version"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+grep "; OPT=100" dig.out$n > /dev/null || { ret=1; reason="option"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+grep "MBZ: 0x0080," dig.out$n > /dev/null || { ret=1; reason="flags"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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; reaons="soa"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Unknown EDNS option ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +ednsopt=100 soa $zone > dig.out$n
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "Unknown EDNS flag ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +ednsflags=0x80 soa $zone > dig.out$n
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+n=`expr $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
+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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/emptyzones/clean.sh b/bin/tests/system/emptyzones/clean.sh
new file mode 100644
index 0000000..7826e73
--- /dev/null
+++ b/bin/tests/system/emptyzones/clean.sh
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.run
+rm -f ns*/named.memstats
+rm -f dig.out.test*
diff --git a/bin/tests/system/emptyzones/ns1/empty.db b/bin/tests/system/emptyzones/ns1/empty.db
new file mode 100644
index 0000000..fdd5ef9
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/empty.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..765ce2c
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/named1.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ algorithm hmac-sha256;
+ secret "1234abcd8765";
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.1 dscp 1;
+ notify-source 10.53.0.1 dscp 2;
+ transfer-source 10.53.0.1 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable 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; };
+};
+
+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..6af2697
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/named2.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ algorithm hmac-sha256;
+ secret "1234abcd8765";
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.1 dscp 1;
+ notify-source 10.53.0.1 dscp 2;
+ transfer-source 10.53.0.1 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable 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; };
+ allow-transfer { none; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "1.10.in-addr.arpa" {
+ type master; 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..465c14f
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/rfc1918.zones
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "10.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "16.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "17.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "18.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "19.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "20.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "21.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "22.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "23.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "24.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "25.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "26.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "27.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "28.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "29.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "30.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "31.172.IN-ADDR.ARPA" { type master; file "empty.db"; };
+zone "168.192.IN-ADDR.ARPA" { type master; 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..64769b9
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e842d2c
--- /dev/null
+++ b/bin/tests/system/emptyzones/setup.sh
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/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..5872479
--- /dev/null
+++ b/bin/tests/system/emptyzones/tests.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "check that switching to automatic empty zones works ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 reload > /dev/null || ret=1
+sleep 5
+
+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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c
new file mode 100644
index 0000000..9612450
--- /dev/null
+++ b/bin/tests/system/feature-test.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/print.h>
+#include <isc/util.h>
+#include <isc/net.h>
+#include <dns/edns.h>
+
+#ifdef WIN32
+#include <Winsock2.h>
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#ifdef HOST_NAME_MAX
+#define MAXHOSTNAMELEN HOST_NAME_MAX
+#else
+#define MAXHOSTNAMELEN 256
+#endif
+#endif
+
+static void
+usage() {
+ fprintf(stderr, "usage: feature-test <arg>\n");
+ fprintf(stderr, "args:\n");
+ fprintf(stderr, " --edns-version\n");
+ fprintf(stderr, " --enable-filter-aaaa\n");
+ fprintf(stderr, " --gethostname\n");
+ fprintf(stderr, " --gssapi\n");
+ fprintf(stderr, " --have-dlopen\n");
+ fprintf(stderr, " --have-geoip\n");
+ fprintf(stderr, " --have-libxml2\n");
+ fprintf(stderr, " --ipv6only=no\n");
+ fprintf(stderr, " --rpz-nsdname\n");
+ fprintf(stderr, " --rpz-nsip\n");
+ fprintf(stderr, " --with-idn\n");
+ fprintf(stderr, " --with-lmdb\n");
+}
+
+int
+main(int argc, char **argv) {
+ if (argc != 2) {
+ usage();
+ return (1);
+ }
+
+ if (strcmp(argv[1], "--enable-filter-aaaa") == 0) {
+#ifdef ALLOW_FILTER_AAAA
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--edns-version") == 0) {
+#ifdef DNS_EDNS_VERSION
+ printf("%d\n", DNS_EDNS_VERSION);
+#else
+ printf("0\n");
+#endif
+ return (0);
+ }
+
+ if (strcmp(argv[1], "--gethostname") == 0) {
+ char hostname[MAXHOSTNAMELEN];
+ int n;
+#ifdef WIN32
+ /* From lwres InitSocket() */
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD(2, 0);
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if (err != 0) {
+ fprintf(stderr, "WSAStartup() failed: %d\n", err);
+ exit(1);
+ }
+#endif
+
+ n = gethostname(hostname, sizeof(hostname));
+ if (n == -1) {
+ perror("gethostname");
+ return(1);
+ }
+ fprintf(stdout, "%s\n", hostname);
+#ifdef WIN32
+ WSACleanup();
+#endif
+ return (0);
+ }
+
+ if (strcmp(argv[1], "--gssapi") == 0) {
+#if defined(GSSAPI)
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--have-dlopen") == 0) {
+#if defined(HAVE_DLOPEN) && defined(ISC_DLZ_DLOPEN)
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--have-geoip") == 0) {
+#ifdef HAVE_GEOIP
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--have-libxml2") == 0) {
+#ifdef HAVE_LIBXML2
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--rpz-nsip") == 0) {
+#ifdef ENABLE_RPZ_NSIP
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--rpz-nsdname") == 0) {
+#ifdef ENABLE_RPZ_NSDNAME
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--with-idn") == 0) {
+#ifdef WITH_LIBIDN2
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--with-lmdb") == 0) {
+#ifdef HAVE_LMDB
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--ipv6only=no") == 0) {
+#ifdef WIN32
+ return (0);
+#elif defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
+ int s;
+ int n = -1;
+ int v6only = -1;
+ ISC_SOCKADDR_LEN_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
+ return (1);
+#endif
+ }
+
+ 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..4b14a92
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ans4/ans.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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) {
+ $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..9296105
--- /dev/null
+++ b/bin/tests/system/fetchlimit/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf */named.memstats */ans.run */named.recursing */named.run
+rm -f dig.out*
+rm -f ans4/norespond
+rm -f ns3/named.stats ns3/named_dump.db
+rm -f burst.input.*
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..eabfe0c
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns1/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example.info." {
+ type master;
+ 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..dab5cea
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..40929b3
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns2/example.db
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..1892756
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns2/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "example" {
+ type master;
+ 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..4f737fc
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named.args
@@ -0,0 +1,2 @@
+# Don't specify '-T clienttest' as it consumes lots of memory with this test
+-D ns3 -X named.lock -m record,size,mctx -c named.conf -d 99 -g -U 4
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..b470f46
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named1.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ notify yes;
+ fetches-per-server 400;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "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..001a958
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named2.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ fetches-per-zone 40;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "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..0244a9a
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named3.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ recursive-clients 400;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "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..418ea96
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/fetchlimit/prereq.sh
new file mode 100644
index 0000000..de147a4
--- /dev/null
+++ b/bin/tests/system/fetchlimit/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/fetchlimit/setup.sh b/bin/tests/system/fetchlimit/setup.sh
new file mode 100644
index 0000000..2c83ad1
--- /dev/null
+++ b/bin/tests/system/fetchlimit/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/fetchlimit/tests.sh b/bin/tests/system/fetchlimit/tests.sh
new file mode 100644
index 0000000..9250c46
--- /dev/null
+++ b/bin/tests/system/fetchlimit/tests.sh
@@ -0,0 +1,186 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGCMD="$DIG @10.53.0.3 -p ${PORT} +tries=1 +time=1"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -s 10.53.0.3 -c ../common/rndc.conf"
+
+burst() {
+ num=${3:-20}
+ rm -f burst.input.$$
+ while [ $num -gt 0 ]; do
+ num=`expr $num - 1`
+ echo "${num}${1}${2}.lamesub.example A" >> burst.input.$$
+ done
+ $PERL ../ditch.pl -p ${PORT} -s 10.53.0.3 burst.input.$$
+ rm -f burst.input.$$
+}
+
+stat() {
+ clients=`$RNDCCMD status | grep "recursive clients" |
+ sed 's;.*: \([^/][^/]*\)/.*;\1;'`
+ echo_i "clients: $clients"
+ [ "$clients" = "" ] && return 1
+ [ "$clients" -le $1 ]
+}
+
+status=0
+
+echo_i "checking recursing clients are dropped at the per-server limit"
+ret=0
+# make the server lame and restart
+$RNDCCMD 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 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
+ stat 200 || ret=1
+ [ $ret -eq 1 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "dumping ADB data"
+$RNDCCMD 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=$5
+[ ${5:-200} -lt 200 ] || ret=1
+
+echo_i "checking servfail statistics"
+ret=0
+rm -f ns3/named.stats
+$RNDCCMD 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=`expr $status + $ret`
+
+echo_i "checking lame server recovery"
+ret=0
+rm -f ans4/norespond
+for try in 1 2 3 4 5; do
+ burst b $try
+ stat 200 || ret=1
+ [ $ret -eq 1 ] && break
+ sleep 1
+done
+
+echo_i "dumping ADB data"
+$RNDCCMD 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
+[ ${5:-${quota}} -lt $quota ] || ret=1
+quota=$5
+
+for try in 1 2 3 4 5 6 7 8 9 10; do
+ burst c $try
+ stat 20 || ret=1
+ [ $ret -eq 1 ] && break
+ sleep 1
+done
+
+echo_i "dumping ADB data"
+$RNDCCMD 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
+[ ${5:-${quota}} -gt $quota ] || ret=1
+quota=$5
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+copy_setports ns3/named2.conf.in ns3/named.conf
+$RNDCCMD reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+
+echo_i "checking lame server clients are dropped at the per-domain limit"
+ret=0
+fail=0
+success=0
+touch ans4/norespond
+for try in 1 2 3 4 5; do
+ burst b $try 300
+ $DIGCMD a ${try}.example > dig.out.ns3.$try
+ grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
+ success=`expr $success + 1`
+ grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
+ fail=`expr $fail + 1`
+ stat 50 || ret=1
+ [ $ret -eq 1 ] && break
+ $RNDCCMD 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=`expr $status + $ret`
+
+echo_i "checking drop statistics"
+rm -f ns3/named.stats
+$RNDCCMD 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=`expr $status + $ret`
+
+copy_setports ns3/named3.conf.in ns3/named.conf
+$RNDCCMD reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+
+echo_i "checking lame server clients are dropped at the soft limit"
+ret=0
+fail=0
+exceeded=0
+success=0
+touch ans4/norespond
+for try in 1 2 3 4 5; do
+ burst b $try 400
+ $DIG @10.53.0.3 -p ${PORT} a ${try}.example > dig.out.ns3.$try
+ stat 360 || exceeded=`expr $exceeded + 1`
+ grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
+ success=`expr $success + 1`
+ grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
+ fail=`expr $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 360 on $exceeded trials (expected 0)"
+[ "$exceeded" -eq 0 ] || { echo_i "failed"; ret=1; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/filter-aaaa/clean.sh b/bin/tests/system/filter-aaaa/clean.sh
new file mode 100644
index 0000000..7373275
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
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..9a23fd8
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad1.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..798f4fd
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad2.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ /*
+ * 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..3c068bb
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad3.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa-on-v4 no;
+};
+
+view myview {
+ 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..5744c8b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad4.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa { any; };
+};
+
+view myview {
+ filter-aaaa-on-v4 no;
+};
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..39f9acc
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad5.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa { none; };
+};
+
+view myview {
+ filter-aaaa-on-v4 yes;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad6.conf b/bin/tests/system/filter-aaaa/conf/bad6.conf
new file mode 100644
index 0000000..e92bb1e
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad6.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa-on-v4 yes;
+};
+
+view myview {
+ filter-aaaa { none; };
+};
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..2a93ef6
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good1.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..916af8e
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good2.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..b3f8de4
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good3.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..d789f30
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good4.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..95baae5
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good5.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa-on-v4 yes;
+};
+
+view myview {
+ filter-aaaa { 1.0.0.0/8; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good6.conf b/bin/tests/system/filter-aaaa/conf/good6.conf
new file mode 100644
index 0000000..9e78367
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good6.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa { 1.0.0.0/8; };
+};
+
+view myview {
+ filter-aaaa-on-v4 yes;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good7.conf b/bin/tests/system/filter-aaaa/conf/good7.conf
new file mode 100644
index 0000000..2531de9
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good7.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+};
+
+view myview {
+ filter-aaaa { 1.0.0.0/8; };
+ filter-aaaa-on-v4 yes;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good8.conf b/bin/tests/system/filter-aaaa/conf/good8.conf
new file mode 100644
index 0000000..f28fdd9
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good8.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ filter-aaaa-on-v4 no;
+};
+
+view myview {
+ filter-aaaa { 1.0.0.0/8; };
+ filter-aaaa-on-v4 yes;
+};
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..b49fe6b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/named1.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { 10.53.0.1; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." { type master; file "root.db"; };
+zone "signed" { type master; file "signed.db.signed"; };
+zone "unsigned" { type master; 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..46e89b4
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/named2.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+ filter-aaaa-on-v6 yes;
+ filter-aaaa { fd92:7065:b8e:ffff::1; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type master; file "root.db"; };
+zone "signed" { type master; file "signed.db.signed"; };
+zone "unsigned" { type master; 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..6a4f832
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/root.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..f755581
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/sign.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=filter-aaaa
+
+dlvsets=
+
+zone=signed.
+infile=signed.db.in
+zonefile=signed.db.signed
+outfile=signed.db.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $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..31dda57
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/signed.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/signed.db.presigned b/bin/tests/system/filter-aaaa/ns1/signed.db.presigned
new file mode 100644
index 0000000..1c7b4ae
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/signed.db.presigned
@@ -0,0 +1,125 @@
+; File written on Mon Oct 16 09:16:28 2017
+; dnssec_signzone version 9.11.2
+signed. 120 IN SOA ns.signed. hostmaster.ns.signed. (
+ 1 ; serial
+ 3600 ; refresh (1 hour)
+ 1200 ; retry (20 minutes)
+ 604800 ; expire (1 week)
+ 60 ; minimum (1 minute)
+ )
+ 120 RRSIG SOA 3 1 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BJDbUrXS4UzBrTeNUMA0sSGYd+h9M5d8qzsE
+ q7RJyDtUNJIwP5vAnSQ= )
+ 120 NS ns.signed.
+ 120 RRSIG NS 3 1 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BGoYuOkkcTAYnym27q2BgqkjUgP/0/Tip1yc
+ txRS1D0CipTUZhCNrXc= )
+ 120 MX 10 mx.signed.
+ 120 RRSIG MX 3 1 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BOUPCSEEJ8dZ0oWeiYEvGIonjagvM1OS+mEY
+ i5VUmysn7kArWqeFERs= )
+ 60 NSEC a-only.signed. NS SOA MX RRSIG NSEC DNSKEY
+ 60 RRSIG NSEC 3 1 60 (
+ 20820519023008 20140501011600 17876 signed.
+ BBzvCsFw4EgfrIsFOu5IjP2gncm8dntwHaMD
+ IeJ6g6s7IOwFT5nyrOU= )
+ 120 DNSKEY 256 3 3 (
+ BPXo3mJOeCCuorn7Hc7bxR3QDHrJvq9gUpPS
+ s8QYF3eiSpB97c8Br7fFzFYHQCJWWnCtpt1E
+ h7SveJSl1ASNl9W2KE6hDNXfDX+ixDOtFZ/7
+ PCh/obX36VK86EH+ZBNLxxEy9tHHCGO08zy8
+ 3lWI3E5bk9a1sks2dy6hbQfMmyXWI5QwYS9D
+ j5Vs5yeUQ5e6SPmIqgqpn6VnDtAIfR2My7/r
+ /Jgf73gpZugZmn6wDbzNCyGIvtOJCHAY2OEg
+ ZfACKVdJrXZ42NKcJCgSTd1xY81UyMI9QAMq
+ 64Lx/tENCo1GKBCk/1HMdiO6WKeXCJd1SYzN
+ VM+n4fRzEkmVT9wfyiSmoq6SxjeqrRebDz8G
+ 42d4lsm2/0bmOlle+fva7LwtGOaS+tBqtD8K
+ kexFaixL5iY+LB0Q
+ ) ; ZSK; alg = DSA ; key id = 17876
+ 120 DNSKEY 257 3 3 (
+ BOOhXnn+YV6RQ+jRPdayrnC2cd9x5P77c1/6
+ Ev41qaWl1N7QRDXYh7VDS1UowoPbvQOvgQU0
+ X7+zKWrB8UQcdsUe96IH/wPab1qkJlKanZni
+ uFdB/2sTvQ6yabIC41dItnGeuN9VY1qwCa7T
+ 4QFRVYyDPKgxo7MRLq9YoUN8RTcB6lY1BH9Z
+ QgcHZljAFVgU1Zc/6DZlQeBZyJafwIR+I7Eq
+ Oe+rR44ZeD5JRgI1OwGyw/b1wKUxFhM+4XJi
+ i8mQ1mrvzZ27iQbYP4WEzaskU6P5X+nPrTFi
+ tLEaPugt8Oe7+lHLjpHvHzSOJZ5Radfiqgzg
+ GGOzj1qmLfKLdRmp4VuBQ+1kguiz9D3ev89d
+ pzP7dYHuSdCjc9X0fLmPjU1xD6RyLCDEmUm7
+ eeRP55SiTiQCzJFr
+ ) ; KSK; alg = DSA ; key id = 3746
+ 120 RRSIG DNSKEY 3 1 120 (
+ 20820519023008 20140501011600 3746 signed.
+ BFuLN7ACQrD6/3WaieXRD1JpSXW9s+/xCZ1x
+ 0ihUT1iKNvJS8F4Pafc= )
+ 120 RRSIG DNSKEY 3 1 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BN+8hbh1FGTNqHds0In57dPr5fVRU/P28dZa
+ zIP19bAwTH/ZvgrqUF0= )
+a-only.signed. 120 IN NS 1.0.0.1.signed.
+ 60 NSEC aaaa-only.signed. NS RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 (
+ 20820519023008 20140501011600 17876 signed.
+ BHpGpjMihpoIykHTpK1XmkVn0jqSST3/K6Fx
+ vTaIb24rpkTriaXxChM= )
+aaaa-only.signed. 120 IN AAAA 2001:db8::2
+ 120 RRSIG AAAA 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BOvYax/3CDnEKTtbc6zoP4hYwhMe5SoXZh0w
+ muzBWw9bEH+Bdt1ZEQ4= )
+ 60 NSEC dual.signed. AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 (
+ 20820519023008 20140501011600 17876 signed.
+ BIqxE79TUnT2DUuocTitGhTNGnLs0+3sLJdz
+ 8haJbyH8pig1h7mqimU= )
+dual.signed. 120 IN A 1.0.0.3
+ 120 RRSIG A 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BIGL70eEIGVDW0gcYpEWgCFv4ne14hutQCMh
+ gQ6kcEbl2qszosJA60E= )
+ 120 AAAA 2001:db8::3
+ 120 RRSIG AAAA 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BCmwk+ng/x1O7MhheK8MgAXYFVDDbyiZ76RV
+ iwQrPRm0ThNRtsQU+UY= )
+ 60 NSEC mx.signed. A AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 (
+ 20820519023008 20140501011600 17876 signed.
+ BLlLAIHF4SX/eWMCkUvj0XTFmaOp3xnifqkL
+ nSWOAqtzJ5fwAdbNBdM= )
+ns.signed. 120 IN A 10.53.0.1
+ 120 RRSIG A 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BJ+Wll7VfNEjM4EfLY2rlx74oIwKRg9pjcJO
+ Zxt6GHQIJ2D6EfyMZ00= )
+ 120 AAAA fd92:7065:b8e:ffff::1
+ 120 RRSIG AAAA 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BGT/agHn4qcHzLV2hYcGeLJ6Tz1to9sTB8LI
+ lMwkV/KUu6UO7yvrnYk= )
+ 60 NSEC signed. A AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 (
+ 20820519023008 20140501011600 17876 signed.
+ BNe3XmEGd/xxoh8FN3T3V9G1enCzNQJ7l3G+
+ D3QPrp7mYtPAGMxCLlc= )
+mx.signed. 120 IN A 1.0.0.3
+ 120 RRSIG A 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BMlIQp1acUSUvgzV1CWlM0+cS1bGkFsbS6HQ
+ d0S6TbNV+uNw0S1q0Dk= )
+ 120 AAAA 2001:db8::3
+ 120 RRSIG AAAA 3 2 120 (
+ 20820519023008 20140501011600 17876 signed.
+ BGtSuYQF7sRVT5OdVHPJjm0PERzSp4v+d/DP
+ Vp2UD0vSVSr3Vj2Wi4M= )
+ 60 NSEC ns.signed. A AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 (
+ 20820519023008 20140501011600 17876 signed.
+ BMzQWws37wYfHvLnqgvjd+j5dkzBb2RYhrQk
+ ykM0GnTAR6ZpmgQO6jc= )
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..8b42258
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/unsigned.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..381e86b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns2/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.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..1ca80d1
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns2/named1.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion yes;
+ notify yes;
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { 10.53.0.2; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
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..c08725e
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns2/named2.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion yes;
+ notify yes;
+ filter-aaaa-on-v6 yes;
+ filter-aaaa { fd92:7065:b8e:ffff::2; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
diff --git a/bin/tests/system/filter-aaaa/ns3/hints b/bin/tests/system/filter-aaaa/ns3/hints
new file mode 100644
index 0000000..381e86b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns3/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.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..5f74870
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns3/named1.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { 10.53.0.3; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
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..b1b2367
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns3/named2.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+ filter-aaaa-on-v6 break-dnssec;
+ filter-aaaa { fd92:7065:b8e:ffff::3; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
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..f70c7a6
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/named1.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { 10.53.0.4; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type master; file "root.db"; };
+zone "signed" { type master; file "signed.db.signed"; };
+zone "unsigned" { type master; 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..3d2b29b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/named2.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+ filter-aaaa-on-v6 break-dnssec;
+ filter-aaaa { fd92:7065:b8e:ffff::4; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type master; file "root.db"; };
+zone "signed" { type master; file "signed.db.signed"; };
+zone "unsigned" { type master; 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..1511cc9
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..f755581
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/sign.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=filter-aaaa
+
+dlvsets=
+
+zone=signed.
+infile=signed.db.in
+zonefile=signed.db.signed
+outfile=signed.db.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $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..623b2b9
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/signed.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/signed.db.presigned b/bin/tests/system/filter-aaaa/ns4/signed.db.presigned
new file mode 100644
index 0000000..d96c104
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/signed.db.presigned
@@ -0,0 +1,110 @@
+; File written on Thu May 1 12:22:01 2014
+; dnssec_signzone version 9.8.5-P1
+signed. 120 IN SOA ns.utld. hostmaster.ns.utld. (
+ 1 ; serial
+ 3600 ; refresh (1 hour)
+ 1200 ; retry (20 minutes)
+ 604800 ; expire (1 week)
+ 60 ; minimum (1 minute)
+ )
+ 120 RRSIG SOA 3 1 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BMC1gbQgLgNsb9G6rElwoY6Krb6lV/WFsd/j
+ LO3aVnPXgU/noM1IBjs= )
+ 120 NS ns.utld.
+ 120 RRSIG NS 3 1 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BF9dWcW8GHL4QMp7rbeQgfUQmwEvskiMFqgt
+ GJqepDLkV4WXtw3TRK4= )
+ 120 MX 10 mx.signed.
+ 120 RRSIG MX 3 1 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BJ7bngL8eZ9GrjQvHj0FDOgk2M6+YoW+cIAh
+ ZjGKcK431aUFMS3YSGE= )
+ 60 NSEC a-only.signed. NS SOA MX RRSIG NSEC DNSKEY
+ 60 RRSIG NSEC 3 1 60 20820519033608 (
+ 20140501012201 20366 signed.
+ BHMei3tCaM9eYTPLRn93c6qp9ADL1Hxy+HlN
+ cLTyzzC+UxjUoI9O2VI= )
+ 120 DNSKEY 256 3 3 (
+ BPLuLs4Ylbx3WZ8Ebj6GF+uEfI+J+RcaI1G3
+ TW4JHqVqeBa0gkPjnCDsK9VeUx5CR8i/T18f
+ YrOSojvASvdvG+TLNN9Jx+5A7c/43WzDOe2B
+ jeAlfZSl1Bie/ccGL6W1+lVvlO0OHI54EoKs
+ KxRub2izdouH4867a8dwahBlm14oWYXjqk3+
+ /ubDCPdXdTUvvLnDd9zyDpWYBXisb/3F8R1v
+ IcqyKDfJSTQSofLK+JlD+n7cv7U7pQWQn2qA
+ t/NkGcwF8EAbiQPmcF1BY6NnEMQ5XxNayAF5
+ Eza+i/kf3hLtS12cqW8hWm7aRYZWbzC4uUZL
+ WGK0XfAK2d/vT8ZMZo1oaYEvy3xHwfsFgrFV
+ qebm2ZFEomHpQ4KOSL1UhVI8uegUgnnovHjC
+ eS4q72Fh+LZTD8C4
+ ) ; key id = 20366
+ 120 DNSKEY 257 3 3 (
+ BPLuLs4Ylbx3WZ8Ebj6GF+uEfI+J+RcaI1G3
+ TW4JHqVqeBa0gkPjnCDsK9VeUx5CR8i/T18f
+ YrOSojvASvdvG+TLNN9Jx+5A7c/43WzDOe2B
+ jeAlfZSl1Bie/ccGL6W1+lVvlO0OHI54EoKs
+ KxRub2izdouH4867a8dwahBlm14oWYXjqk3+
+ /ubDCPdXdTUvvLnDd9zyDpWYBXisb/3F8R1v
+ IcqyKDfJSTQSofLK+JlD+n7cv7U7pQWQn2qA
+ t/NkGcwF8EAbiQPmcF1BY6NnEMQ5XxNayAF5
+ Eza+i/kf3hLtS12cqW8hWm7aRYZWbzC4uUZL
+ WGK0XfAK2d/vT8ZMZo1oaYEvy3xHwfsFgrFV
+ qebm2ZFEomHpQ4KOSL1UhVI8uegUgnnovHjC
+ eS4q72Fh+LZTD8C4
+ ) ; key id = 20367
+ 120 RRSIG DNSKEY 3 1 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BBhlUYWd3f00zsSl+UJTxeVZUimQP8iMjf6j
+ Q7uPoI37BUz9NbZhTCg= )
+ 120 RRSIG DNSKEY 3 1 120 20820519033608 (
+ 20140501012201 20367 signed.
+ BHPcogpnebYByfzp/KT53GsIiT3yPk/4atwj
+ NNsPFmVLqb/6yjotWQ0= )
+a-only.signed. 120 IN NS 1.0.0.1.signed.
+ 60 NSEC aaaa-only.signed. NS RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 20820519033608 (
+ 20140501012201 20366 signed.
+ BF1Wt+NtJ1Cuoj1H1D9BCS33ImdgkZeyEKuz
+ 8FT66wAFigkXQ1zNofw= )
+aaaa-only.signed. 120 IN AAAA 2001:db8::2
+ 120 RRSIG AAAA 3 2 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BJFHllFzB91E/NWN1KjgmLuXQgDsGqBOuMuk
+ eNEc0RmToi3wV+TZwt0= )
+ 60 NSEC dual.signed. AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 20820519033608 (
+ 20140501012201 20366 signed.
+ BGfjvmN9LAHU2r9hXKgZRwyL4mZt4N/uBR1y
+ TKOGBOyx6b0hVHmGPnw= )
+dual.signed. 120 IN A 1.0.0.3
+ 120 RRSIG A 3 2 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BEHMwkdjcbK++gvR/a36hSHf+uLwNUpbwKiw
+ PpmEz0be+gavwU0qSmY= )
+ 120 AAAA 2001:db8::3
+ 120 RRSIG AAAA 3 2 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BPKR07CI/4KFd5L7aLMvQifiYDb1EbAP2BIp
+ SgErW40i5qkFz9u588s= )
+ 60 NSEC mx.signed. A AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 20820519033608 (
+ 20140501012201 20366 signed.
+ BGJ0Ei6QbWJva3NwVSE/Bojcodsbu0sSVVLJ
+ QE8F5puTbx6qZ2dqrv4= )
+mx.signed. 120 IN A 1.0.0.3
+ 120 RRSIG A 3 2 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BOyL/Pi5Ih/Xt3b1icWIqoagM7ZKXzPKrmbQ
+ VOZIvn0nmCj/gjShka4= )
+ 120 AAAA 2001:db8::3
+ 120 RRSIG AAAA 3 2 120 20820519033608 (
+ 20140501012201 20366 signed.
+ BL1n80SXkdcDRaFa66xHIrMMFiYUnrM0zoGj
+ ArI7APPAxthUKN+ptAQ= )
+ 60 NSEC signed. A AAAA RRSIG NSEC
+ 60 RRSIG NSEC 3 2 60 20820519033608 (
+ 20140501012201 20366 signed.
+ BG6+zIJRFY4HqyUzPLcErSJibgtxxqfuHGYP
+ kXX9V0coQ3zBC92s2jo= )
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..8f155bb
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/unsigned.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..381e86b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns5/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.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..47b3aff
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns5/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+ };
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { any; };
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
diff --git a/bin/tests/system/filter-aaaa/prereq.sh b/bin/tests/system/filter-aaaa/prereq.sh
new file mode 100644
index 0000000..9c22176
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/prereq.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$FEATURETEST --enable-filter-aaaa || {
+ echo "I:This test requires --enable-filter-aaaa at compile time." >&2
+ exit 255
+}
+exit 0
diff --git a/bin/tests/system/filter-aaaa/setup.sh b/bin/tests/system/filter-aaaa/setup.sh
new file mode 100644
index 0000000..681a91d
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/setup.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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
+
+if $SHELL ../testcrypto.sh -q
+then
+ (cd ns1 && $SHELL -e sign.sh)
+ (cd ns4 && $SHELL -e sign.sh)
+else
+ echo_i "using pre-signed zones"
+ cp -f ns1/signed.db.presigned ns1/signed.db.signed
+ cp -f ns4/signed.db.presigned ns4/signed.db.signed
+fi
diff --git a/bin/tests/system/filter-aaaa/tests.sh b/bin/tests/system/filter-aaaa/tests.sh
new file mode 100644
index 0000000..16a9332
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/tests.sh
@@ -0,0 +1,1390 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+for conf in conf/good*.conf
+do
+ n=`expr $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=`expr $status + $ret`
+done
+
+for conf in conf/bad*.conf
+do
+ n=`expr $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=`expr $status + $ret`
+done
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v4 yes;
+# filter-aaaa { 10.53.0.1; };
+#
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "AUTHORITY: 0," 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=`expr $status + $ret`
+
+n=`expr $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 "AUTHORITY: 0," 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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "AUTHORITY: 0," 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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v4 break-dnssec;
+# filter-aaaa { 10.53.0.4; };
+#
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v4 yes;
+# filter-aaaa { 10.53.0.2; };
+#
+n=`expr $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 ::2 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 ::3 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 ::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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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.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=`expr $status + $ret`
+
+n=`expr $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.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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, 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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v4 break-dnssec;
+# filter-aaaa { 10.53.0.3; };
+#
+n=`expr $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 ::2 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+else
+echo_i "skipped."
+fi
+
+$TESTSOCK6 fd92:7065:b8e:ffff::1 || {
+ echo_i "IPv6 address not configured; skipping IPv6 query tests"
+ echo_i "exit status: $status"
+ exit $status
+}
+
+# Reconfiguring for IPv6 tests
+echo_i "reconfiguring servers"
+copy_setports ns1/named2.conf.in ns1/named.conf
+$RNDCCMD 10.53.0.1 reconfig 2>&1 | sed 's/^/ns1 /' | cat_i
+copy_setports ns2/named2.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig 2>&1 | sed 's/^/ns2 /' | cat_i
+copy_setports ns3/named2.conf.in ns3/named.conf
+$RNDCCMD 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+copy_setports ns4/named2.conf.in ns4/named.conf
+$RNDCCMD 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
+
+# BEGIN IPv6 TESTS
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v6 yes;
+# filter-aaaa { fd92:7065:b8e:ffff::1; };
+#
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v6 break-dnssec;
+# filter-aaaa { fd92:7065:b8e:ffff::4; };
+#
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v6 yes;
+# filter-aaaa { fd92:7065:b8e:ffff::2; };
+#
+n=`expr $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 ::2 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 ::3 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 ::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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v6 yes;
+# filter-aaaa { fd92:7065:b8e:ffff::3; };
+#
+n=`expr $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 ::2 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 "^mx.signed.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/formerr/clean.sh b/bin/tests/system/formerr/clean.sh
new file mode 100644
index 0000000..0bb0e3d
--- /dev/null
+++ b/bin/tests/system/formerr/clean.sh
@@ -0,0 +1,16 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
diff --git a/bin/tests/system/formerr/formerr.pl b/bin/tests/system/formerr/formerr.pl
new file mode 100644
index 0000000..f0937e2
--- /dev/null
+++ b/bin/tests/system/formerr/formerr.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 hexidecimal.
+# 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..b24ceaa
--- /dev/null
+++ b/bin/tests/system/formerr/ns1/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {
+ type master;
+ 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..9515924
--- /dev/null
+++ b/bin/tests/system/formerr/ns1/root.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7e60631
--- /dev/null
+++ b/bin/tests/system/formerr/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..d8b91e8
--- /dev/null
+++ b/bin/tests/system/formerr/tests.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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=`expr $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=`expr $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=`expr $status + 1`;
+fi
+
+echo_i "exit status: $status"
+
+[ $status -eq 0 ] || exit 1
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/clean.sh b/bin/tests/system/forward/clean.sh
new file mode 100644
index 0000000..3052d27
--- /dev/null
+++ b/bin/tests/system/forward/clean.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after forward tests.
+#
+rm -f dig.out.*
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
diff --git a/bin/tests/system/forward/ns1/example.db b/bin/tests/system/forward/ns1/example.db
new file mode 100644
index 0000000..ebbc2ae
--- /dev/null
+++ b/bin/tests/system/forward/ns1/example.db
@@ -0,0 +1,12 @@
+$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..7ce81dd
--- /dev/null
+++ b/bin/tests/system/forward/ns1/named.conf.in
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example1." {
+ type master;
+ file "example.db";
+};
+
+zone "example2." {
+ type master;
+ file "example.db";
+};
+
+zone "example3." {
+ type master;
+ file "example.db";
+};
+
+zone "example4." {
+ type master;
+ file "example.db";
+};
+
+zone "example5." {
+ type master;
+ file "example.db";
+};
+
+/* A forward zone without forwarders. */
+zone "example6" {
+ type forward;
+};
diff --git a/bin/tests/system/forward/ns1/root.db b/bin/tests/system/forward/ns1/root.db
new file mode 100644
index 0000000..7346810
--- /dev/null
+++ b/bin/tests/system/forward/ns1/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/example.db b/bin/tests/system/forward/ns2/example.db
new file mode 100644
index 0000000..3a5f46c
--- /dev/null
+++ b/bin/tests/system/forward/ns2/example.db
@@ -0,0 +1,12 @@
+$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..ff104d4
--- /dev/null
+++ b/bin/tests/system/forward/ns2/named.conf.in
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type master;
+ file "example.db";
+};
+
+zone "example2." {
+ type master;
+ file "example.db";
+};
+
+zone "example3." {
+ type master;
+ file "example.db";
+};
+
+zone "example4." {
+ type master;
+ file "example.db";
+};
+
+zone "grafted." {
+ type master;
+ file "example.db";
+};
+
+zone "1.0.10.in-addr.arpa." {
+ type master;
+ file "example.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..7346810
--- /dev/null
+++ b/bin/tests/system/forward/ns2/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/named.conf.in b/bin/tests/system/forward/ns3/named.conf.in
new file mode 100644
index 0000000..80a4f7e
--- /dev/null
+++ b/bin/tests/system/forward/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+ forwarders { 10.53.0.2; };
+ forward first;
+};
+
+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 { };
+};
diff --git a/bin/tests/system/forward/ns3/root.db b/bin/tests/system/forward/ns3/root.db
new file mode 100644
index 0000000..7346810
--- /dev/null
+++ b/bin/tests/system/forward/ns3/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/named.conf.in b/bin/tests/system/forward/ns4/named.conf.in
new file mode 100644
index 0000000..480530b
--- /dev/null
+++ b/bin/tests/system/forward/ns4/named.conf.in
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+};
+
+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; };
+};
diff --git a/bin/tests/system/forward/ns4/root.db b/bin/tests/system/forward/ns4/root.db
new file mode 100644
index 0000000..7346810
--- /dev/null
+++ b/bin/tests/system/forward/ns4/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/ns5/named.conf.in b/bin/tests/system/forward/ns5/named.conf.in
new file mode 100644
index 0000000..0e65985
--- /dev/null
+++ b/bin/tests/system/forward/ns5/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/forward/ns5/root.db b/bin/tests/system/forward/ns5/root.db
new file mode 100644
index 0000000..7346810
--- /dev/null
+++ b/bin/tests/system/forward/ns5/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/rfc1918-inherited.conf b/bin/tests/system/forward/rfc1918-inherited.conf
new file mode 100644
index 0000000..3c310d0
--- /dev/null
+++ b/bin/tests/system/forward/rfc1918-inherited.conf
@@ -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 http://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..d3febc1
--- /dev/null
+++ b/bin/tests/system/forward/rfc1918-notinherited.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..c63aeb1
--- /dev/null
+++ b/bin/tests/system/forward/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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/forward/tests.sh b/bin/tests/system/forward/tests.sh
new file mode 100644
index 0000000..f23cde1
--- /dev/null
+++ b/bin/tests/system/forward/tests.sh
@@ -0,0 +1,135 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+root=10.53.0.1
+hidden=10.53.0.2
+f1=10.53.0.3
+f2=10.53.0.4
+
+status=0
+
+echo_i "checking that a forward zone overrides global forwarders"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example1. txt @$hidden > dig.out.hidden || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example1. txt @$f1 > dig.out.f1 || ret=1
+digcomp dig.out.hidden dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a forward first zone no forwarders recurses"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example2. txt @$root > dig.out.root || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example2. txt @$f1 > dig.out.f1 || ret=1
+digcomp dig.out.root dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a forward only zone no forwarders fails"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example2. txt @$root > dig.out.root || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example2. txt @$f1 > dig.out.f1 || ret=1
+digcomp dig.out.root dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that global forwarders work"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example4. txt @$hidden > dig.out.hidden || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example4. txt @$f1 > dig.out.f1 || ret=1
+digcomp dig.out.hidden dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a forward zone works"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example1. txt @$hidden > dig.out.hidden || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example1. txt @$f2 > dig.out.f2 || ret=1
+digcomp dig.out.hidden dig.out.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that forwarding doesn't spontaneously happen"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example2. txt @$root > dig.out.root || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example2. txt @$f2 > dig.out.f2 || ret=1
+digcomp dig.out.root dig.out.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a forward zone with no specified policy works"
+ret=0
+$DIG $DIGOPTS +noadd +noauth txt.example3. txt @$hidden > dig.out.hidden || ret=1
+$DIG $DIGOPTS +noadd +noauth txt.example3. txt @$f2 > dig.out.f2 || ret=1
+digcomp dig.out.hidden dig.out.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that a forward only doesn't recurse"
+ret=0
+$DIG $DIGOPTS txt.example5. txt @$f2 > dig.out.f2 || ret=1
+grep "SERVFAIL" dig.out.f2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for negative caching of forwarder response"
+# prime the cache, shutdown the forwarder then check that we can
+# get the answer from the cache. restart forwarder.
+ret=0
+$DIG $DIGOPTS nonexist. txt @10.53.0.5 > dig.out.f2 || ret=1
+grep "status: NXDOMAIN" dig.out.f2 > /dev/null || ret=1
+$PERL ../stop.pl . ns4 || ret=1
+$DIG $DIGOPTS nonexist. txt @10.53.0.5 > dig.out.f2 || ret=1
+grep "status: NXDOMAIN" dig.out.f2 > /dev/null || ret=1
+$PERL ../start.pl --restart --noclean --port ${PORT} . ns4 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that forward only zone overrides empty zone"
+ret=0
+$DIG $DIGOPTS 1.0.10.in-addr.arpa TXT @10.53.0.4 > dig.out.f2
+grep "status: NOERROR" dig.out.f2 > /dev/null || ret=1
+$DIG $DIGOPTS 2.0.10.in-addr.arpa TXT @10.53.0.4 > dig.out.f2
+grep "status: NXDOMAIN" dig.out.f2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that DS lookups for grafting forward zones are isolated"
+ret=0
+$DIG $DIGOPTS grafted A @10.53.0.4 > dig.out.q1
+$DIG $DIGOPTS grafted DS @10.53.0.4 > dig.out.q2
+$DIG $DIGOPTS grafted A @10.53.0.4 > dig.out.q3
+$DIG $DIGOPTS grafted AAAA @10.53.0.4 > dig.out.q4
+grep "status: NOERROR" dig.out.q1 > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.q2 > /dev/null || ret=1
+grep "status: NOERROR" dig.out.q3 > /dev/null || ret=1
+grep "status: NOERROR" dig.out.q4 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that rfc1918 inherited 'forward first;' zones are warned about"
+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=`expr $status + $ret`
+
+echo_i "checking that ULA inherited 'forward first;' zones are warned about"
+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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/forward/ula-inherited.conf b/bin/tests/system/forward/ula-inherited.conf
new file mode 100644
index 0000000..27fc8ed
--- /dev/null
+++ b/bin/tests/system/forward/ula-inherited.conf
@@ -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 http://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..e235d20
--- /dev/null
+++ b/bin/tests/system/forward/ula-notinherited.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone d.f.ip6.arpa {
+ type forward;
+ forward first;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh
new file mode 100644
index 0000000..264d4ae
--- /dev/null
+++ b/bin/tests/system/genzone.sh
@@ -0,0 +1,468 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up a test zone
+#
+# Usage: genzone.sh master-server-number slave-server-number...
+#
+# e.g., "genzone.sh 2 3 4" means ns2 is the master and ns3, ns4
+# are slaves.
+#
+
+master="$1"
+
+cat <<EOF
+\$TTL 3600
+
+@ 86400 IN SOA ns${master} 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 (EID - not implemented by BIND)
+; type 32 (NIMLOC - not implemented by BIND)
+
+; type 33
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box
+
+; type 34 (ATMA - not implemented by BIND)
+
+; 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
+
+; 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 512 ( 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 -- 98 (unassigned)
+
+; type 99
+spf01 SPF "v=spf1 -all"
+spf02 SPF "v=spf1" " -all"
+
+; type 100 (UINFO - not implemented by BIND)
+; type 101 (UID - not implemented by BIND)
+; type 102 (GID - not implemented by BIND)
+
+; type 103 (UNSPEC - XXXMUKS TODO - this has some weird encoding - see btoa_totext())
+
+; 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 (
+; 255 ; 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 (
+; 255 ; 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 -- 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)
+
+; 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/geoip/clean.sh b/bin/tests/system/geoip/clean.sh
new file mode 100644
index 0000000..d6fe94b
--- /dev/null
+++ b/bin/tests/system/geoip/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns2/named.conf
+rm -f ns2/example*.db
+rm -f dig.out.* rndc.out.*
+rm -f data2/*dat
+[ -d data2 ] && rmdir data2
+rm -f ns?/named.run
+rm -f ns?/named.memstats
+rm -f ns*/named.lock
diff --git a/bin/tests/system/geoip/data/GeoIP.csv b/bin/tests/system/geoip/data/GeoIP.csv
new file mode 100644
index 0000000..8e71854
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIP.csv
@@ -0,0 +1,8 @@
+10.53.0.1/32 AU
+10.53.0.2/32 US
+10.53.0.3/32 GB
+10.53.0.4/32 CA
+10.53.0.5/32 CL
+10.53.0.6/32 DE
+10.53.0.7/32 EH
+192.0.2/24 O1
diff --git a/bin/tests/system/geoip/data/GeoIP.dat b/bin/tests/system/geoip/data/GeoIP.dat
new file mode 100644
index 0000000..345092f
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIP.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPASNum.csv b/bin/tests/system/geoip/data/GeoIPASNum.csv
new file mode 100644
index 0000000..774edd1
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPASNum.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32 AS100001 One Systems, Inc.
+10.53.0.2/32 AS100002 Two Technology Ltd.
+10.53.0.3/32 AS100003 Three Network Labs
+10.53.0.4/32 AS100004 Four University
+10.53.0.5/32 AS100005 Five Telecom
+10.53.0.6/32 AS100006 Six Company
+10.53.0.7/32 AS100007 Seven Communications
diff --git a/bin/tests/system/geoip/data/GeoIPASNum.dat b/bin/tests/system/geoip/data/GeoIPASNum.dat
new file mode 100644
index 0000000..2fd3938
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPASNum.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPASNumv6.csv b/bin/tests/system/geoip/data/GeoIPASNumv6.csv
new file mode 100644
index 0000000..4074289
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPASNumv6.csv
@@ -0,0 +1,7 @@
+fd92:7065:b8e:ffff::1/128,AS100001 One Systems, Inc.
+fd92:7065:b8e:ffff::2/128,AS100002 Two Technology Ltd.
+fd92:7065:b8e:ffff::3/128,AS100003 Three Network Labs
+fd92:7065:b8e:ffff::4/128,AS100004 Four University
+fd92:7065:b8e:ffff::5/128,AS100005 Five Telecom
+fd92:7065:b8e:ffff::6/128,AS100006 Six Company
+fd92:7065:b8e:ffff::7/128,AS100007 Seven Communications
diff --git a/bin/tests/system/geoip/data/GeoIPASNumv6.dat b/bin/tests/system/geoip/data/GeoIPASNumv6.dat
new file mode 100644
index 0000000..8b9504a
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPASNumv6.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPCity.csv b/bin/tests/system/geoip/data/GeoIPCity.csv
new file mode 100644
index 0000000..14900d5
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPCity.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32,US,CA,"Redwood City",94063,37.4914,-122.2110,807,650
+10.53.0.2/32,US,CA,"Santa Cruz",95060,37.0448,-122.1021,828,831
+10.53.0.3/32,US,OK,"Oklahoma City",73120,35.5798,-97.5731,650,405
+10.53.0.4/32,US,VA,Ashland,23005,37.7563,-77.4888,556,804
+10.53.0.5/32,US,GA,Atlanta,30345,33.8477,-84.2814,524,404
+10.53.0.6/32,US,CO,Morrison,80465,39.6081,-105.2072,751,303
+10.53.0.7/32,US,AK,Ketchikan,99901,55.6153,-131.5848,747,907
diff --git a/bin/tests/system/geoip/data/GeoIPCity.dat b/bin/tests/system/geoip/data/GeoIPCity.dat
new file mode 100644
index 0000000..a22ff7d
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPCity.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPCityv6.csv b/bin/tests/system/geoip/data/GeoIPCityv6.csv
new file mode 100644
index 0000000..5f09e62
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPCityv6.csv
@@ -0,0 +1,7 @@
+"fd92:7065:b8e:ffff::1","fd92:7065:b8e:ffff::1","US","CA","Redwood City","94063",37.4914,-122.2110,807,650
+"fd92:7065:b8e:ffff::2","fd92:7065:b8e:ffff::2","US","CA","Santa Cruz","95060",37.0448,-122.1021,828,831
+"fd92:7065:b8e:ffff::3","fd92:7065:b8e:ffff::3","US","OK","Oklahoma City","73120",35.5798,-97.5731,650,405
+"fd92:7065:b8e:ffff::4","fd92:7065:b8e:ffff::4","DE","07","Lotte","",52.2833,7.9167,0,0
+"fd92:7065:b8e:ffff::5","fd92:7065:b8e:ffff::5","US","GA","Atlanta","30345",33.8477,-84.2814,524,404
+"fd92:7065:b8e:ffff::6","fd92:7065:b8e:ffff::6","US","CO","Morrison","80465",39.6081,-105.2072,751,303
+"fd92:7065:b8e:ffff::7","fd92:7065:b8e:ffff::7","US","AK","Ketchikan","99901",55.6153,-131.5848,747,907
diff --git a/bin/tests/system/geoip/data/GeoIPCityv6.dat b/bin/tests/system/geoip/data/GeoIPCityv6.dat
new file mode 100644
index 0000000..ab9110f
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPCityv6.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPDomain.csv b/bin/tests/system/geoip/data/GeoIPDomain.csv
new file mode 100644
index 0000000..8611d65
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPDomain.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32 one.de
+10.53.0.2/32 two.com
+10.53.0.3/32 three.com
+10.53.0.4/32 four.com
+10.53.0.5/32 five.es
+10.53.0.6/32 six.it
+10.53.0.7/32 seven.org
diff --git a/bin/tests/system/geoip/data/GeoIPDomain.dat b/bin/tests/system/geoip/data/GeoIPDomain.dat
new file mode 100644
index 0000000..e63629b
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPDomain.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPISP.csv b/bin/tests/system/geoip/data/GeoIPISP.csv
new file mode 100644
index 0000000..3d5b4fa
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPISP.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32 One Systems, Inc.
+10.53.0.2/32 Two Technology Ltd.
+10.53.0.3/32 Three Network Labs
+10.53.0.4/32 Four University
+10.53.0.5/32 Five Telecom
+10.53.0.6/32 Six Company
+10.53.0.7/32 Seven Communications
diff --git a/bin/tests/system/geoip/data/GeoIPISP.dat b/bin/tests/system/geoip/data/GeoIPISP.dat
new file mode 100644
index 0000000..3b1761c
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPISP.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPNetSpeed.csv b/bin/tests/system/geoip/data/GeoIPNetSpeed.csv
new file mode 100644
index 0000000..4ede137
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPNetSpeed.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32 0
+10.53.0.2/32 1
+10.53.0.3/32 2
+10.53.0.4/32 3
+10.53.0.5/32 0
+10.53.0.6/32 1
+10.53.0.7/32 2
diff --git a/bin/tests/system/geoip/data/GeoIPNetSpeed.dat b/bin/tests/system/geoip/data/GeoIPNetSpeed.dat
new file mode 100644
index 0000000..13d80a9
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPNetSpeed.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPOrg.csv b/bin/tests/system/geoip/data/GeoIPOrg.csv
new file mode 100644
index 0000000..3d5b4fa
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPOrg.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32 One Systems, Inc.
+10.53.0.2/32 Two Technology Ltd.
+10.53.0.3/32 Three Network Labs
+10.53.0.4/32 Four University
+10.53.0.5/32 Five Telecom
+10.53.0.6/32 Six Company
+10.53.0.7/32 Seven Communications
diff --git a/bin/tests/system/geoip/data/GeoIPOrg.dat b/bin/tests/system/geoip/data/GeoIPOrg.dat
new file mode 100644
index 0000000..9fcc25d
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPOrg.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPRegion.csv b/bin/tests/system/geoip/data/GeoIPRegion.csv
new file mode 100644
index 0000000..0bcd872
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPRegion.csv
@@ -0,0 +1,7 @@
+10.53.0.1/32 US CA
+10.53.0.2/32 CA BC
+10.53.0.3/32 US OK
+10.53.0.4/32 AU
+10.53.0.5/32 US CO
+10.53.0.6/32 CA ON
+10.53.0.7/32 NL
diff --git a/bin/tests/system/geoip/data/GeoIPRegion.dat b/bin/tests/system/geoip/data/GeoIPRegion.dat
new file mode 100644
index 0000000..8e2d12c
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPRegion.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/GeoIPv6.csv b/bin/tests/system/geoip/data/GeoIPv6.csv
new file mode 100644
index 0000000..919bf86
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPv6.csv
@@ -0,0 +1,7 @@
+"fd92:7065:b8e:ffff::1/128",AU
+"fd92:7065:b8e:ffff::2/128",US
+"fd92:7065:b8e:ffff::3/128",GB
+"fd92:7065:b8e:ffff::4/128",CA
+"fd92:7065:b8e:ffff::5/128",CL
+"fd92:7065:b8e:ffff::6/128",DE
+"fd92:7065:b8e:ffff::7/128",EH
diff --git a/bin/tests/system/geoip/data/GeoIPv6.dat b/bin/tests/system/geoip/data/GeoIPv6.dat
new file mode 100644
index 0000000..6781a85
--- /dev/null
+++ b/bin/tests/system/geoip/data/GeoIPv6.dat
Binary files differ
diff --git a/bin/tests/system/geoip/data/README b/bin/tests/system/geoip/data/README
new file mode 100644
index 0000000..7ed1d61
--- /dev/null
+++ b/bin/tests/system/geoip/data/README
@@ -0,0 +1,34 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The data data files in this directory are sample GeoIP databases,
+generated from the corresponding CSV files. Thanks to MaxMind, Inc.
+for assistance with producing these files.
+
+Unless otherwise noted, the databases only support IPv4:
+
+GeoIP.dat: Country (IPv4)
+GeoIPv6.dat: Country (IPv6)
+GeoIPCity.dat: City (IPv4)
+GeoIPCityv6.dat: City (IPv6)
+GeoIPRegion.dat: Region
+GeoIPISP.dat: ISP
+GeoIPOrg.dat: Organization
+GeoIPDoain.dat: Domain Name
+GeoIPASNum.dat: AS Number
+GeoIPNetSpeed.dat: Net Speed
+
+GeoIP.dat can also be egenerated using the open source 'geoip-csv-to-dat'
+utility (also known in some packages as "geoip-generator"):
+
+$ geoip-csv-to-dat -i "BIND9 geoip test data v1" -o GeoIP.dat << EOF
+"10.53.0.1","10.53.0.1","171245569","171245569","AU","Australia"
+"10.53.0.2","10.53.0.2","171245570","171245570","US","United States"
+"10.53.0.3","10.53.0.3","171245571","171245571","GB","United Kingdom"
+"10.53.0.4","10.53.0.4","171245572","171245572","CA","Canada"
+"10.53.0.5","10.53.0.5","171245573","171245573","CL","Chile"
+"10.53.0.6","10.53.0.6","171245574","171245574","DE","Germany"
+"10.53.0.7","10.53.0.7","171245575","171245575","EH","Western Sahara"
+"192.0.2.0","192.0.2.255","3221225984","3221226239","O1","Other"
+EOF
diff --git a/bin/tests/system/geoip/ns2/example.db.in b/bin/tests/system/geoip/ns2/example.db.in
new file mode 100644
index 0000000..836359d
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/geoip/ns2/named1.conf.in b/bin/tests/system/geoip/ns2/named1.conf.in
new file mode 100644
index 0000000..a425311
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named1.conf.in
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db country country US; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db country country GB; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip db country country CA; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip db country country CL; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip db country country DE; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db country country EH; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view other {
+ match-clients { geoip db country country O1; };
+ zone "example" {
+ type master;
+ file "exampleother.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named10.conf.in b/bin/tests/system/geoip/ns2/named10.conf.in
new file mode 100644
index 0000000..1372d41
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named10.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip asnum "AS100001"; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip asnum "AS100002"; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip asnum "AS100003"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip asnum "AS100004"; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip asnum "AS100005"; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip asnum "AS100006"; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip asnum "AS100007"; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named11.conf.in b/bin/tests/system/geoip/ns2/named11.conf.in
new file mode 100644
index 0000000..c7a0ad2
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named11.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip domain one.de; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip domain two.com; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip domain three.com; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip domain four.com; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip domain five.es; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip domain six.it; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip domain seven.org; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named12.conf.in b/bin/tests/system/geoip/ns2/named12.conf.in
new file mode 100644
index 0000000..68abc85
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named12.conf.in
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip netspeed 0; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip netspeed 1; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip netspeed 2; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip netspeed 3; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named13.conf.in b/bin/tests/system/geoip/ns2/named13.conf.in
new file mode 100644
index 0000000..05a3314
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named13.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 { none; };
+ recursion no;
+ geoip-directory "../data";
+ blackhole { blocking; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/geoip/ns2/named14.conf.in b/bin/tests/system/geoip/ns2/named14.conf.in
new file mode 100644
index 0000000..6d9d966
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named14.conf.in
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 { none; };
+ recursion no;
+ geoip-directory "../data";
+ geoip-use-ecs no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { gUS; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { gGB; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { gCA; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { gCL; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { gDE; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { gEH; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "examplebogus.db";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named15.conf.in b/bin/tests/system/geoip/ns2/named15.conf.in
new file mode 100644
index 0000000..01ee377
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named15.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data2";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view two {
+ match-clients { geoip country US; };
+ zone "example" {
+ type master;
+ file "../ns2/example2.db";
+ };
+};
+
+view none {
+ zone "example" {
+ type master;
+ file "examplebogus.db";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named2.conf.in b/bin/tests/system/geoip/ns2/named2.conf.in
new file mode 100644
index 0000000..541f904
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named2.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip db country country AUS; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db country country USA; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db country country GBR; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip db country country CAN; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip db country country CHL; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip db country country DEU; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db country country ESH; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named3.conf.in b/bin/tests/system/geoip/ns2/named3.conf.in
new file mode 100644
index 0000000..a8cf6a3
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named3.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db country country "United States"; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db country country "United Kingdom"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip db country country Canada; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip db country country Chile; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip db country country Germany; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db country country "Western Sahara"; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named4.conf.in b/bin/tests/system/geoip/ns2/named4.conf.in
new file mode 100644
index 0000000..81e3e65
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named4.conf.in
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip region CA; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view three {
+ match-clients { geoip region OK; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip region VA; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip region GA; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip region CO; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip region AK; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named5.conf.in b/bin/tests/system/geoip/ns2/named5.conf.in
new file mode 100644
index 0000000..0c4ce50
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named5.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db region region "British Columbia"; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db region region "Oklahoma"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip db region country AU; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip db region region "Colorado"; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip db region region "Ontario"; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db region country NL; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named6.conf.in b/bin/tests/system/geoip/ns2/named6.conf.in
new file mode 100644
index 0000000..195133b
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named6.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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::1; };
+ recursion no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip city "Redwood City"; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip city "Santa Cruz"; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip city "Oklahoma City"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip city "Ashland"; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip city "Atlanta"; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip city "Morrison"; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip city "Ketchikan"; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named7.conf.in b/bin/tests/system/geoip/ns2/named7.conf.in
new file mode 100644
index 0000000..4fa4626
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named7.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip isp "Two Technology Ltd."; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip isp "Three Network Labs"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip isp "Four University"; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip isp "Five Telecom"; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip isp "Six Company"; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip isp "Seven Communications"; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named8.conf.in b/bin/tests/system/geoip/ns2/named8.conf.in
new file mode 100644
index 0000000..2840c8f
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named8.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip org "Two Technology Ltd."; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip org "Three Network Labs"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip org "Four University"; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip org "Five Telecom"; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip org "Six Company"; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip org "Seven Communications"; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/ns2/named9.conf.in b/bin/tests/system/geoip/ns2/named9.conf.in
new file mode 100644
index 0000000..720f7ac
--- /dev/null
+++ b/bin/tests/system/geoip/ns2/named9.conf.in
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip asnum "AS100001 One Systems, Inc."; };
+ zone "example" {
+ type master;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip asnum "AS100002 Two Technology Ltd."; };
+ zone "example" {
+ type master;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip asnum "AS100003 Three Network Labs"; };
+ zone "example" {
+ type master;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip asnum "AS100004 Four University"; };
+ zone "example" {
+ type master;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip asnum "AS100005 Five Telecom"; };
+ zone "example" {
+ type master;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip asnum "AS100006 Six Company"; };
+ zone "example" {
+ type master;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip asnum "AS100007 Seven Communications"; };
+ zone "example" {
+ type master;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type master;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip/options.conf b/bin/tests/system/geoip/options.conf
new file mode 100644
index 0000000..95df0af
--- /dev/null
+++ b/bin/tests/system/geoip/options.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 PST;
+ geoip timezone PST;
+ geoip postal 95060;
+ geoip postalcode 95060;
+ };
+};
+
diff --git a/bin/tests/system/geoip/prereq.sh b/bin/tests/system/geoip/prereq.sh
new file mode 100644
index 0000000..9bd4429
--- /dev/null
+++ b/bin/tests/system/geoip/prereq.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$FEATURETEST --have-geoip || {
+ echo_i "This test requires GeoIP support." >&2
+ exit 255
+}
+exit 0
diff --git a/bin/tests/system/geoip/setup.sh b/bin/tests/system/geoip/setup.sh
new file mode 100644
index 0000000..c85dd90
--- /dev/null
+++ b/bin/tests/system/geoip/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
+
+mkdir -p data2
+cp data/GeoIPv6.dat data2/
diff --git a/bin/tests/system/geoip/tests.sh b/bin/tests/system/geoip/tests.sh
new file mode 100644
index 0000000..cb1473a
--- /dev/null
+++ b/bin/tests/system/geoip/tests.sh
@@ -0,0 +1,484 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+n=`expr $n + 1`
+echo_i "checking GeoIP country database by code ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP country database by code (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking response scope using client subnet ($n)"
+ret=0
+$DIG +tcp -p ${PORT} @10.53.0.2 txt example -b 127.0.0.1 +subnet="10.53.0.1/32" > dig.out.ns2.test$n.1 || ret=1
+grep 'CLIENT-SUBNET.*10.53.0.1/32/32' dig.out.ns2.test$n.1 > /dev/null || ret=1
+$DIG +tcp -p ${PORT} @10.53.0.2 txt example -b 127.0.0.1 +subnet="192.0.2.64/32" > dig.out.ns2.test$n.2 || ret=1
+grep 'CLIENT-SUBNET.*192.0.2.64/32/24' dig.out.ns2.test$n.2 > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named2.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP country database by three-letter code ($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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named3.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP country database by name ($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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named4.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP region code, no specified database ($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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named5.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP region database by region name and country code ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP region database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+
+echo_i "reloading server"
+copy_setports ns2/named6.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+if $TESTSOCK6 fd92:7065:b8e:ffff::3
+then
+ n=`expr $n + 1`
+ echo_i "checking GeoIP city database by city name using IPv6 ($n)"
+ ret=0
+ $DIG +tcp +short -p ${PORT} @fd92:7065:b8e:ffff::1 -6 txt example -b fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=`expr $status + $ret`
+else
+ echo_i "IPv6 unavailable; skipping"
+fi
+
+n=`expr $n + 1`
+echo_i "checking GeoIP city database by city name ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP city database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named7.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP isp database ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP isp database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named8.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP org database ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP org database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named9.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP asnum database ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP asnum database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named10.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP asnum database - ASNNNN only ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP asnum database - ASNNNN only (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named11.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP domain database ($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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP domain database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named12.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP netspeed database ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4; 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP netspeed database (using client subnet) ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4; do
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named13.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP blackhole ACL ($n)"
+ret=0
+$DIG $DIGOPTS txt example -b 10.53.0.$i > 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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named14.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking GeoIP country database by code (using nested ACLs) ($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=`expr $status + $ret`
+
+echo_i "reloading server"
+copy_setports ns2/named14.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+
+n=`expr $n + 1`
+echo_i "checking geoip-use-ecs ($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
+
+ $DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.ecs.$i || lret=1
+ j=`cat dig.out.ns2.test$n.ecs.$i | tr -d '"'`
+ [ "$j" = "bogus" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "reloading server with different geoip-directory ($n)"
+copy_setports ns2/named15.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 3
+awk '/using "..\/data2" as GeoIP directory/ {m=1} ; { if (m>0) { print } }' ns2/named.run | grep "GeoIP City .* DB not available" > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking GeoIP v4/v6 when only IPv6 database is available ($n)"
+ret=0
+$DIG $DIGOPTS -4 txt example -b 10.53.0.2 > dig.out.ns2.test$n.1 || ret=1
+j=`cat dig.out.ns2.test$n.1 | tr -d '"'`
+[ "$j" = "bogus" ] || ret=1
+if $TESTSOCK6 fd92:7065:b8e:ffff::2; then
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n.2 || ret=1
+ j=`cat dig.out.ns2.test$n.2 | tr -d '"'`
+ [ "$j" = "2" ] || ret=1
+fi
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking other GeoIP options are parsed correctly ($n)"
+ret=0
+$CHECKCONF options.conf || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/glue/clean.sh b/bin/tests/system/glue/clean.sh
new file mode 100644
index 0000000..25e408d
--- /dev/null
+++ b/bin/tests/system/glue/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after glue tests.
+#
+
+rm -f dig.out ns1/cache
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
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/cache.in b/bin/tests/system/glue/ns1/cache.in
new file mode 100644
index 0000000..8089efb
--- /dev/null
+++ b/bin/tests/system/glue/ns1/cache.in
@@ -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 http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; Preloaded cache data for glue test
+
+$TTL 86400
+ns.zz. 3600 IN A 10.0.0.1
+ns.zz. IN AAAA 10::1
+ns.zz. IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
diff --git a/bin/tests/system/glue/ns1/mil.db b/bin/tests/system/glue/ns1/mil.db
new file mode 100644
index 0000000..2dda694
--- /dev/null
+++ b/bin/tests/system/glue/ns1/mil.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN mil.
+$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.
+
+ARL.MIL. 172800 IN NS NS1.ARL.MIL.
+NS1.arl.mil. 172800 IN A 128.63.16.4
+
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..20cc887
--- /dev/null
+++ b/bin/tests/system/glue/ns1/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ cache-file "cache";
+ check-integrity no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "root-servers.nil" {
+ type master;
+ file "root-servers.nil.db";
+};
+zone "net" {
+ type master;
+ file "net.db";
+};
+
+zone "mil" {
+ type master;
+ file "mil.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..b98271e
--- /dev/null
+++ b/bin/tests/system/glue/ns1/net.db
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e40f392
--- /dev/null
+++ b/bin/tests/system/glue/ns1/root-servers.nil.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..1d58542
--- /dev/null
+++ b/bin/tests/system/glue/ns1/root.db
@@ -0,0 +1,68 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.
+mil. 172800 IN NS a.root-servers.nil.
+se. 172800 IN NS ns.uu.net.
+
+;
+; 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
+
+;
+; Another sample ccTLD
+;
+is. 172800 IN NS ISGATE.is.
+is. 172800 IN NS NISC.JVNC.NET.
+is. 172800 IN NS NS.EU.NET.
+is. 172800 IN NS SPARKY.ARL.MIL.
+is. 172800 IN NS SUNIC.SUNET.SE.
+ISGATE.is. 172800 IN A 193.4.58.51
+NISC.JVNC.NET. 172800 IN A 128.121.50.7
+NS.EU.NET. 172800 IN A 192.16.202.11
+SPARKY.ARL.MIL. 172800 IN A 128.63.58.18
+SUNIC.SUNET.SE. 172800 IN A 192.36.125.2
+
+;
+; A hypothetical ccTLD where we are authoritative for the NS glue.
+;
+xx. 172800 IN NS b.root-servers.nil.
+
+;
+; A hypothetical ccTLD where we have cached NS glue.
+;
+yy. 172800 IN NS ns.zz.
diff --git a/bin/tests/system/glue/setup.sh b/bin/tests/system/glue/setup.sh
new file mode 100644
index 0000000..062e453
--- /dev/null
+++ b/bin/tests/system/glue/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
+
+cd ns1 && cp -f cache.in cache
diff --git a/bin/tests/system/glue/tests.sh b/bin/tests/system/glue/tests.sh
new file mode 100644
index 0000000..0425a34
--- /dev/null
+++ b/bin/tests/system/glue/tests.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+#
+# 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 find glue A RRs we are authoritative for"
+$DIG +norec @10.53.0.1 -p ${PORT} foo.bar.xx. a >dig.out || status=1
+$PERL ../digcomp.pl xx.good dig.out || status=1
+
+echo_i "testing that we find glue A/AAAA RRs in the cache"
+$DIG +norec @10.53.0.1 -p ${PORT} foo.bar.yy. a >dig.out || status=1
+$PERL ../digcomp.pl yy.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/xx.good b/bin/tests/system/glue/xx.good
new file mode 100644
index 0000000..19ae1d7
--- /dev/null
+++ b/bin/tests/system/glue/xx.good
@@ -0,0 +1,16 @@
+
+; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.xx. a
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41239
+;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
+
+;; QUESTION SECTION:
+;foo.bar.xx. IN A
+
+;; AUTHORITY SECTION:
+xx. 172800 IN NS b.root-servers.nil.
+
+;; ADDITIONAL SECTION:
+b.root-servers.nil. 300 IN A 10.53.0.2
+
diff --git a/bin/tests/system/glue/yy.good b/bin/tests/system/glue/yy.good
new file mode 100644
index 0000000..fd97e3d
--- /dev/null
+++ b/bin/tests/system/glue/yy.good
@@ -0,0 +1,17 @@
+
+; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.yy. a
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6172
+;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 3
+
+;; QUESTION SECTION:
+;foo.bar.yy. IN A
+
+;; AUTHORITY SECTION:
+yy. 172800 IN NS ns.zz.
+
+;; ADDITIONAL SECTION:
+ns.zz. 3463 IN A 10.0.0.1
+ns.zz. 86263 IN AAAA 10::1
+
diff --git a/bin/tests/system/gost/clean.sh b/bin/tests/system/gost/clean.sh
new file mode 100644
index 0000000..3779676
--- /dev/null
+++ b/bin/tests/system/gost/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */dsset-* */*.signed */trusted.conf
+rm -f ns1/root.db
+rm -f ns1/signer.err
+rm -f dig.out*
+rm -f */named.run
+rm -f */named.memstats
+rm -f ns*/named.lock
diff --git a/bin/tests/system/gost/ns1/named.conf b/bin/tests/system/gost/ns1/named.conf
new file mode 100644
index 0000000..715f7d3
--- /dev/null
+++ b/bin/tests/system/gost/ns1/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/gost/ns1/root.db.in b/bin/tests/system/gost/ns1/root.db.in
new file mode 100644
index 0000000..e882893
--- /dev/null
+++ b/bin/tests/system/gost/ns1/root.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2010121600 ; 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/gost/ns1/sign.sh b/bin/tests/system/gost/ns1/sign.sh
new file mode 100644
index 0000000..bdd78d5
--- /dev/null
+++ b/bin/tests/system/gost/ns1/sign.sh
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+key1=`$KEYGEN -q -r $RANDFILE -a ECCGOST -n zone $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a ECCGOST -n zone -f KSK $zone`
+$DSFROMKEY -a gost $key2.key > dsset-gost
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err
+
+# Configure the resolving server with a trusted key.
+
+cat $key1.key | grep -v '^; ' | $PERL -n -e '
+local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
+local $key = join("", @rest);
+print <<EOF
+trusted-keys {
+ "$dn" $flags $proto $alg "$key";
+};
+EOF
+' > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
diff --git a/bin/tests/system/gost/ns2/named.conf b/bin/tests/system/gost/ns2/named.conf
new file mode 100644
index 0000000..50621a5
--- /dev/null
+++ b/bin/tests/system/gost/ns2/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 yes;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/gost/prereq.sh b/bin/tests/system/gost/prereq.sh
new file mode 100644
index 0000000..f5295b7
--- /dev/null
+++ b/bin/tests/system/gost/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh gost
diff --git a/bin/tests/system/gost/setup.sh b/bin/tests/system/gost/setup.sh
new file mode 100644
index 0000000..96b421c
--- /dev/null
+++ b/bin/tests/system/gost/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+cd ns1 && $SHELL sign.sh
diff --git a/bin/tests/system/gost/tests.sh b/bin/tests/system/gost/tests.sh
new file mode 100644
index 0000000..516f0c1
--- /dev/null
+++ b/bin/tests/system/gost/tests.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+# Check the example. domain
+
+echo "I:checking that positive validation works ($n)"
+ret=0
+$DIG $DIGOPTS . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS . @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
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/idna/clean.sh b/bin/tests/system/idna/clean.sh
new file mode 100644
index 0000000..7a8e0d3
--- /dev/null
+++ b/bin/tests/system/idna/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f dig.out.*
+rm -f ns*/named.lock
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..92acac9
--- /dev/null
+++ b/bin/tests/system/idna/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ 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-enable no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type master;
+ 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..76ed2a0
--- /dev/null
+++ b/bin/tests/system/idna/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7e60631
--- /dev/null
+++ b/bin/tests/system/idna/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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..6637bf6
--- /dev/null
+++ b/bin/tests/system/idna/tests.sh
@@ -0,0 +1,347 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+# 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=`expr $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
+ if [ $? -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=`expr $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=`expr $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
+ if [ $? -eq 0 ]; then
+ echo_i "failed: dig command unexpectedly succeeded"
+ ret=1
+ fi
+ status=`expr $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ünchen."
+ 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ß.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" "βόλος.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" "βόλοσ.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."
+
+
+
+ # 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_fail "$text" "" "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_fail "$text" "" "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 IDNA names.
+ #
+ # +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_fail "$text" "" "🧦.com"
+ idna_test "$text" "+noidnin +noidnout" "🧦.com" "\240\159\167\166.com."
+ idna_test "$text" "+noidnin +idnout" "🧦.com" "\240\159\167\166.com."
+ idna_fail "$text" "+idnin +noidnout" "🧦.com"
+ idna_fail "$text" "+idnin +idnout" "🧦.com"
+
+ # Tests of a valid unicode string but an invalid U-label (output)
+ #
+ # Symbols are not valid IDNA names.
+ #
+ # Note that an invalid U-label is accepted even when +idnin is in effect
+ # because "xn--19g" is valid Punycode.
+ #
+ # +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_fail "$text" "" "xn--19g"
+ idna_test "$text" "+noidnin +noidnout" "xn--19g" "xn--19g."
+ idna_fail "$text" "+noidnin +idnout" "xn--19g"
+ idna_test "$text" "+idnin +noidnout" "xn--19g" "xn--19g."
+ idna_fail "$text" "+idnin +idnout" "xn--19g"
+}
+
+
+# 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
+
+$FEATURETEST --with-idn
+if [ $? -eq 0 ]; then
+ idna_enabled_test
+else
+ idna_disabled_test
+fi
+
+exit $status
diff --git a/bin/tests/system/ifconfig.bat b/bin/tests/system/ifconfig.bat
new file mode 100644
index 0000000..0d87c79
--- /dev/null
+++ b/bin/tests/system/ifconfig.bat
@@ -0,0 +1,34 @@
+echo off
+rem
+rem Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+rem
+rem This Source Code Form is subject to the terms of the Mozilla Public
+rem License, v. 2.0. If a copy of the MPL was not distributed with this
+rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+rem ifconfig.bat
+rem Set up interface aliases for bind9 system tests.
+rem
+rem IPv4: 10.53.0.{1..8} RFC 1918
+rem IPv6: fd92:7065:b8e:ffff::{1..8} ULA
+rem
+
+echo Please adapt this script to your system
+rem remove the following line when the script is ready
+exit /b 1
+
+rem for IPv4 adding these static addresses to a physical interface
+rem will switch it from DHCP to static flushing DHCP setup.
+rem So it is highly recommended to install the loopback pseudo-interface
+rem and add IPv4 addresses to it.
+
+rem for IPv6 your interface can have a different name, e.g.,
+rem "Local Area Connection". Please update this script and remove the
+rem exit line
+
+echo on
+
+FOR %%I IN (1,2,3,4,5,6,7,8) DO (
+ netsh interface ipv4 add address name=Loopback 10.53.0.%%I 255.255.255.0
+ netsh interface ipv6 add address interface=Ethernet fd92:7065:b8e:ffff::%%I/64
+)
diff --git a/bin/tests/system/ifconfig.sh b/bin/tests/system/ifconfig.sh
new file mode 100755
index 0000000..e8232f8
--- /dev/null
+++ b/bin/tests/system/ifconfig.sh
@@ -0,0 +1,263 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up interface aliases for bind9 system tests.
+#
+# IPv4: 10.53.0.{1..10} RFC 1918
+# 10.53.1.{0..2}
+# 10.53.2.{0..2}
+# IPv6: fd92:7065:b8e:ffff::{1..10} ULA
+# fd92:7065:b8e:99ff::{1..2}
+# fd92:7065:b8e:ff::{1..2}
+#
+
+config_guess=""
+for f in ./config.guess ../../../config.guess
+do
+ if test -f $f
+ then
+ config_guess=$f
+ fi
+done
+
+if test "X$config_guess" = "X"
+then
+ cat <<EOF >&2
+$0: must be run from the top level source directory or the
+bin/tests/system directory
+EOF
+ exit 1
+fi
+
+sys=`sh $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
+
+case "$1" in
+
+ start|up)
+ for i in 0 1 2
+ do
+ case $i in
+ 0) ipv6="ff" ;;
+ 1) ipv6="99" ;;
+ 2) ipv6="00" ;;
+ *) ipv6="" ;;
+ esac
+ for ns in 1 2 3 4 5 6 7 8 9 10
+ do
+ [ $i -gt 0 -a $ns -gt 2 ] && break
+ int=`expr $i \* 10 + $ns`
+ case "$sys" in
+ *-pc-solaris2.5.1)
+ ifconfig lo0:$int 10.53.$i.$ns \
+ netmask 0xffffffff up
+ ;;
+ *-sun-solaris2.[6-7])
+ ifconfig lo0:$int 10.53.$i.$ns \
+ netmask 0xffffffff up
+ ;;
+ *-*-solaris2.[8-9]|*-*-solaris2.1[0-9])
+ /sbin/ifconfig lo0:$int plumb
+ /sbin/ifconfig lo0:$int 10.53.$i.$ns up
+ /sbin/ifconfig lo0:$int inet6 plumb
+ [ "$ipv6" ] && /sbin/ifconfig lo0:$int \
+ inet6 fd92:7065:b8e:${ipv6}ff::$ns up
+ ;;
+ *-*-linux*)
+ if [ $use_ip ]; then
+ ip address add 10.53.$i.$ns/24 \
+ dev lo:$int
+ [ "$ipv6" ] && ip address add \
+ fd92:7065:b8e:${ipv6}ff::$ns/64 \
+ dev lo
+ else
+ ifconfig lo:$int 10.53.$i.$ns up \
+ netmask 255.255.255.0
+ [ "$ipv6" ] && ifconfig lo inet6 add \
+ fd92:7065:b8e:${ipv6}ff::$ns/64
+ fi
+ ;;
+ *-unknown-freebsd*)
+ ifconfig lo0 10.53.$i.$ns alias \
+ netmask 0xffffffff
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns alias
+ ;;
+ *-unknown-netbsd*)
+ ifconfig lo0 10.53.$i.$ns alias \
+ netmask 255.255.255.0
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns alias
+ ;;
+ *-unknown-openbsd*)
+ ifconfig lo0 10.53.$i.$ns alias \
+ netmask 255.255.255.0
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns alias
+ ;;
+ *-*-bsdi[3-5].*)
+ ifconfig lo0 add 10.53.$i.$ns \
+ netmask 255.255.255.0
+ ;;
+ *-dec-osf[4-5].*)
+ ifconfig lo0 alias 10.53.$i.$ns
+ ;;
+ *-sgi-irix6.*)
+ ifconfig lo0 alias 10.53.$i.$ns
+ ;;
+ *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ ifconfig lo0 10.53.$i.$ns alias \
+ netmask 0xffffffff
+ ;;
+ *-ibm-aix4.*|*-ibm-aix5.*)
+ ifconfig lo0 alias 10.53.$i.$ns
+ [ "$ipv6" ] && ifconfig lo0 inet6 alias -dad \
+ fd92:7065:b8e:${ipv6}ff::$ns/64
+ ;;
+ hpux)
+ ifconfig lo0:$int 10.53.$i.$ns \
+ netmask 255.255.255.0 up
+ [ "$ipv6" ] && ifconfig lo0:$int inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns up
+ ;;
+ *-sco3.2v*)
+ ifconfig lo0 alias 10.53.$i.$ns
+ ;;
+ *-darwin*)
+ ifconfig lo0 alias 10.53.$i.$ns
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns alias
+ ;;
+ *-cygwin*)
+ echo "Please run ifconfig.bat as Administrator."
+ exit 1
+ ;;
+ *)
+ echo "Don't know how to set up interface. Giving up."
+ exit 1
+ esac
+ done
+ done
+ ;;
+
+ stop|down)
+ for i in 0 1 2
+ do
+ case $i in
+ 0) ipv6="ff" ;;
+ 1) ipv6="99" ;;
+ 2) ipv6="00" ;;
+ *) ipv6="" ;;
+ esac
+ for ns in 10 9 8 7 6 5 4 3 2 1
+ do
+ [ $i -gt 0 -a $ns -gt 2 ] && continue
+ int=`expr $i \* 10 + $ns - 1`
+ case "$sys" in
+ *-pc-solaris2.5.1)
+ ifconfig lo0:$int 0.0.0.0 down
+ ;;
+ *-sun-solaris2.[6-7])
+ ifconfig lo0:$int 10.53.$i.$ns down
+ ;;
+ *-*-solaris2.[8-9]|*-*-solaris2.1[0-9])
+ ifconfig lo0:$int 10.53.$i.$ns down
+ ifconfig lo0:$int 10.53.$i.$ns unplumb
+ ifconfig lo0:$int inet6 down
+ ifconfig lo0:$int inet6 unplumb
+ ;;
+ *-*-linux*)
+ if [ $use_ip ]; then
+ ip address del 10.53.$i.$ns/24 \
+ dev lo:$int
+ [ "$ipv6" ] && ip address del \
+ fd92:7065:b8e:${ipv6}ff::$ns/64 \
+ dev lo
+ else
+ ifconfig lo:$int 10.53.$i.$ns down
+ [ "$ipv6" ] && ifconfig lo inet6 \
+ del fd92:7065:b8e:${ipv6}ff::$ns/64
+ fi
+ ;;
+ *-unknown-freebsd*)
+ ifconfig lo0 10.53.$i.$ns delete
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns delete
+ ;;
+ *-unknown-netbsd*)
+ ifconfig lo0 10.53.$i.$ns delete
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns delete
+ ;;
+ *-unknown-openbsd*)
+ ifconfig lo0 10.53.$i.$ns delete
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns delete
+ ;;
+ *-*-bsdi[3-5].*)
+ ifconfig lo0 remove 10.53.$i.$ns
+ ;;
+ *-dec-osf[4-5].*)
+ ifconfig lo0 -alias 10.53.$i.$ns
+ ;;
+ *-sgi-irix6.*)
+ ifconfig lo0 -alias 10.53.$i.$ns
+ ;;
+ *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ ifconfig lo0 -alias 10.53.$i.$ns
+ ;;
+ *-ibm-aix4.*|*-ibm-aix5.*)
+ ifconfig lo0 delete 10.53.$i.$ns
+ [ "$ipv6" ] && ifconfig lo0 delete inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns/64
+ ;;
+ hpux)
+ ifconfig lo0:$int 0.0.0.0
+ ifconfig lo0:$int inet6 ::
+ ;;
+ *-sco3.2v*)
+ ifconfig lo0 -alias 10.53.$i.$ns
+ ;;
+ *darwin*)
+ ifconfig lo0 -alias 10.53.$i.$ns
+ [ "$ipv6" ] && ifconfig lo0 inet6 \
+ fd92:7065:b8e:${ipv6}ff::$ns delete
+ ;;
+ *-cygwin*)
+ echo "Please run ifconfig.bat as Administrator."
+ exit 1
+ ;;
+ *)
+ echo "Don't know how to destroy interface. Giving up."
+ exit 1
+ esac
+ done
+ done
+ ;;
+
+ *)
+ echo "Usage: $0 { up | down }"
+ exit 1
+esac
diff --git a/bin/tests/system/inline/checkdsa.sh.in b/bin/tests/system/inline/checkdsa.sh.in
new file mode 100644
index 0000000..5b6ea2e
--- /dev/null
+++ b/bin/tests/system/inline/checkdsa.sh.in
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+if [ "@CHECK_DSA@" -eq 0 ]; then
+ exit 1
+fi
+if [ ! -r /dev/random -o ! -r /dev/urandom ]; then
+ exit 1
+fi
+
+exit 0
diff --git a/bin/tests/system/inline/clean.sh b/bin/tests/system/inline/clean.sh
new file mode 100644
index 0000000..6bcd8ad
--- /dev/null
+++ b/bin/tests/system/inline/clean.sh
@@ -0,0 +1,127 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.run.prev
+rm -f */trusted.conf
+rm -f ns1/K*
+rm -f ns1/dsset-*
+rm -f ns3/dsset-*
+rm -f ns1/root.db
+rm -f ns1/root.db.signed
+rm -f ns2/bits.db
+rm -f ns2/bits.db.jnl
+rm -f ns1/signer.out
+rm -f ns2/inactiveksk.db
+rm -f ns2/inactiveksk.db.jnl
+rm -f ns2/inactivezsk.db
+rm -f ns2/inactivezsk.db.jnl
+rm -f ns2/nokeys.db
+rm -f ns2/nokeys.db.jnl
+rm -f ns2/removedkeys-secondary.db
+rm -f ns2/removedkeys-secondary.db.jnl
+rm -f ns2/retransfer.db
+rm -f ns2/retransfer.db.jnl
+rm -f ns2/retransfer3.db
+rm -f ns2/retransfer3.db.jnl
+rm -f ns3/K*
+rm -f ns3/bits.bk
+rm -f ns3/bits.bk.jnl
+rm -f ns3/bits.bk.signed
+rm -f ns3/bits.bk.signed.jnl
+rm -f ns3/noixfr.bk
+rm -f ns3/noixfr.bk.jnl
+rm -f ns3/noixfr.bk.signed
+rm -f ns3/noixfr.bk.signed.jnl
+rm -f ns3/master.db
+rm -f ns3/master.db.jnl
+rm -f ns3/master.db.signed
+rm -f ns3/master.db.signed.jnl
+rm -f ns3/dynamic.db
+rm -f ns3/dynamic.db.jnl
+rm -f ns3/dynamic.db.signed
+rm -f ns3/dynamic.db.signed.jnl
+rm -f ns3/updated.db
+rm -f ns3/updated.db.jnl
+rm -f ns3/updated.db.signed
+rm -f ns3/updated.db.signed.jnl
+rm -f ns3/expired.db
+rm -f ns3/expired.db.jnl
+rm -f ns3/expired.db.signed
+rm -f ns3/expired.db.signed.jnl
+rm -f ns3/inactiveksk.bk
+rm -f ns3/inactiveksk.bk.jnl
+rm -f ns3/inactiveksk.bk.signed
+rm -f ns3/inactiveksk.bk.signed.jnl
+rm -f ns3/inactivezsk.bk
+rm -f ns3/inactivezsk.bk.jnl
+rm -f ns3/inactivezsk.bk.signed
+rm -f ns3/inactivezsk.bk.signed.jnl
+rm -f ns3/nokeys.bk
+rm -f ns3/nokeys.bk.jnl
+rm -f ns3/nokeys.bk.signed
+rm -f ns3/nokeys.bk.signed.jnl
+rm -f ns3/nsec3.db
+rm -f ns3/nsec3.db.jnl
+rm -f ns3/nsec3.db.signed
+rm -f ns3/nsec3.db.signed.jnl
+rm -f ns3/delayedkeys.db
+rm -f ns3/delayedkeys.db.jnl
+rm -f ns3/delayedkeys.db.signed
+rm -f ns3/delayedkeys.db.signed.jnl
+rm -f ns3/removedkeys-primary.db
+rm -f ns3/removedkeys-primary.db.jnl
+rm -f ns3/removedkeys-primary.db.signed
+rm -f ns3/removedkeys-primary.db.signed.jnl
+rm -f ns3/removedkeys-secondary.bk
+rm -f ns3/removedkeys-secondary.bk.jnl
+rm -f ns3/removedkeys-secondary.bk.signed
+rm -f ns3/removedkeys-secondary.bk.signed.jnl
+rm -f ns3/retransfer.bk
+rm -f ns3/retransfer.bk.jnl
+rm -f ns3/retransfer.bk.signed
+rm -f ns3/retransfer.bk.signed.jnl
+rm -f ns3/retransfer3.bk
+rm -f ns3/retransfer3.bk.jnl
+rm -f ns3/retransfer3.bk.signed
+rm -f ns3/retransfer3.bk.signed.jnl
+rm -f ns3/externalkey.db
+rm -f ns3/externalkey.db.signed
+rm -f ns3/externalkey.db.signed.jnl
+rm -f ns4/K*
+rm -f ns4/noixfr.db
+rm -f ns4/noixfr.db.jnl
+rm -f ns5/K*
+rm -f ns5/bits.bk
+rm -f ns5/bits.bk.jnl
+rm -f ns5/bits.bk.signed
+rm -f ns5/bits.bk.signed.jnl
+rm -f ns7/K*
+rm -f ns7/nsec3-loop.db
+rm -f ns7/nsec3-loop.db.signed
+rm -f ns7/nsec3-loop.db.signed.jnl
+rm -f */*.jbk
+rm -f dig.out.ns*
+rm -f signing.out*
+rm -f freeze.test*
+rm -f thaw.test*
+rm -f */*.nzd */*.nzd-lock */*.nzf
+rm -f ns3/test-?.bk
+rm -f ns3/test-?.bk.signed
+rm -f ns3/test-?.bk.signed.jnl
+rm -f import.key Kimport*
+rm -f checkgost checkdsa checkecdsa
+rm -f ns3/a-file
+rm -f ns*/named.lock
+rm -f dig.out.*
+rm -f ns3/nzf-*
+rm -f rndc.out.ns*
+rm -rf 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..215800c
--- /dev/null
+++ b/bin/tests/system/inline/ns1/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..5f8640f
--- /dev/null
+++ b/bin/tests/system/inline/ns1/root.db.in
@@ -0,0 +1,57 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+
+master. NS ns3.master.
+ns3.master. 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..4c7dfd2
--- /dev/null
+++ b/bin/tests/system/inline/ns1/sign.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+rm -f K.+*+*.key
+rm -f K.+*+*.private
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+$SIGNER -S -x -T 1200 -o ${zone} root.db > signer.out 2>&1
+[ $? = 0 ] || cat signer.out
+
+keyfile_to_trusted_keys $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..a86fe8f
--- /dev/null
+++ b/bin/tests/system/inline/ns2/bits.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c4da508
--- /dev/null
+++ b/bin/tests/system/inline/ns2/named.conf.in
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+};
+
+zone "bits" {
+ type master;
+ file "bits.db";
+ allow-update { any; };
+};
+
+zone "retransfer" {
+ type master;
+ file "retransfer.db";
+ allow-update { any; };
+ notify no;
+};
+
+zone "retransfer3" {
+ type master;
+ file "retransfer3.db";
+ allow-update { any; };
+ allow-transfer { none; }; // changed dynamically by tests.sh
+ notify no;
+};
+
+zone "nsec3-loop" {
+ type master;
+ file "nsec3-loop.db";
+ notify no;
+};
+
+zone "inactiveksk" {
+ type master;
+ file "inactiveksk.db";
+ allow-update { any; };
+};
+
+zone "inactivezsk" {
+ type master;
+ file "inactivezsk.db";
+ allow-update { any; };
+};
+
+zone "nokeys" {
+ type master;
+ file "nokeys.db";
+ allow-update { any; };
+};
+
+zone "removedkeys-secondary" {
+ type master;
+ file "removedkeys-secondary.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/inline/ns2/nsec3-loop.db b/bin/tests/system/inline/ns2/nsec3-loop.db
new file mode 100644
index 0000000..ba0db9d
--- /dev/null
+++ b/bin/tests/system/inline/ns2/nsec3-loop.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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/master.db.in b/bin/tests/system/inline/ns3/master.db.in
new file mode 100644
index 0000000..67e1510
--- /dev/null
+++ b/bin/tests/system/inline/ns3/master.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/master2.db.in b/bin/tests/system/inline/ns3/master2.db.in
new file mode 100644
index 0000000..1bbeb9d
--- /dev/null
+++ b/bin/tests/system/inline/ns3/master2.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/master3.db.in b/bin/tests/system/inline/ns3/master3.db.in
new file mode 100644
index 0000000..f78a950
--- /dev/null
+++ b/bin/tests/system/inline/ns3/master3.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/master4.db.in b/bin/tests/system/inline/ns3/master4.db.in
new file mode 100644
index 0000000..0dc04a9
--- /dev/null
+++ b/bin/tests/system/inline/ns3/master4.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/master5.db.in b/bin/tests/system/inline/ns3/master5.db.in
new file mode 100644
index 0000000..9bad591
--- /dev/null
+++ b/bin/tests/system/inline/ns3/master5.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/named.conf.in b/bin/tests/system/inline/ns3/named.conf.in
new file mode 100644
index 0000000..1dff0b5
--- /dev/null
+++ b/bin/tests/system/inline/ns3/named.conf.in
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+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;
+};
+
+zone "bits" {
+ type slave;
+ masters { 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 slave;
+ masters { 10.53.0.4; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update-forwarding { any; };
+ file "noixfr.bk";
+};
+
+zone "master" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "master.db";
+ notify explicit;
+ also-notify {
+ 10.53.0.3;
+ };
+};
+
+zone "dynamic" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "dynamic.db";
+};
+
+zone "updated" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { none; };
+ file "updated.db";
+};
+
+zone "expired" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "expired.db";
+};
+
+zone "retransfer" {
+ type slave;
+ masters { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "retransfer.bk";
+};
+
+zone "nsec3" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "nsec3.db";
+};
+
+zone "externalkey" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "externalkey.db";
+};
+
+zone "retransfer3" {
+ type slave;
+ masters { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "retransfer3.bk";
+};
+
+zone "inactiveksk" {
+ type slave;
+ masters { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly yes;
+ file "inactiveksk.bk";
+};
+
+zone "inactivezsk" {
+ type slave;
+ masters { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "inactivezsk.bk";
+};
+
+zone "nokeys" {
+ type slave;
+ masters { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "nokeys.bk";
+};
+
+zone "delayedkeys" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "delayedkeys.db";
+};
+
+zone "removedkeys-primary" {
+ type master;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ file "removedkeys-primary.db";
+};
+
+zone "removedkeys-secondary" {
+ type slave;
+ masters { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "removedkeys-secondary.bk";
+};
diff --git a/bin/tests/system/inline/ns3/sign.sh b/bin/tests/system/inline/ns3/sign.sh
new file mode 100755
index 0000000..735d8ea
--- /dev/null
+++ b/bin/tests/system/inline/ns3/sign.sh
@@ -0,0 +1,176 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=bits
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=master
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+$SIGNER -S -O raw -L 2000042407 -o ${zone} ${zone}.db > /dev/null 2>&1
+cp master2.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 -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -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 2>&1
+
+zone=retransfer
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -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 -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -P now -A now+3600 -f KSK $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -P now -A now+3600 $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -f KSK $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -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 -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -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 -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+
+zone=removedkeys-secondary
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+
+for s in a c d h k l m q z
+do
+ zone=test-$s
+ keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+done
+
+for s in b f i o p t v
+do
+ zone=test-$s
+ keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+ keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+done
+
+zone=externalkey
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+
+for alg in ECCGOST ECDSAP256SHA256 NSEC3RSASHA1 DSA
+do
+ case $alg in
+ DSA)
+ $SHELL ../checkdsa.sh 2> /dev/null || continue
+ checkfile=../checkdsa
+ touch $checkfile ;;
+ ECCGOST)
+ fail=0
+ $KEYGEN -q -r $RANDFILE -a eccgost test > /dev/null 2>&1 || fail=1
+ rm -f Ktest*
+ [ $fail != 0 ] && continue
+ checkfile=../checkgost
+ touch $checkfile ;;
+ ECDSAP256SHA256)
+ fail=0
+ $KEYGEN -q -r $RANDFILE -a ecdsap256sha256 test > /dev/null 2>&1 || fail=1
+ rm -f Ktest*
+ [ $fail != 0 ] && continue
+ $SHELL ../checkdsa.sh 2> /dev/null || continue
+ checkfile=../checkecdsa
+ touch $checkfile ;;
+ *) ;;
+ esac
+
+ k1=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone -f KSK $zone`
+ k2=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone $zone`
+ k3=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone $zone`
+ k4=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -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 "importkey failed: $alg"; rm -f $checkfile )
+ rm -f $k2.private
+ mv $k2.key a-file
+ $IMPORTKEY -f a-file $zone > /dev/null 2>&1 ||
+ ( echo "importkey failed: $alg"; rm -f $checkfile )
+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..c20c74e
--- /dev/null
+++ b/bin/tests/system/inline/ns4/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ notify-delay 0;
+};
+
+zone "noixfr" {
+ type master;
+ 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..c4750ca
--- /dev/null
+++ b/bin/tests/system/inline/ns4/noixfr.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2a241e5
--- /dev/null
+++ b/bin/tests/system/inline/ns5/named.conf.post
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+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 slave;
+ masters { 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..dd92ebe
--- /dev/null
+++ b/bin/tests/system/inline/ns5/named.conf.pre
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+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 slave;
+ masters { 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..dc8b5ec
--- /dev/null
+++ b/bin/tests/system/inline/ns6/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+};
+
+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..0847966
--- /dev/null
+++ b/bin/tests/system/inline/ns7/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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..9fd5553
--- /dev/null
+++ b/bin/tests/system/inline/ns7/sign.sh
@@ -0,0 +1,23 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+# 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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -f KSK $zone`
diff --git a/bin/tests/system/inline/prereq.sh b/bin/tests/system/inline/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/inline/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/inline/setup.sh b/bin/tests/system/inline/setup.sh
new file mode 100644
index 0000000..4dd4dd0
--- /dev/null
+++ b/bin/tests/system/inline/setup.sh
@@ -0,0 +1,55 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+cp ns1/root.db.in ns1/root.db
+rm -f ns1/root.db.signed
+
+touch ns2/trusted.conf
+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
+rm -f ns2/bits.db.jnl
+
+cp ns3/master.db.in ns3/master.db
+cp ns3/master.db.in ns3/dynamic.db
+cp ns3/master.db.in ns3/updated.db
+cp ns3/master.db.in ns3/expired.db
+cp ns3/master.db.in ns3/nsec3.db
+cp ns3/master.db.in ns3/externalkey.db
+cp ns3/master.db.in ns3/delayedkeys.db
+cp ns3/master.db.in ns3/removedkeys-primary.db
+
+mkdir ns3/removedkeys
+
+touch ns4/trusted.conf
+cp ns4/noixfr.db.in ns4/noixfr.db
+rm -f ns4/noixfr.db.jnl
+
+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
+
+(cd ns3; $SHELL -e sign.sh)
+(cd ns1; $SHELL -e sign.sh)
+(cd ns7; $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..997d81a
--- /dev/null
+++ b/bin/tests/system/inline/tests.sh
@@ -0,0 +1,1369 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - nsec3 > /dev/null 2>&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.`
+ test "$nsec3param" = "1 0 0 -" && break
+ sleep 1
+done
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+n=`expr $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
+expiry=`awk '$4 == "RRSIG" { print $9 }' dig.out.ns3.test$n`
+[ "$expiry" = "20110101000000" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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
+ 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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone bits
+server 10.53.0.2 ${PORT}
+update add added.bits 0 A 1.2.3.4
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking that the record is added on the hidden master ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 added.bits A > dig.out.ns2.test$n
+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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that update has been transfered 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
+ 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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone bits
+server 10.53.0.2 ${PORT}
+update add bits 0 SOA ns2.bits. . 2011072400 20 20 1814400 3600
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking YYYYMMDDVV (2011072400) serial on hidden master ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 bits SOA > dig.out.ns2.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone noixfr
+server 10.53.0.4 ${PORT}
+update add added.noixfr 0 A 1.2.3.4
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking that the record is added on the hidden master, noixfr ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.4 added.noixfr A > dig.out.ns4.test$n
+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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that update has been transfered 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
+ 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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone noixfr
+server 10.53.0.4 ${PORT}
+update add noixfr 0 SOA ns4.noixfr. . 2011072400 20 20 1814400 3600
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking YYYYMMDDVV (2011072400) serial on hidden master, noixfr ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.4 noixfr SOA > dig.out.ns4.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that the master 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 master > signing.out.test$n 2>&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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking removal of private type record via 'rndc signing -clear' (master) ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -list master > signing.out.test$n 2>&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} master > /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 master > signing.out.test$n 2>&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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking private type was properly signed (master) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 master TYPE65534 > dig.out.ns6.test$n
+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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking removal of remaining private type record via 'rndc signing -clear' (master) ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -clear all master > /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 master > signing.out.test$n 2>&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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check adding of record to unsigned master ($n)"
+ret=0
+cp ns3/master2.db.in ns3/master.db
+$RNDCCMD 10.53.0.3 reload master 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 e.master A > dig.out.ns3.test$n
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check adding record fails when SOA serial not changed ($n)"
+ret=0
+echo "c A 10.0.0.3" >> ns3/master.db
+$RNDCCMD 10.53.0.3 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+$DIG $DIGOPTS @10.53.0.3 c.master A > dig.out.ns3.test$n
+grep "NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check adding record works after updating SOA serial ($n)"
+ret=0
+cp ns3/master3.db.in ns3/master.db
+$RNDCCMD 10.53.0.3 reload master 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.master A > dig.out.ns3.test$n
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check the added record was properly signed ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 e.master A > dig.out.ns6.test$n
+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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that the dynamic master 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
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking master zone that was updated while offline is correct ($n)"
+ret=0
+serial=`$DIG $DIGOPTS +nodnssec +short @10.53.0.3 updated SOA | awk '{print $3}'`
+# 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
+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 master2.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).
+serial=`$JOURNALPRINT ns3/updated.db.signed.jnl | head -1 | awk '{print $4}'`
+[ "$serial" = "2000042408" ] || ret=1
+diffsize=`$JOURNALPRINT ns3/updated.db.signed.jnl | wc -l`
+[ "$diffsize" -le 13 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking adding of record to unsigned master using UPDATE ($n)"
+ret=0
+
+[ -f ns3/dynamic.db.jnl ] && { ret=1 ; echo_i "journal exists (pretest)" ; }
+
+$NSUPDATE << EOF
+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
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "stop bump in the wire signer server ($n)"
+ret=0
+$PERL ../stop.pl . ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "restart bump in the wire signer server ($n)"
+ret=0
+$PERL ../start.pl --noclean --restart --port ${PORT} . ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone bits
+server 10.53.0.2 ${PORT}
+update add bits 0 SOA ns2.bits. . 2011072450 20 20 1814400 3600
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking YYYYMMDDVV (2011072450) serial on hidden master ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 bits SOA > dig.out.ns2.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone noixfr
+server 10.53.0.4 ${PORT}
+update add noixfr 0 SOA ns4.noixfr. . 2011072450 20 20 1814400 3600
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking YYYYMMDDVV (2011072450) serial on hidden master, noixfr ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.4 noixfr SOA > dig.out.ns4.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone bits
+server 10.53.0.3 ${PORT}
+update add bits 0 SOA ns2.bits. . 2011072460 20 20 1814400 3600
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking forwarded update on hidden master ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 bits SOA > dig.out.ns2.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone noixfr
+server 10.53.0.3 ${PORT}
+update add noixfr 0 SOA ns4.noixfr. . 2011072460 20 20 1814400 3600
+send
+EOF
+
+n=`expr $n + 1`
+echo_i "checking forwarded update on hidden master, noixfr ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.4 noixfr SOA > dig.out.ns4.test$n
+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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+ret=0
+n=`expr $n + 1`
+echo_i "checking turning on of inline signing in a slave zone via reload ($n)"
+$DIG $DIGOPTS @10.53.0.5 +dnssec bits SOA > dig.out.ns5.test$n
+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=`expr $status + $ret`
+
+copy_setports ns5/named.conf.post ns5/named.conf
+(cd ns5; $KEYGEN -q -r $RANDFILE bits) > /dev/null 2>&1
+(cd ns5; $KEYGEN -q -r $RANDFILE -f KSK bits) > /dev/null 2>&1
+$RNDCCMD 10.53.0.5 reload 2>&1 | sed 's/^/ns5 /' | cat_i
+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
+ 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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+# allow 1 second so that file time stamps change
+sleep 1
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+ 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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+$NSUPDATE << EOF
+zone retransfer
+server 10.53.0.2 ${PORT}
+update add added.retransfer 0 A 1.2.3.4
+send
+
+EOF
+
+n=`expr $n + 1`
+echo_i "checking that the retransfer record is added on the hidden master ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 added.retransfer A > dig.out.ns2.test$n
+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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that the change has not been transfered 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
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check rndc retransfer of a inline slave 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
+ 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=`expr $status + $ret`
+
+n=`expr $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
+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
+# Wait until ns3 finishes building the NSEC3 chain for "retransfer3". There is
+# no need to immediately set ret=1 if building the NSEC3 chain is not finished
+# within the time limit because the query we will send shortly will detect any
+# problems anyway.
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $RNDCCMD 10.53.0.3 signing -list retransfer3 > signing.out.test$n.$i 2>&1
+ keys_done=`grep "Done signing" signing.out.test$n.$i | wc -l`
+ nsec3_pending=`grep "NSEC3 chain" signing.out.test$n.$i | wc -l`
+ test $keys_done -eq 2 -a $nsec3_pending -eq 0 && break
+ sleep 1
+done
+# Check whether "retransfer3" uses NSEC3 as requested.
+$DIG $DIGOPTS @10.53.0.3 nonexist.retransfer3 A > dig.out.ns3.post.test$n
+grep "status: NXDOMAIN" dig.out.ns3.post.test$n > /dev/null || ret=1
+grep "NSEC3" dig.out.ns3.post.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check rndc retransfer of a inline nsec3 slave 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
+ 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
+ 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=`expr $status + $ret`
+
+# NOTE: The test below should be considered fragile. More details can be found
+# in the comment inside ns7/named.conf.
+n=`expr $n + 1`
+echo_i "check rndc retransfer of a inline nsec3 slave does not trigger an infinite loop ($n)"
+ret=0
+zone=nsec3-loop
+# Add slave zone using rndc
+$RNDCCMD 10.53.0.7 addzone $zone \
+ '{ type slave; masters { 10.53.0.2; }; file "'$zone'.db"; inline-signing yes; auto-dnssec maintain; };'
+# Wait until slave 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
+ keys=`grep '^Done signing' signing.out.test$n | wc -l`
+ [ $keys -eq 3 ] && ret=0 && break
+ sleep 1
+done
+# Switch slave zone to NSEC3
+$RNDCCMD 10.53.0.7 signing -nsec3param 1 0 2 12345678 $zone > /dev/null 2>&1
+# Wait until slave 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`
+ test "$nsec3param" = "1 0 2 12345678" && ret=0 && break
+ sleep 1
+done
+# Attempt to retransfer the slave zone from master
+$RNDCCMD 10.53.0.7 retransfer $zone
+# 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
+ [ $? -eq 0 ] && ret=0 && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "stop bump in the wire signer server ($n)"
+ret=0
+$PERL ../stop.pl . ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "update SOA record while stopped"
+cp ns3/master4.db.in ns3/master.db
+rm ns3/master.db.jnl
+
+n=`expr $n + 1`
+echo_i "restart bump in the wire signer server ($n)"
+ret=0
+$PERL ../start.pl --noclean --restart --port ${PORT} . ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 master SOA > dig.out.ns3.test$n
+ 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=`expr $status + $ret`
+
+n=`expr $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/master.db by waiting 1 second so
+# that the master 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/master5.db.in ns3/master.db
+$RNDCCMD 10.53.0.3 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ if nextpart ns3/named.run | grep "zone master.*sending notifies" > /dev/null; then
+ ret=0
+ break
+ fi
+ sleep 1
+done
+# Sanity check: master 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 master 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=`expr $status + $ret`
+
+n=`expr $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 master; file "bits.db.in"; allow-transfer { any; }; };'
+$DIG $DIGOPTS @10.53.0.2 test-$zone SOA > dig.out.ns2.$zone.test$n
+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 slave; masters { 10.53.0.2; }; file "'test-$zone.bk'"; inline-signing yes; auto-dnssec maintain; allow-transfer { any; }; };'
+$RNDCCMD 10.53.0.3 delzone test-$zone > /dev/null 2>&1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+for alg in 3 7 12 13
+do
+ [ $alg = 3 -a ! -f checkdsa ] && continue;
+ [ $alg = 12 -a ! -f checkgost ] && continue;
+ [ $alg = 13 -a ! -f checkecdsa ] && continue;
+
+ case $alg in
+ 3) echo_i "checking DSA";;
+ 7) echo_i "checking NSEC3RSASHA1";;
+ 12) echo_i "checking GOST";;
+ 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "testing imported key won't overwrite a private key ($n)"
+ret=0
+key=`$KEYGEN -r $RANDFILE -q 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=`expr $status + $ret`
+
+n=`expr $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
+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
+sleep 1
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.ns3.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n`
+[ ${newserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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
+sleep 1
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.ns3.post.test$n
+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=`expr $status + $ret`
+
+#
+# Freezing only operates on the raw zone.
+#
+n=`expr $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
+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
+$RNDCCMD 10.53.0.3 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 thaw nsec3 > /dev/null 2>&1
+sleep 1
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.ns3.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n`
+[ ${newserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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
+sleep 1
+$DIG $DIGOPTS bits. SOA @10.53.0.2 > dig.out.ns2.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.post.test$n`
+[ ${newserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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
+sleep 1
+$DIG $DIGOPTS bits. SOA @10.53.0.2 > dig.out.ns2.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.post.test$n`
+[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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
+$RNDCCMD 10.53.0.2 signing -serial ${newserial:-0} bits > /dev/null 2>&1
+$RNDCCMD 10.53.0.2 thaw bits > /dev/null 2>&1
+sleep 1
+$DIG $DIGOPTS bits. SOA @10.53.0.2 > dig.out.ns2.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.post.test$n`
+[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+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 7 2" dig.out.ns3.test$n > /dev/null || ret=1
+grep "TXT 8 2" dig.out.ns3.test$n > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+
+#
+# check that DNSKEY is signed with ZSK for algorithm 7
+#
+awk='$4 == "DNSKEY" && $5 == 256 && $7 == 7 { print }'
+zskid=`awk "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inactiveksk | awk '{ print $4}' `
+grep "DNSKEY 7 1 [0-9]* [0-9]* [0-9]* ${zskid} " dig.out.ns3.test$n > /dev/null || ret=1
+awk='$4 == "DNSKEY" && $5 == 257 && $7 == 7 { print }'
+kskid=`awk "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inactiveksk | awk '{ print $4}' `
+grep "DNSKEY 7 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 algorithm 8
+#
+awk='$4 == "DNSKEY" && $5 == 256 && $7 == 8 { print }'
+zskid=`awk "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inactiveksk | awk '{ print $4}' `
+grep "DNSKEY 8 1 [0-9]* [0-9]* [0-9]* ${zskid} " dig.out.ns3.test$n > /dev/null && ret=1
+awk='$4 == "DNSKEY" && $5 == 257 && $7 == 8 { print }'
+kskid=`awk "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inactiveksk | awk '{ print $4}' `
+grep "DNSKEY 8 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=`expr $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 | egrep "zone ${zone}.*(sending notifies|receive_secure_serial)" > /dev/null; then
+ return
+ fi
+ sleep 1
+ done
+}
+
+n=`expr $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 master.
+$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
+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=`expr $status + $ret`
+
+n=`expr $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 master.
+$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
+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=`expr $status + $ret`
+
+n=`expr $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
+# 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
+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=`expr $status + $ret`
+
+n=`expr $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 master.
+$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
+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=`expr $status + $ret`
+
+n=`expr $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
+# 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 master.
+$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
+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=`expr $status + $ret`
+
+# Check that the master 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=`expr $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.
+ans=1
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ $RNDCCMD 10.53.0.3 signing -list delayedkeys > signing.out.test$n 2>&1
+ num=`grep "Done signing with" signing.out.test$n | wc -l`
+ if [ $num -eq 2 ]; then
+ ans=0
+ break
+ fi
+ sleep 1
+done
+if [ $ans != 0 ]; then ret=1; fi
+# Halt rather than stopping the server to prevent the master file from being
+# flushed upon shutdown since we specifically want to avoid it.
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --halt --port ${CONTROLPORT} . ns3
+ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns3
+# 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.
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --halt --port ${CONTROLPORT} . ns3
+ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns3
+# 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 master file contains no
+# DNSSEC records.
+$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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "check that zonestatus reports 'type: master' for a inline master zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 zonestatus master > rndc.out.ns3.test$n
+grep "type: master" rndc.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that zonestatus reports 'type: slave' for a inline slave zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 zonestatus bits > rndc.out.ns3.test$n
+grep "type: slave" rndc.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/integrity/clean.sh b/bin/tests/system/integrity/clean.sh
new file mode 100644
index 0000000..d9c1453
--- /dev/null
+++ b/bin/tests/system/integrity/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.test*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
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..550f985
--- /dev/null
+++ b/bin/tests/system/integrity/ns1/mx-cname.db
@@ -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 http://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..bc04332
--- /dev/null
+++ b/bin/tests/system/integrity/ns1/named.conf.in
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "mx-cname-fail" {
+ type master;
+ check-integrity yes;
+ check-mx-cname fail;
+ file "mx-cname.db";
+};
+
+zone "mx-cname-warn" {
+ type master;
+ check-integrity yes;
+ check-mx-cname warn;
+ file "mx-cname.db";
+};
+
+zone "mx-cname-ignore" {
+ type master;
+ check-integrity yes;
+ check-mx-cname ignore;
+ file "mx-cname.db";
+};
+
+zone "no-mx-cname-fail" {
+ type master;
+ check-integrity no;
+ check-mx-cname fail;
+ file "mx-cname.db";
+};
+
+zone "no-mx-cname-warn" {
+ type master;
+ check-integrity no;
+ check-mx-cname warn;
+ file "mx-cname.db";
+};
+
+zone "no-mx-cname-ignore" {
+ type master;
+ check-integrity no;
+ check-mx-cname ignore;
+ file "mx-cname.db";
+};
+
+zone "srv-cname-fail" {
+ type master;
+ check-integrity yes;
+ check-srv-cname fail;
+ file "srv-cname.db";
+};
+
+zone "srv-cname-warn" {
+ type master;
+ check-integrity yes;
+ check-srv-cname warn;
+ file "srv-cname.db";
+};
+
+zone "srv-cname-ignore" {
+ type master;
+ check-integrity yes;
+ check-srv-cname ignore;
+ file "srv-cname.db";
+};
+zone "no-srv-cname-fail" {
+ type master;
+ check-integrity no;
+ check-srv-cname fail;
+ file "srv-cname.db";
+};
+
+zone "no-srv-cname-warn" {
+ type master;
+ check-integrity no;
+ check-srv-cname warn;
+ file "srv-cname.db";
+};
+
+zone "no-srv-cname-ignore" {
+ type master;
+ 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..d0dca6c
--- /dev/null
+++ b/bin/tests/system/integrity/ns1/srv-cname.db
@@ -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 http://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..7e60631
--- /dev/null
+++ b/bin/tests/system/integrity/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..8d494d9
--- /dev/null
+++ b/bin/tests/system/integrity/tests.sh
@@ -0,0 +1,129 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+test $status -eq 0 || exit 1
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..a935a95
--- /dev/null
+++ b/bin/tests/system/ixfr/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/myftp.db
+rm -f ns3/*.jnl ns3/mytest.db ns3/subtest.db
+rm -f ns4/*.jnl ns4/*.db
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f */ans.run
+rm -f dig.out dig.out1 dig.out2 dig.out3
+rm -f ns3/large.db
+rm -f ns*/named.lock
diff --git a/bin/tests/system/ixfr/ns1/startme b/bin/tests/system/ixfr/ns1/startme
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/ixfr/ns1/startme
diff --git a/bin/tests/system/ixfr/ns3/mytest0.db b/bin/tests/system/ixfr/ns3/mytest0.db
new file mode 100644
index 0000000..b05fecc
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/mytest0.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN test.
+$TTL 15
+test. 15 IN SOA ns1.test. hostmaster.test. (
+ 1 ; serial
+ 3H ; refresh
+ 15 ; retry
+ 1w ; expire
+ 3h ; minimum
+ )
+ IN NS ns1.test.
+ IN NS ns2.test.
+ns1 IN A 10.53.0.3
+ns2 IN A 10.53.0.4
+host1 IN A 192.168.10.3
+host2 IN A 192.168.10.4
diff --git a/bin/tests/system/ixfr/ns3/mytest1.db b/bin/tests/system/ixfr/ns3/mytest1.db
new file mode 100644
index 0000000..bb9fa4b
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/mytest1.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN test.
+$TTL 15
+test. 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.
+ns1 IN A 10.53.0.3
+ns2 IN A 10.53.0.4
+host1 IN A 192.168.10.13
+host2 IN A 192.168.10.4
diff --git a/bin/tests/system/ixfr/ns3/mytest2.db b/bin/tests/system/ixfr/ns3/mytest2.db
new file mode 100644
index 0000000..1eb3c9f
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/mytest2.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN test.
+$TTL 15
+test. 15 IN SOA ns1.test. hostmaster.test. (
+ 4 ; serial
+ 3H ; refresh
+ 15 ; retry
+ 1w ; expire
+ 3h ; minimum
+ )
+ IN NS ns1.test.
+ IN NS ns2.test.
+ns1 IN A 10.53.0.3
+ns2 IN A 10.53.0.4
+host1 IN A 192.168.10.13
+host2 IN A 192.168.10.14
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..4ffb872
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "mytest.db";
+ };
+ zone "sub.test" IN {
+ type master;
+ file "subtest.db";
+ };
+ zone "large" IN {
+ type master;
+ file "large.db";
+ };
+};
diff --git a/bin/tests/system/ixfr/ns3/subtest0.db b/bin/tests/system/ixfr/ns3/subtest0.db
new file mode 100644
index 0000000..7dc1ed7
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/subtest0.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN sub.test.
+$TTL 15
+sub.test. 15 IN SOA ns1.test. hostmaster.test. (
+ 1 ; serial
+ 3H ; refresh
+ 15 ; retry
+ 1w ; expire
+ 3h ; minimum
+ )
+ IN NS ns1.test.
+ IN NS ns2.test.
+host3 IN A 192.168.10.23
+host4 IN A 192.168.10.24
diff --git a/bin/tests/system/ixfr/ns3/subtest1.db b/bin/tests/system/ixfr/ns3/subtest1.db
new file mode 100644
index 0000000..5af027a
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/subtest1.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN sub.test.
+$TTL 15
+sub.test. 15 IN SOA ns1.test. hostmaster.test. (
+ 3 ; serial
+ 3H ; refresh
+ 15 ; retry
+ 1w ; expire
+ 3h ; minimum
+ )
+ IN NS ns1.test.
+ IN NS ns2.test.
+host3 IN A 192.168.10.123
+host4 IN A 192.168.10.24
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..d3490b1
--- /dev/null
+++ b/bin/tests/system/ixfr/ns4/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 slave;
+ file "mytest.db";
+ masters { 10.53.0.3; };
+ };
+ zone "sub.test" IN {
+ type slave;
+ file "subtest.db";
+ request-ixfr no;
+ masters { 10.53.0.3; };
+ };
+};
diff --git a/bin/tests/system/ixfr/prereq.sh b/bin/tests/system/ixfr/prereq.sh
new file mode 100644
index 0000000..0e299f4
--- /dev/null
+++ b/bin/tests/system/ixfr/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo_i "This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/ixfr/setup.sh b/bin/tests/system/ixfr/setup.sh
new file mode 100644
index 0000000..21df2e6
--- /dev/null
+++ b/bin/tests/system/ixfr/setup.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+rm -f ns1/*.db ns1/*.jnl ns3/*.jnl ns4/*.db ns4/*.jnl
+
+cat <<EOF >ns1/named.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;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port ${CONTROLPORT} allow { any; } keys { rndc_key; };
+};
+EOF
+
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+# Setup initial db files for ns3
+cp ns3/mytest0.db ns3/mytest.db
+cp ns3/subtest0.db ns3/subtest.db
+$SHELL ../genzone.sh 3 > ns3/large.db
+awk 'END { for (i = 0; i < 10000; i++) printf("record%d 10 IN TXT this is record %d\n", i, i) }' < /dev/null >> ns3/large.db
diff --git a/bin/tests/system/ixfr/tests.sh b/bin/tests/system/ixfr/tests.sh
new file mode 100644
index 0000000..70c8103
--- /dev/null
+++ b/bin/tests/system/ixfr/tests.sh
@@ -0,0 +1,311 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+# 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.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+SENDCMD="$PERL ../send.pl 10.53.0.2 ${EXTRAPORT1}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf -s"
+
+echo_i "testing initial AXFR"
+
+$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 slave for nil.
+
+cat <<EOF >>ns1/named.conf
+zone "nil" {
+ type slave;
+ file "myftp.db";
+ masters { 10.53.0.2; };
+};
+EOF
+
+$RNDCCMD 10.53.0.1 reload | sed 's/^/ns1 /' | cat_i
+
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS @10.53.0.1 nil. SOA > dig.out
+ grep "SOA" dig.out > /dev/null && break
+ sleep 1
+done
+
+$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'initial AXFR' >/dev/null || {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "testing successful IXFR"
+
+# 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
+
+sleep 2
+
+$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'successful IXFR' >/dev/null || {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "testing AXFR fallback after IXFR failure"
+
+# 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
+
+sleep 2
+
+$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'fallback AXFR' >/dev/null || {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "testing ixfr-from-differences option"
+# ns3 is master; ns4 is slave
+$CHECKZONE test. ns3/mytest.db > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ echo_i "named-checkzone returned failure on ns3/mytest.db"
+fi
+# modify the master
+#echo_i "digging against master: "
+#$DIG $DIGOPTS @10.53.0.3 a host1.test.
+#echo_i "digging against slave: "
+#$DIG $DIGOPTS @10.53.0.4 a host1.test.
+
+# wait for slave to be stable
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS +tcp @10.53.0.4 SOA test > dig.out
+ grep -i "hostmaster\.test\..1" dig.out > /dev/null && break
+ sleep 1
+done
+
+# modify the master
+cp ns3/mytest1.db ns3/mytest.db
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+#wait for master to reload load
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS +tcp @10.53.0.3 SOA test > dig.out
+ grep -i "hostmaster\.test\..2" dig.out > /dev/null && break
+ sleep 1
+done
+
+#wait for slave to transfer zone
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+do
+ $DIG $DIGOPTS +tcp @10.53.0.4 SOA test > dig.out
+ grep -i "hostmaster\.test\..2" dig.out > /dev/null && break
+
+ # re-notify if we've been waiting a long time
+ if [ $i -ge 5 ]; then
+ $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i
+ fi
+ sleep 1
+done
+
+# slave should have gotten notify and updated
+
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ INCR=`grep "test/IN/primary" ns4/named.run|grep "got incremental"|wc -l`
+ [ $INCR -eq 1 ] && break
+ sleep 1
+done
+if [ $INCR -ne 1 ]
+then
+ echo_i "failed to get incremental response"
+ status=1
+fi
+
+echo_i "testing request-ixfr option in view vs zone"
+# 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
+
+echo_i " this result should be AXFR"
+cp ns3/subtest1.db ns3/subtest.db # change to sub.test zone, should be AXFR
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+#wait for master to reload zone
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS +tcp @10.53.0.3 SOA sub.test > dig.out
+ grep -i "hostmaster\.test\..3" dig.out > /dev/null && break
+ sleep 1
+done
+
+#wait for slave to transfer zone
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+do
+ $DIG $DIGOPTS +tcp @10.53.0.4 SOA sub.test > dig.out
+ grep -i "hostmaster\.test\..3" dig.out > /dev/null && break
+
+ # re-notify if we've been waiting a long time
+ if [ $i -ge 5 ]; then
+ $RNDCCMD 10.53.0.3 notify sub.test | set 's/^/ns3 /' | cat_i
+ fi
+ sleep 1
+done
+
+echo_i " this result should be AXFR"
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ NONINCR=`grep 'sub\.test/IN/primary' ns4/named.run|grep "got nonincremental" | wc -l`
+ [ $NONINCR -eq 2 ] && break
+ sleep 1
+done
+if [ $NONINCR -ne 2 ]
+then
+ echo_i "failed to get nonincremental response in 2nd AXFR test"
+ status=1
+else
+ echo_i " success: AXFR it was"
+fi
+
+echo_i " this result should be IXFR"
+cp ns3/mytest2.db ns3/mytest.db # change to test zone, should be IXFR
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+# wait for master to reload zone
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG +tcp -p 5300 @10.53.0.3 SOA test > dig.out
+ grep -i "hostmaster\.test\..4" dig.out > /dev/null && break
+ sleep 1
+done
+
+# wait for slave to transfer zone
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+do
+ $DIG $DIGOPTS +tcp @10.53.0.4 SOA test > dig.out
+ grep -i "hostmaster\.test\..4" dig.out > /dev/null && break
+
+ # re-notify if we've been waiting a long time
+ if [ $i -ge 5 ]; then
+ $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i
+ fi
+ sleep 1
+done
+
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ INCR=`grep "test/IN/primary" ns4/named.run|grep "got incremental"|wc -l`
+ [ $INCR -eq 2 ] && break
+ sleep 1
+done
+if [ $INCR -ne 2 ]
+then
+ echo_i "failed to get incremental response in 2nd IXFR test"
+ status=1
+else
+ echo_i " success: IXFR it was"
+fi
+
+echo_i "testing DiG's handling of a multi message AXFR style IXFR response"
+(
+(sleep 10 && kill $$) 2>/dev/null &
+sub=$!
+$DIG -p ${PORT} ixfr=0 large @10.53.0.3 > dig.out
+kill $sub
+)
+lines=`grep hostmaster.large dig.out | wc -l`
+test ${lines:-0} -eq 2 || { echo_i "failed"; status=1; }
+messages=`sed -n 's/^;;.*messages \([0-9]*\),.*/\1/p' dig.out`
+test ${messages:-0} -gt 1 || { echo_i "failed"; status=1; }
+
+echo_i "test 'dig +notcp ixfr=<value>' vs 'dig ixfr=<value> +notcp' vs 'dig ixfr=<value>'"
+ret=0
+# Should be "switch to TCP" response
+$DIG $DIGOPTS +notcp ixfr=1 test @10.53.0.4 > dig.out1 || ret=1
+$DIG $DIGOPTS ixfr=1 +notcp test @10.53.0.4 > dig.out2 || ret=1
+digcomp dig.out1 dig.out2 || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1 || ret=1
+awk '$4 == "SOA" { if ($7 == 4) exit(0); else exit(1);}' dig.out1 || ret=1
+# Should be incremental transfer.
+$DIG $DIGOPTS ixfr=1 test @10.53.0.4 > dig.out3 || ret=1
+awk '$4 == "SOA" { soacnt++} END { if (soacnt == 6) exit(0); else exit(1);}' dig.out3 || ret=1
+if [ ${ret} != 0 ]; then
+ echo_i "failed";
+ status=1;
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/keymgr/01-ksk-inactive/README b/bin/tests/system/keymgr/01-ksk-inactive/README
new file mode 100644
index 0000000..b91a675
--- /dev/null
+++ b/bin/tests/system/keymgr/01-ksk-inactive/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes one KSK rollover. The KSK is deactivated prior to
+its replacement being activated.
diff --git a/bin/tests/system/keymgr/01-ksk-inactive/expect b/bin/tests/system/keymgr/01-ksk-inactive/expect
new file mode 100644
index 0000000..b076310
--- /dev/null
+++ b/bin/tests/system/keymgr/01-ksk-inactive/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1h -m 2h example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/02-zsk-inactive/README b/bin/tests/system/keymgr/02-zsk-inactive/README
new file mode 100644
index 0000000..9d1e17f
--- /dev/null
+++ b/bin/tests/system/keymgr/02-zsk-inactive/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes one ZSK rollover. The first ZSK is deactivated
+prior to its replacement being activated.
diff --git a/bin/tests/system/keymgr/02-zsk-inactive/expect b/bin/tests/system/keymgr/02-zsk-inactive/expect
new file mode 100644
index 0000000..b076310
--- /dev/null
+++ b/bin/tests/system/keymgr/02-zsk-inactive/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1h -m 2h example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/03-ksk-unpublished/README b/bin/tests/system/keymgr/03-ksk-unpublished/README
new file mode 100644
index 0000000..513e9bd
--- /dev/null
+++ b/bin/tests/system/keymgr/03-ksk-unpublished/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set contains one KSK rollover. The KSK is unpublished before its
+successor is published.
diff --git a/bin/tests/system/keymgr/03-ksk-unpublished/expect b/bin/tests/system/keymgr/03-ksk-unpublished/expect
new file mode 100644
index 0000000..b076310
--- /dev/null
+++ b/bin/tests/system/keymgr/03-ksk-unpublished/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1h -m 2h example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/04-zsk-unpublished/README b/bin/tests/system/keymgr/04-zsk-unpublished/README
new file mode 100644
index 0000000..a518556
--- /dev/null
+++ b/bin/tests/system/keymgr/04-zsk-unpublished/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set contains one ZSK rollover. The ZSK is unpublished before its
+successor is published.
diff --git a/bin/tests/system/keymgr/04-zsk-unpublished/expect b/bin/tests/system/keymgr/04-zsk-unpublished/expect
new file mode 100644
index 0000000..b076310
--- /dev/null
+++ b/bin/tests/system/keymgr/04-zsk-unpublished/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1h -m 2h example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/05-ksk-unpub-active/README b/bin/tests/system/keymgr/05-ksk-unpub-active/README
new file mode 100644
index 0000000..e6a194b
--- /dev/null
+++ b/bin/tests/system/keymgr/05-ksk-unpub-active/README
@@ -0,0 +1,7 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes one KSK rollover. The first KSK is deleted
+and its successor published prior to the first KSK being deactivated
+and its successor activated.
diff --git a/bin/tests/system/keymgr/05-ksk-unpub-active/expect b/bin/tests/system/keymgr/05-ksk-unpub-active/expect
new file mode 100644
index 0000000..b076310
--- /dev/null
+++ b/bin/tests/system/keymgr/05-ksk-unpub-active/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1h -m 2h example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/06-zsk-unpub-active/README b/bin/tests/system/keymgr/06-zsk-unpub-active/README
new file mode 100644
index 0000000..e6a194b
--- /dev/null
+++ b/bin/tests/system/keymgr/06-zsk-unpub-active/README
@@ -0,0 +1,7 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes one KSK rollover. The first KSK is deleted
+and its successor published prior to the first KSK being deactivated
+and its successor activated.
diff --git a/bin/tests/system/keymgr/06-zsk-unpub-active/expect b/bin/tests/system/keymgr/06-zsk-unpub-active/expect
new file mode 100644
index 0000000..b076310
--- /dev/null
+++ b/bin/tests/system/keymgr/06-zsk-unpub-active/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1h -m 2h example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/07-ksk-ttl/README b/bin/tests/system/keymgr/07-ksk-ttl/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/07-ksk-ttl/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/07-ksk-ttl/expect b/bin/tests/system/keymgr/07-ksk-ttl/expect
new file mode 100644
index 0000000..de792a9
--- /dev/null
+++ b/bin/tests/system/keymgr/07-ksk-ttl/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/08-zsk-ttl/README b/bin/tests/system/keymgr/08-zsk-ttl/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/08-zsk-ttl/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/08-zsk-ttl/expect b/bin/tests/system/keymgr/08-zsk-ttl/expect
new file mode 100644
index 0000000..de792a9
--- /dev/null
+++ b/bin/tests/system/keymgr/08-zsk-ttl/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/09-no-keys/README b/bin/tests/system/keymgr/09-no-keys/README
new file mode 100644
index 0000000..5f4d53a
--- /dev/null
+++ b/bin/tests/system/keymgr/09-no-keys/README
@@ -0,0 +1,5 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This directory has no key set, but one will be initialized by dnssec-keymgr.
diff --git a/bin/tests/system/keymgr/09-no-keys/expect b/bin/tests/system/keymgr/09-no-keys/expect
new file mode 100644
index 0000000..de792a9
--- /dev/null
+++ b/bin/tests/system/keymgr/09-no-keys/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/10-change-roll/README b/bin/tests/system/keymgr/10-change-roll/README
new file mode 100644
index 0000000..8cf6f4e
--- /dev/null
+++ b/bin/tests/system/keymgr/10-change-roll/README
@@ -0,0 +1,7 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This directory has a key set which is valid, but has a ZSK rollover period
+of only three months. It will be updated to have a ZSK rollover period of
+one year.
diff --git a/bin/tests/system/keymgr/10-change-roll/expect b/bin/tests/system/keymgr/10-change-roll/expect
new file mode 100644
index 0000000..de792a9
--- /dev/null
+++ b/bin/tests/system/keymgr/10-change-roll/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/11-many-simul/README b/bin/tests/system/keymgr/11-many-simul/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/11-many-simul/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/11-many-simul/expect b/bin/tests/system/keymgr/11-many-simul/expect
new file mode 100644
index 0000000..de792a9
--- /dev/null
+++ b/bin/tests/system/keymgr/11-many-simul/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/12-many-active/README b/bin/tests/system/keymgr/12-many-active/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/12-many-active/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/12-many-active/expect b/bin/tests/system/keymgr/12-many-active/expect
new file mode 100644
index 0000000..f990a7a
--- /dev/null
+++ b/bin/tests/system/keymgr/12-many-active/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf -f example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/13-noroll/README b/bin/tests/system/keymgr/13-noroll/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/13-noroll/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/13-noroll/expect b/bin/tests/system/keymgr/13-noroll/expect
new file mode 100644
index 0000000..40616e1
--- /dev/null
+++ b/bin/tests/system/keymgr/13-noroll/expect
@@ -0,0 +1,9 @@
+kargs="-f -c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/14-wrongalg/README b/bin/tests/system/keymgr/14-wrongalg/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/14-wrongalg/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/14-wrongalg/expect b/bin/tests/system/keymgr/14-wrongalg/expect
new file mode 100644
index 0000000..436f05f
--- /dev/null
+++ b/bin/tests/system/keymgr/14-wrongalg/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=4
diff --git a/bin/tests/system/keymgr/15-unspec/README b/bin/tests/system/keymgr/15-unspec/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/15-unspec/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/15-unspec/expect b/bin/tests/system/keymgr/15-unspec/expect
new file mode 100644
index 0000000..b1ff4fc
--- /dev/null
+++ b/bin/tests/system/keymgr/15-unspec/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/16-wrongalg-unspec/README b/bin/tests/system/keymgr/16-wrongalg-unspec/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/16-wrongalg-unspec/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/16-wrongalg-unspec/expect b/bin/tests/system/keymgr/16-wrongalg-unspec/expect
new file mode 100644
index 0000000..7a21dec
--- /dev/null
+++ b/bin/tests/system/keymgr/16-wrongalg-unspec/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=4
diff --git a/bin/tests/system/keymgr/17-noforce/README b/bin/tests/system/keymgr/17-noforce/README
new file mode 100644
index 0000000..791b6d3
--- /dev/null
+++ b/bin/tests/system/keymgr/17-noforce/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This set includes a KSK rollover, with insufficient delay between
+prepublication and rollover.
diff --git a/bin/tests/system/keymgr/17-noforce/expect b/bin/tests/system/keymgr/17-noforce/expect
new file mode 100644
index 0000000..a5bf1f1
--- /dev/null
+++ b/bin/tests/system/keymgr/17-noforce/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=1
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/18-nonstd-prepub/README b/bin/tests/system/keymgr/18-nonstd-prepub/README
new file mode 100644
index 0000000..fc1aaca
--- /dev/null
+++ b/bin/tests/system/keymgr/18-nonstd-prepub/README
@@ -0,0 +1,7 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This directory has a key set which is valid, but will expire within
+the rollover period. The prepublication interval in policy.conf is a
+nonstandard value.
diff --git a/bin/tests/system/keymgr/18-nonstd-prepub/expect b/bin/tests/system/keymgr/18-nonstd-prepub/expect
new file mode 100644
index 0000000..de792a9
--- /dev/null
+++ b/bin/tests/system/keymgr/18-nonstd-prepub/expect
@@ -0,0 +1,9 @@
+kargs="-c policy.conf example.com"
+kmatch=""
+kret=0
+cargs="-d 1w -m 2w example.com"
+cmatch=""
+cret=0
+warn=0
+error=0
+ok=2
diff --git a/bin/tests/system/keymgr/18-nonstd-prepub/policy.conf b/bin/tests/system/keymgr/18-nonstd-prepub/policy.conf
new file mode 100644
index 0000000..91817ff
--- /dev/null
+++ b/bin/tests/system/keymgr/18-nonstd-prepub/policy.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+policy default {
+ policy global;
+ algorithm nsec3rsasha1;
+ pre-publish zsk 2w;
+ roll-period zsk 6mo;
+ coverage 364d;
+};
diff --git a/bin/tests/system/keymgr/clean.sh b/bin/tests/system/keymgr/clean.sh
new file mode 100644
index 0000000..dc9f0a0
--- /dev/null
+++ b/bin/tests/system/keymgr/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K*.key
+rm -f */K*.private
+rm -f coverage.* keymgr.*
+rm -f policy.out
diff --git a/bin/tests/system/keymgr/policy.conf b/bin/tests/system/keymgr/policy.conf
new file mode 100644
index 0000000..4da487a
--- /dev/null
+++ b/bin/tests/system/keymgr/policy.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+policy default {
+ policy global;
+ algorithm nsec3rsasha1;
+ key-size zsk 1024;
+ pre-publish zsk 6w;
+ post-publish zsk 6w;
+ roll-period zsk 6mo;
+ roll-period ksk 0;
+ coverage 364d;
+};
diff --git a/bin/tests/system/keymgr/policy.good b/bin/tests/system/keymgr/policy.good
new file mode 100644
index 0000000..95af940
--- /dev/null
+++ b/bin/tests/system/keymgr/policy.good
@@ -0,0 +1,170 @@
+policy default:
+ inherits global
+ directory None
+ algorithm None
+ coverage None
+ ksk_keysize None
+ zsk_keysize None
+ ksk_rollperiod None
+ zsk_rollperiod None
+ ksk_prepublish None
+ ksk_postpublish None
+ zsk_prepublish None
+ zsk_postpublish None
+ ksk_standby None
+ zsk_standby None
+ keyttl None
+
+policy global:
+ inherits None
+ directory None
+ algorithm RSASHA256
+ coverage 15552000
+ ksk_keysize 2048
+ zsk_keysize 2048
+ ksk_rollperiod None
+ zsk_rollperiod 31536000
+ ksk_prepublish 2592000
+ ksk_postpublish 2592000
+ zsk_prepublish 2592000
+ zsk_postpublish 2592000
+ ksk_standby None
+ zsk_standby None
+ keyttl 3600
+
+constructed policy example.com:
+ inherits global
+ directory None
+ algorithm RSASHA256
+ coverage 15552000
+ ksk_keysize 2048
+ zsk_keysize 2048
+ ksk_rollperiod None
+ zsk_rollperiod 31536000
+ ksk_prepublish 2592000
+ ksk_postpublish 2592000
+ zsk_prepublish 2592000
+ zsk_postpublish 2592000
+ ksk_standby None
+ zsk_standby None
+ keyttl 3600
+
+policy default:
+ inherits None
+ directory "keydir"
+ algorithm RSASHA1
+ coverage 31536000
+ ksk_keysize None
+ zsk_keysize None
+ ksk_rollperiod None
+ zsk_rollperiod 15552000
+ ksk_prepublish None
+ ksk_postpublish None
+ zsk_prepublish 3628800
+ zsk_postpublish 3628800
+ ksk_standby None
+ zsk_standby None
+ keyttl 3600
+
+zone policy example.com:
+ inherits extra
+ directory "keydir"
+ algorithm NSEC3RSASHA1
+ coverage 12960000
+ ksk_keysize 2048
+ zsk_keysize 2048
+ ksk_rollperiod 31536000
+ zsk_rollperiod 7776000
+ ksk_prepublish 7776000
+ ksk_postpublish None
+ zsk_prepublish 3628800
+ zsk_postpublish 604800
+ ksk_standby None
+ zsk_standby None
+ keyttl 7200
+
+constructed policy example.org:
+ inherits None
+ directory "keydir"
+ algorithm RSASHA1
+ coverage 31536000
+ ksk_keysize 2048
+ zsk_keysize 1024
+ ksk_rollperiod None
+ zsk_rollperiod 15552000
+ ksk_prepublish None
+ ksk_postpublish None
+ zsk_prepublish 3628800
+ zsk_postpublish 3628800
+ ksk_standby None
+ zsk_standby None
+ keyttl 3600
+
+constructed policy example.net:
+ inherits None
+ directory "keydir"
+ algorithm RSASHA1
+ coverage 31536000
+ ksk_keysize 2048
+ zsk_keysize 1024
+ ksk_rollperiod None
+ zsk_rollperiod 15552000
+ ksk_prepublish None
+ ksk_postpublish None
+ zsk_prepublish 3628800
+ zsk_postpublish 3628800
+ ksk_standby None
+ zsk_standby None
+ keyttl 3600
+
+algorithm policy RSASHA1:
+ inherits None
+ directory None
+ algorithm None
+ coverage None
+ ksk_keysize 2048
+ zsk_keysize 1024
+ ksk_rollperiod None
+ zsk_rollperiod None
+ ksk_prepublish None
+ ksk_postpublish None
+ zsk_prepublish None
+ zsk_postpublish None
+ ksk_standby None
+ zsk_standby None
+ keyttl None
+
+algorithm policy DSA:
+ inherits None
+ directory None
+ algorithm DSA
+ coverage None
+ ksk_keysize 1024
+ zsk_keysize 2048
+ ksk_rollperiod None
+ zsk_rollperiod None
+ ksk_prepublish None
+ ksk_postpublish None
+ zsk_prepublish None
+ zsk_postpublish None
+ ksk_standby None
+ zsk_standby None
+ keyttl None
+
+policy extra:
+ inherits default
+ directory None
+ algorithm None
+ coverage 157680000
+ ksk_keysize None
+ zsk_keysize None
+ ksk_rollperiod 31536000
+ zsk_rollperiod 7776000
+ ksk_prepublish 7776000
+ ksk_postpublish None
+ zsk_prepublish None
+ zsk_postpublish 604800
+ ksk_standby None
+ zsk_standby None
+ keyttl 7200
+
diff --git a/bin/tests/system/keymgr/policy.sample b/bin/tests/system/keymgr/policy.sample
new file mode 100644
index 0000000..4594091
--- /dev/null
+++ b/bin/tests/system/keymgr/policy.sample
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# a comment which should be skipped
+
+algorithm-policy rsasha1 {
+ key-size ksk 2048;
+ key-size zsk 1024; // this too
+};
+
+// and this
+
+policy default {
+ directory "keydir";
+ algorithm rsasha1;
+ coverage 1y; # another comment
+ roll-period zsk 6mo; // and yet another
+ pre-publish zsk 6w;
+ post-publish zsk 6w;
+ keyttl 1h;
+};
+
+policy extra {
+ policy default;
+ coverage 5y;
+ roll-period KSK 1 year;
+ roll-period zsk 3mo;
+ pre-publish ksk 3mo;
+ post-publish zsk 1w;
+ keyttl 2h;
+};
+
+/*
+ * and this is also a comment,
+ * and it should be ignored like
+ * the others.
+ */
+
+zone example.com {
+ policy extra;
+ coverage 5 mon;
+ algorithm nsec3rsasha1;
+};
+
+/*
+ * This confirms that zones starting with digits are accepted.
+ */
+zone "99example.com" {
+ policy global;
+};
diff --git a/bin/tests/system/keymgr/prereq.sh b/bin/tests/system/keymgr/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/keymgr/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/keymgr/setup.sh b/bin/tests/system/keymgr/setup.sh
new file mode 100644
index 0000000..24e6c7c
--- /dev/null
+++ b/bin/tests/system/keymgr/setup.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+KEYGEN="$KEYGEN -qr $RANDFILE"
+
+$SHELL clean.sh
+
+# Test 1: KSK goes inactive before successor is active
+dir=01-ksk-inactive
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -I +7mo $ksk1 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 2: ZSK goes inactive before successor is active
+dir=02-zsk-inactive
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -I +7mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 3: KSK is unpublished before its successor is published
+dir=03-ksk-unpublished
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -D +6mo $ksk1 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 4: ZSK is unpublished before its successor is published
+dir=04-zsk-unpublished
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -D +6mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 5: KSK deleted and successor published before KSK is deactivated
+# and successor activated.
+dir=05-ksk-unpub-active
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +8mo $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 6: ZSK deleted and successor published before ZSK is deactivated
+# and successor activated.
+dir=06-zsk-unpub-active
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +8mo $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 7: KSK rolled with insufficient delay after prepublication.
+dir=07-ksk-ttl
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -P +269d $ksk2 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 8: ZSK rolled with insufficient delay after prepublication.
+dir=08-zsk-ttl
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+# allow only 1 day between publication and activation
+$SETTIME -K $dir -P +269d $zsk2 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 9: No special preparation needed
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+
+# Test 10: Valid key set, but rollover period has changed
+dir=10-change-roll
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +3mo -D +4mo $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+
+# Test 11: Many keys all simultaneously scheduled to be active in the future
+dir=11-many-simul
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -q3fk -P now+1mo -A now+1mo example.com`
+z1=`$KEYGEN -K $dir -q3 -P now+1mo -A now+1mo example.com`
+z2=`$KEYGEN -K $dir -q3 -P now+1mo -A now+1mo example.com`
+z3=`$KEYGEN -K $dir -q3 -P now+1mo -A now+1mo example.com`
+z4=`$KEYGEN -K $dir -q3 -P now+1mo -A now+1mo example.com`
+
+# Test 12: Many keys all simultaneously scheduled to be active in the past
+dir=12-many-active
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -q3fk example.com`
+z1=`$KEYGEN -K $dir -q3 example.com`
+z2=`$KEYGEN -K $dir -q3 example.com`
+z3=`$KEYGEN -K $dir -q3 example.com`
+z4=`$KEYGEN -K $dir -q3 example.com`
+
+# Test 13: Multiple simultaneous keys with no configured roll period
+dir=13-noroll
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -q3fk example.com`
+k2=`$KEYGEN -K $dir -q3fk example.com`
+k3=`$KEYGEN -K $dir -q3fk example.com`
+z1=`$KEYGEN -K $dir -q3 example.com`
+
+# Test 14: Keys exist but have the wrong algorithm
+dir=14-wrongalg
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -qfk example.com`
+z1=`$KEYGEN -K $dir -q example.com`
+$SETTIME -K $dir -I now+6mo -D now+8mo $z1 > /dev/null
+z2=`$KEYGEN -K $dir -q -S ${z1}.key`
+$SETTIME -K $dir -I now+1y -D now+14mo $z2 > /dev/null
+z3=`$KEYGEN -K $dir -q -S ${z2}.key`
+$SETTIME -K $dir -I now+18mo -D now+20mo $z3 > /dev/null
+z4=`$KEYGEN -K $dir -q -S ${z3}.key`
+
+# Test 15: No zones specified; just search the directory for keys
+dir=15-unspec
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -q3fk example.com`
+z1=`$KEYGEN -K $dir -q3 example.com`
+$SETTIME -K $dir -I now+6mo -D now+8mo $z1 > /dev/null
+z2=`$KEYGEN -K $dir -q -S ${z1}.key`
+$SETTIME -K $dir -I now+1y -D now+14mo $z2 > /dev/null
+z3=`$KEYGEN -K $dir -q -S ${z2}.key`
+$SETTIME -K $dir -I now+18mo -D now+20mo $z3 > /dev/null
+z4=`$KEYGEN -K $dir -q -S ${z3}.key`
+
+# Test 16: No zones specified; search the directory for keys;
+# keys have the wrong algorithm for their policies
+dir=16-wrongalg-unspec
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -qfk example.com`
+z1=`$KEYGEN -K $dir -q example.com`
+$SETTIME -K $dir -I now+6mo -D now+8mo $z1 > /dev/null
+z2=`$KEYGEN -K $dir -q -S ${z1}.key`
+$SETTIME -K $dir -I now+1y -D now+14mo $z2 > /dev/null
+z3=`$KEYGEN -K $dir -q -S ${z2}.key`
+$SETTIME -K $dir -I now+18mo -D now+20mo $z3 > /dev/null
+z4=`$KEYGEN -K $dir -q -S ${z3}.key`
+
+# Test 17: Keys are simultaneously active but we run with no force
+# flag (this should fail)
+dir=17-noforce
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+k1=`$KEYGEN -K $dir -q3fk example.com`
+z1=`$KEYGEN -K $dir -q3 example.com`
+z2=`$KEYGEN -K $dir -q3 example.com`
+z3=`$KEYGEN -K $dir -q3 example.com`
+z4=`$KEYGEN -K $dir -q3 example.com`
+
+# Test 18: Prepublication interval is set to a nonstandard value
+dir=18-nonstd-prepub
+echo_i "set up $dir"
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I now+2mo -D now+3mo $zsk1 > /dev/null
diff --git a/bin/tests/system/keymgr/testpolicy.py b/bin/tests/system/keymgr/testpolicy.py
new file mode 100644
index 0000000..e9125cf
--- /dev/null
+++ b/bin/tests/system/keymgr/testpolicy.py
@@ -0,0 +1,39 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import sys
+sys.path.insert(0, '../../../python')
+from isc import *
+
+pp = policy.dnssec_policy()
+# print the unmodified default and a generated zone policy
+print(pp.named_policy['default'])
+print(pp.named_policy['global'])
+print(pp.policy('example.com'))
+
+if len(sys.argv) > 0:
+ for policy_file in sys.argv[1:]:
+ pp.load(policy_file)
+
+ # now print the modified default and generated zone policies
+ print(pp.named_policy['default'])
+ print(pp.policy('example.com'))
+ print(pp.policy('example.org'))
+ print(pp.policy('example.net'))
+
+ # print algorithm policies
+ print(pp.alg_policy['RSASHA1'])
+ print(pp.alg_policy['DSA'])
+
+ # print another named policy
+ print(pp.named_policy['extra'])
+else:
+ print("ERROR: Please provide an input file")
diff --git a/bin/tests/system/keymgr/tests.sh b/bin/tests/system/keymgr/tests.sh
new file mode 100644
index 0000000..88b43d9
--- /dev/null
+++ b/bin/tests/system/keymgr/tests.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+matchall () {
+ file=$1
+ echo "$2" | while read matchline; do
+ grep "$matchline" $file > /dev/null 2>&1 || {
+ echo "FAIL"
+ return
+ }
+ done
+}
+
+echo_i "checking for DNSSEC key coverage issues"
+ret=0
+for dir in [0-9][0-9]-*; do
+ ret=0
+ echo_i "$dir ($n)"
+ kargs= cargs= kmatch= cmatch= kret= cret=0 warn= error= ok=
+ . $dir/expect
+
+ # use policy.conf if available
+ policy=""
+ [ -e "$dir/policy.conf" ] && policy="-c $dir/policy.conf"
+ # run keymgr to update keys
+ if [ "$CYGWIN" ]; then
+ $KEYMGR $policy -K $dir -g `cygpath -w $KEYGEN` -r $RANDFILE \
+ -s `cygpath -w $SETTIME` $kargs > keymgr.$n 2>&1
+ else
+ $KEYMGR $policy -K $dir -g $KEYGEN -r $RANDFILE \
+ -s $SETTIME $kargs > keymgr.$n 2>&1
+ fi
+ # check that return code matches expectations
+ found=$?
+ if [ $found -ne $kret ]; then
+ echo "keymgr retcode was $found expected $kret"
+ ret=1
+ fi
+
+ found=`matchall keymgr.$n "$kmatch"`
+ if [ "$found" = "FAIL" ]; then
+ echo "no match on '$kmatch'"
+ ret=1
+ fi
+
+ # now check coverage
+ $COVERAGE -K $dir $cargs > coverage.$n 2>&1
+ # check that return code matches expectations
+ found=$?
+ if [ $found -ne $cret ]; then
+ echo "coverage retcode was $found expected $cret"
+ ret=1
+ fi
+
+ # check for correct number of errors
+ found=`grep ERROR coverage.$n | wc -l`
+ if [ $found -ne $error ]; then
+ echo "error count was $found expected $error"
+ ret=1
+ fi
+
+ # check for correct number of warnings
+ found=`grep WARNING coverage.$n | wc -l`
+ if [ $found -ne $warn ]; then
+ echo "warning count was $found expected $warn"
+ ret=1
+ fi
+
+ # check for correct number of OKs
+ found=`grep "No errors found" coverage.$n | wc -l`
+ if [ $found -ne $ok ]; then
+ echo "good count was $found expected $ok"
+ ret=1
+ fi
+
+ found=`matchall coverage.$n "$cmatch"`
+ if [ "$found" = "FAIL" ]; then
+ echo "no match on '$cmatch'"
+ ret=1
+ fi
+
+ n=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+done
+
+echo_i "checking policy.conf parser ($n)"
+ret=0
+${PYTHON} testpolicy.py policy.sample > policy.out
+$DOS2UNIX policy.out > /dev/null
+cmp -s policy.good policy.out || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/legacy/build.sh b/bin/tests/system/legacy/build.sh
new file mode 100644
index 0000000..bc3fcf1
--- /dev/null
+++ b/bin/tests/system/legacy/build.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+$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..50237dc
--- /dev/null
+++ b/bin/tests/system/legacy/clean.sh
@@ -0,0 +1,25 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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 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
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..c5833a4
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/named1.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {
+ type master;
+ 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..e3edb02
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/named2.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {
+ type master;
+ 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..78ae65b
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/root.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
diff --git a/bin/tests/system/legacy/ns1/trusted.conf b/bin/tests/system/legacy/ns1/trusted.conf
new file mode 100644
index 0000000..0727543
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/trusted.conf
@@ -0,0 +1,3 @@
+trusted-keys {
+ "edns512-notcp." 257 3 10 "AwEAAcEBkn/cuVhdRTWMHt19O7h9F4Hx2t68u1JUZg7swLLvwfljqnNYjsKYk9EzUhIaYOAHtVe7//cYwoVU4BFhY2DGbx1YE1LnKIGxfqpopFxDZC34TTl6jpoTP6kvj+XpeO0HfF2+DcyNgnQcMGgHXyLWeRUJFt1As6o9tmsBiInGIZMTE3/rANhtAGMLNzhRLN7CS/Tc5GhKaL66uebyEYenEOAyDVgsuhr8Q9D5ka6xZmxzXFVswy2KvsSxu9aoxVq4nACjIeTZ4GJy0v83zclV7hA+5jlPDXMFtIpvwux5XALrNkUUPq+Fb5sc5/u141LcvdASnlk58I77HbsnfausvDxdYYxEns7K9e9N85dwyreM/OGTmm8p4hNDngZESAea7MrSCsJpOGn9XLkVe6gZnBgB1cra+ezzTSWn+4QH17lIhFXYNjMV83df2h/gH3Gmthqnr9RgknZga8B/Czc7TeX6iy2gAOshKGyb6w12eJim1L8tS5T138V8d6SigzxZz1raiJNolVhXyA8SbbDpgBrcoEXN/WjwvWI+2ol5gzlqMeNw/F9SMoWdpGIWkkNCNWBbhLWhp6qfhpRLUFwVys54LGOIGSVRd9uJmc2hPdXoP8ephnCIeNJb8Zp6DnpssyN0JaF815dKkOHff9GEjaiRLj0xWvtZSqNFaGoB";
+};
diff --git a/bin/tests/system/legacy/ns2/dropedns.db b/bin/tests/system/legacy/ns2/dropedns.db
new file mode 100644
index 0000000..3bf81cd
--- /dev/null
+++ b/bin/tests/system/legacy/ns2/dropedns.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..552227d
--- /dev/null
+++ b/bin/tests/system/legacy/ns2/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+zone "dropedns" {
+ type master;
+ 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..40f5e11
--- /dev/null
+++ b/bin/tests/system/legacy/ns3/dropedns-notcp.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..8d10f93
--- /dev/null
+++ b/bin/tests/system/legacy/ns3/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "dropedns-notcp" {
+ type master;
+ 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..3c5fde6
--- /dev/null
+++ b/bin/tests/system/legacy/ns4/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -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..91c1203
--- /dev/null
+++ b/bin/tests/system/legacy/ns4/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "plain" {
+ type master;
+ 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..fd5be9f
--- /dev/null
+++ b/bin/tests/system/legacy/ns4/plain.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..3c5fde6
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -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..2cb4af4
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "plain-notcp" {
+ type master;
+ 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..51c9e10
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/plain-notcp.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..6da723f
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/edns512.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.6
+txt500 60 TXT ( "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789" )
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..1493dd8
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/edns512.db.signed
@@ -0,0 +1,248 @@
+; File written on Fri Dec 5 16:35:57 2014
+; dnssec_signzone version 9.11.0pre-alpha
+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 (
+ 20441127043557 20141205043557 59033 edns512.
+ Xqas69NmX1N9jXSQntGXjcDTmZpO542fJURc
+ peYqY2gD445jxcH6FwmdMbzyPX4Nel+ZKdqx
+ wzb6U4S2sc7V1Wt8sOuNWil3LOaF9Mr2ZhL9
+ /BgFaZixYdij0dFkUyuaSRfDx+3rvYtGZBRW
+ w55/U2bRvIgk0TjH+XHOUM+l5n755bsH1GFP
+ kRxhsYtsrUdWrB7Wn5lOdURsIf31xUfuMejR
+ QO5UIeqIgLhqE67GTy4SkfJW01G97Fkmt9Kx
+ 6K1gIwOeJy2rHN9WIF9vLJ2nyxWiSkmUka7l
+ Zw3kuR9fjgrFE8FEy4e/J8VIoq0v9bnwLh8a
+ woBnoQoZcfngu56e5hyF+g4t91JDbViOMAcJ
+ /DWsaGa7IF0o61Z51XoOakpgV4TP3VU53jFr
+ gfc4HDKP3sQQH9ZqzOpkXtoWGpSQ+u+2jSYu
+ NKa05LW4q1SJf8DHTiMxAUkkbikGHemskgIm
+ 0MESkBJI95/M3FbsRc9FswOeX0ZaRo3+6982
+ elE1T0ZVPOWjPq1L5upWvUZDP0/d+2ns7Yt/
+ MY5dKXjl74kQWTIDdeUC/8aaWFiJhsx7Haa1
+ LhHtttBHtQQKQBo8uWVoTHDs9XY7pDcpkF6Z
+ /NzaCOVHFKh4Ahpr9xwY1J9Cy56oRIq5AEP9
+ HmtN1vS04jbad220C+jfkDPJH9s64MKggQ4= )
+ 60 NS ns.edns512.
+ 60 RRSIG NS 10 1 60 (
+ 20441127043557 20141205043557 59033 edns512.
+ G9qrHjBQZ+jcueOhibtN18rXYEaLzWOZh1o2
+ ZRQ9jS59BJd0KJ4taQzpz4CxA/juqEjSCmuY
+ Vynfeg15u4wvUf1/anC38Rp/QG0MHPrFily0
+ DzeS/o2plYNCJ8r2wOmufG34rZakXZs2EdBf
+ 9s3+f+vqx+WsIs1TfaayGi90qDxVjn/SKGqb
+ v/eXGmYxyRMTaQ2x0+8y018MT+7zLbb3/VvV
+ EuD8X+J8N8dZiw3Rc1X6zj3usSOEO6wa4GRk
+ Oss3CMkYJuMND/3RG6XGt6du4hl3lK3+UK/4
+ bb/D5FBlCJc76bkmo8ZmUjxKGXXGzh9w+bMT
+ rt0GfabUcbQyWyOifIsWOeIxYVpvUHusk7VT
+ gvvhfqXabGT7pPoCPz97IW820qTXKPPX/Rzb
+ DpRgWdVdQDWcmhb4RBDQrr1DDMmBJlz91S4Q
+ 0lDAnSMfMO2JIpJKOFNHnsMgLayEvdKOKQOH
+ ESKzbylxL4qARAq4zYbwz3vY6VDCV5MGcnAT
+ 3XMNM9RwRq0/qMuE8XfPmRaDimIOLaEojMpU
+ 59sFvaKzvn7t1h1ZQVLuJqu3jkWwz4iUtwts
+ +av/IdbbKP6spPy4gimngRWbpiiQHESNx9kp
+ EHB85/UAR28RffvPadNoQq1eaAOQJCEJf7xv
+ BOGytbBxrLFsTWrmrB5uCb9hujWu04unJyc= )
+ 0 NSEC ns.edns512. NS SOA RRSIG NSEC DNSKEY
+ 0 RRSIG NSEC 10 1 0 (
+ 20441127043557 20141205043557 59033 edns512.
+ BY9hQLrs9zkekTWeXmSqT+8dCZ+vaRBGSSUf
+ E8BUr4gYbuzo7xeOpHjMkpO7IpkT80TRcIQf
+ AkleOlf3+XcUIhK9/7C/xu0/jI3XbaBs5NNJ
+ 0zhf0CmJBzeCSMtxXInDLGkhGMgoclB3j5+f
+ nme65PHYFVEVWS/64ZRd71XUUV2kTk4slfqx
+ YNGhT7IPcgUTNOrsBGi6SmH2iKMseg2BfFOt
+ +2RRY9HBlfKywozHz9jjWsEmRZke3fqfpuln
+ C6r3EQ873XBjrsOrDerNaSDf29Zl46SQs3UQ
+ kCJZ0gWEReRvvooLlh4+PsbIW1M0FMmsImfv
+ l1kPh8kQgJVxljba7kXX3k5bc/YwTQE3rI6e
+ ametdxSwbxcUZiUr8rM2ZF4IfqFGS05sD+Cz
+ 68dDDyR/vu+6Rt/U+39bzg2tI4Ok6aQxOgXP
+ v+hhOC8Sancpmn+SHLQvYoMW/VxR633TeyW3
+ zn4Xhcp7aD4TdKHGK9PpVrtWcx50zZEXu17c
+ essPk0yDOarTmoqx0r3LSe5jjDLJJ5kZxWxM
+ nlfkw3aKQwQMuyaVWN+Ruz7KRgD9lkwoOic4
+ Qs/7PYpMrV58YVlEa7aESd3+qPHjv6dD99Zm
+ Fe6bc+SqUTKwjeYfIm/luc70FpykGhdxTK/E
+ dEjQJ8jMrAzCCr/or/JOHgV1yrTCfU3hAN8= )
+ 60 DNSKEY 256 3 10 (
+ AwEAAcEBkn/cuVhdRTWMHt19O7h9F4Hx2t68
+ u1JUZg7swLLvwfljqnNYjsKYk9EzUhIaYOAH
+ tVe7//cYwoVU4BFhY2DGbx1YE1LnKIGxfqpo
+ pFxDZC34TTl6jpoTP6kvj+XpeO0HfF2+DcyN
+ gnQcMGgHXyLWeRUJFt1As6o9tmsBiInGIZMT
+ E3/rANhtAGMLNzhRLN7CS/Tc5GhKaL66ueby
+ EYenEOAyDVgsuhr8Q9D5ka6xZmxzXFVswy2K
+ vsSxu9aoxVq4nACjIeTZ4GJy0v83zclV7hA+
+ 5jlPDXMFtIpvwux5XALrNkUUPq+Fb5sc5/u1
+ 41LcvdASnlk58I77HbsnfausvDxdYYxEns7K
+ 9e9N85dwyreM/OGTmm8p4hNDngZESAea7MrS
+ CsJpOGn9XLkVe6gZnBgB1cra+ezzTSWn+4QH
+ 17lIhFXYNjMV83df2h/gH3Gmthqnr9RgknZg
+ a8B/Czc7TeX6iy2gAOshKGyb6w12eJim1L8t
+ S5T138V8d6SigzxZz1raiJNolVhXyA8SbbDp
+ gBrcoEXN/WjwvWI+2ol5gzlqMeNw/F9SMoWd
+ pGIWkkNCNWBbhLWhp6qfhpRLUFwVys54LGOI
+ GSVRd9uJmc2hPdXoP8ephnCIeNJb8Zp6Dnps
+ syN0JaF815dKkOHff9GEjaiRLj0xWvtZSqNF
+ aGoB
+ ) ; ZSK; alg = RSASHA512; key id = 59033
+ 60 DNSKEY 257 3 10 (
+ AwEAAcEBkn/cuVhdRTWMHt19O7h9F4Hx2t68
+ u1JUZg7swLLvwfljqnNYjsKYk9EzUhIaYOAH
+ tVe7//cYwoVU4BFhY2DGbx1YE1LnKIGxfqpo
+ pFxDZC34TTl6jpoTP6kvj+XpeO0HfF2+DcyN
+ gnQcMGgHXyLWeRUJFt1As6o9tmsBiInGIZMT
+ E3/rANhtAGMLNzhRLN7CS/Tc5GhKaL66ueby
+ EYenEOAyDVgsuhr8Q9D5ka6xZmxzXFVswy2K
+ vsSxu9aoxVq4nACjIeTZ4GJy0v83zclV7hA+
+ 5jlPDXMFtIpvwux5XALrNkUUPq+Fb5sc5/u1
+ 41LcvdASnlk58I77HbsnfausvDxdYYxEns7K
+ 9e9N85dwyreM/OGTmm8p4hNDngZESAea7MrS
+ CsJpOGn9XLkVe6gZnBgB1cra+ezzTSWn+4QH
+ 17lIhFXYNjMV83df2h/gH3Gmthqnr9RgknZg
+ a8B/Czc7TeX6iy2gAOshKGyb6w12eJim1L8t
+ S5T138V8d6SigzxZz1raiJNolVhXyA8SbbDp
+ gBrcoEXN/WjwvWI+2ol5gzlqMeNw/F9SMoWd
+ pGIWkkNCNWBbhLWhp6qfhpRLUFwVys54LGOI
+ GSVRd9uJmc2hPdXoP8ephnCIeNJb8Zp6Dnps
+ syN0JaF815dKkOHff9GEjaiRLj0xWvtZSqNF
+ aGoB
+ ) ; KSK; alg = RSASHA512; key id = 59034
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20441127043557 20141205043557 59033 edns512.
+ QYXBCtuqzY2R7s4sIDFmSkhLqXXYAAdm5T3x
+ MddwlppybV0tEnkRdgWD+3VL2PAdr+MMFigm
+ OCohMdYAXOhJwW9OHiSkeIpYamojB+eBPDBl
+ 63guu73QADTUmffZirWvNb79reVHmKkTPdLm
+ nEfEs7VEtTm1Wj60jT1q1RIkJDvtIo7mJgRO
+ MYKyJBCocBUSGGXoHCA+djXCqKiuLavQ2rBu
+ IGxXtB2Pf2Wkw/9xxhBo5vTrT1u+V2hFGMPO
+ vnODw0lU4XiSjeBrmMXnadrsx8DrM4KInwAL
+ A9VolAXXWjqvD3il54ziqikkjTYnOeyik3QM
+ R7UtDrLTLnAeyeL9rhLuBk2dnsE+XaJ2PP3q
+ iD7LiEQLDGGKJRC3P6odVb17e7q0mDtH2HId
+ VdjGap+W6mxql8aVrRHs5P0t/5GJmW83JbJi
+ e7W3Y1ikoimB4S6FPBbjadaUEpzUs806SIdj
+ v/AZoydoa/qOdre9Pur51At2dQNgeFhIL9w+
+ 2IcN3pRjojTPrMToqVRqOySzx6OzvSmnydDg
+ PMe4yoqpzumJLQXJ2IceEg5rlLaRjMOBYSW8
+ VuqLMfEup+KBEg+nZv6mAmx1KLuIgO5q5ae9
+ tq0I7eaV/EPvBYxO7j2RA0AbtmGSUyP4ZzTy
+ FjIYfOqzwwPjONzLQ2E/RsbS5MlIAk92aC0= )
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20441127043557 20141205043557 59034 edns512.
+ V13nqWSVWVdkN/RZnJ+4ywjju3JoRbQrpnjL
+ RKPi4U8cOc1nnh64y4RvaIe+2TI1hiVKYHfE
+ 9XGXZb2zhxrWMq8kLjpIRN+jpItoFXu7rSRA
+ GmiHz7v7PW7+UHz7fhGHKJuqQuodBokTlHhR
+ /0mNkaDQ96OOyG/aLOfj6Jj16KEBfyM8hALy
+ jwWE8EOKzV37CLBWawazXVY/EAP5jzQuAaot
+ SPh3wFuJ2L6rB4lkh5IwaeXU42ip7eirT2i5
+ V9W2v01UWbQ3Jab1DJlNwVgNGzXYvCvLU9zG
+ EHbqVcDuMErOqFzePLhK7Aqh8LIB9DnQlFqE
+ 2tyATJb0hcMetMNRiInJFGPMekdNiTguhLMC
+ GyEjzEJdiKT0XA/lVF9MVyEqL2HeSj3NYRe6
+ ScfqAZArEPgu+UI0CaiC2eR8KdQCPcwUJuNE
+ mNdv3F9CnNvq3w72Q3TJpOaFzuToQh8JleTN
+ Ty3zRkVGKWSDNs+px9sedJkRpaRyVQVXJruT
+ /boYT8HgK8R6PXIp3Ujud0SSlVjPQrlbxF/P
+ 5saDwruBkYPRKNGBC0OVcHhI+w1N3gkp59kY
+ CqBih/kazLfWjUXxc130OEkPhmS1zUEOjsl2
+ fmRhKrlRmPM1DyHqFiEVogj/nfZ+VCiO4bIx
+ F+vVQX+EqQo0p3bRvfSxpY/I7fM0P6/cZlQ= )
+txt500.edns512. 60 IN TXT "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789"
+ 60 RRSIG TXT 10 2 60 (
+ 20441127043557 20141205043557 59033 edns512.
+ OtzlxomsR6xFpPI19gEpl5edx+rbqjrhR6CI
+ zWiqpjHv5HhdydRPIW6M8KSuBDK/AOuUCy1P
+ 9qOy7J0QUIGK8Ds4wcw09VCqkxImVu6w7e+z
+ HoaNJzKT4Oxf1LLrvUnitqEbS4cME15r+Fj4
+ cUlkpSZgttMcGhV+VPEiG3z56KzXNAViapJl
+ HaV10Be0nx0UtEpftkAtgnkXwNPIaDrbULUI
+ tvD/uvu3ICV5gRATriy3RcanB9c0xKEO9NAm
+ nbWQD8a7o+zs3OqqDRcZqvq0PRuz7X8Q4T/n
+ fPYNkGoph1etQTaM1F6V0gP/2Hxv/oQclL77
+ IQSRZ8zCZJech8qgBlEHgdY/4hqJzJtO98Ha
+ OfB7ixmHp9fE5dGInIot6eMKN+Utnl2KLjjn
+ oO05gh9VESsgDIOM2amN/aViP54ad5DFtJni
+ 1mLRhV7FmBD2WSkdZF4/u4SvxjKYpWF1pspO
+ xNPhgaavnAqkM361P0kV13StLXzff9g9QsuB
+ S8Z4v0Ypiv4s5SlXsKeTpa0Y1gKXf8U1UZGq
+ /+2089ZurC8S1D89m72M3hgP80TDnLeuDCHY
+ /3tpU4V0yZ0u2riJG8/4MVFeeo8suk/z2gq0
+ nvs3YD7U0XB5ozLUlnKTT+NK49lnv5xoIByL
+ +ezP5zXMz4D0KAfKk+Wn84RgYn3ADABr1ZI= )
+ 0 NSEC edns512. TXT RRSIG NSEC
+ 0 RRSIG NSEC 10 2 0 (
+ 20441127043557 20141205043557 59033 edns512.
+ nFZKkyTy5O+je3VUaWt/eqVDqPtpktHFJt5X
+ K1TJHvRbuEanNMJoQJidS6ZhawgJhK54qgcM
+ klsR2n/eZ61Wbr1dpUscI7PNWGtZThW18d6W
+ GQjfxvLVSi+YVcSlAt5Jfc+4KZ+Mcte25xOD
+ DJMWVXTv2AgKt9T7JdOQTrpiugkpflct87FQ
+ 95POqtj5j72xnTvpjzaDcL22rD5q3kLQlQ14
+ xDZV1hOgqCYgbYVgwxgxigWSuWkKjiHiYR9o
+ YkLPkWHYNn7aDDFpAve4MJXRpuwPP9/TLQKH
+ hV4H8q7CZK30uKpUqy38JGTQzr7FDgTekGCd
+ InPLwSrURIkn3rVyCRq7PgvSBNXNW+3h9tYX
+ gMj6FDNyroWRH1eWmDFg3BmXKu6hUxrZ2fOk
+ wyhJ5M0LtZinjd5RuHy0CCKFuFA/Gv3Zga0m
+ vc34auzfwLnQmJc94j3JfwUGlMDeKtizKrhK
+ PahfCxEMVhY9E9LKx0UsbtJJ1ZgeNsm+zF5E
+ 6TkzYFc+hHeYM2/Jb2PVxjTmOkbfRoDmnRCd
+ 9Fus/kFtbgUK6ukpaQsNgdkwtLT8++FiaJUs
+ ion91SQWK7wjW3Fm+zMA88K/vzSQtv9mGUry
+ oZ4qpK1PFpafpzUVODx3HSS5RCPGZzd4zuDR
+ 6u7jgRUH3mokpudb4X1qt9L6tVyMLPqAaq8= )
+ns.edns512. 60 IN A 10.53.0.6
+ 60 RRSIG A 10 2 60 (
+ 20441127043557 20141205043557 59033 edns512.
+ BLCw43y8QO0QFaQpBPbMgLk3iIStBvp08qp6
+ wRCslXGRNK279mlNd29ZROVwmU7jrNd5jTIt
+ KhYlO/9DX0JMuTrG3W+tsGkGNqx3LNsVt6/U
+ rfF7iAxzBjnY4MRv0DIIKJqgEuz+A/vmbGQi
+ L0QxukaNPycQUEnMBbNmVvEi6uETW0yMPugn
+ BPg2jSVbrd/lY40K1yyUme//q8ljvneU++Mg
+ mmQ2crmINUQX3h4NBmXoOun0T5hehqiSvz4n
+ TUO9rhSMWFJxCvUcjndha2MBEm3/H5MhqHqH
+ vEFlL9/yDScmwT6FW7yoVtcoQzPymgimBIlB
+ SW75upaIy6EQcx88WhANB+oEm3JsIwufcpUl
+ jwe7taxtCV1VYxqbqH9ynEzbUH956pE6gsvW
+ 1lYrqzkmKl1l4YdJEr/Um8daVT88OR8ClP/3
+ v3OhAjmvnzl6WolaMPARCkFtswK8Awd61qDw
+ T11lTu7k0jB7Xx0JNzP2L/ehPaLokctPvECl
+ lMbHUryP30VnfBahCewO3/15+sUEhKrrlCif
+ G/MSFzDWbV11X1ItEQcBWgfcvhNfmAgQ0bsi
+ HgrgUuFIkmosoQUPEqJFCggTMYNZ769zEv/a
+ 9gJpLo5AmQqZYCn0sOw59IgXHUOsDoStB+WB
+ vAl9Q3ePoJ8wd+4sBC4KJs++Hw5pJ1oU+ks= )
+ 0 NSEC txt500.edns512. A RRSIG NSEC
+ 0 RRSIG NSEC 10 2 0 (
+ 20441127043557 20141205043557 59033 edns512.
+ DP0dAdDzZRS91BYNOzrHPbcGRRDTdkk+fAHi
+ Zb+kQ6Eur3EbXrrc/zH9UBmqircogWtOk8iv
+ h83G5y7Ry/tKQdrqb2igbkLo/BFsyeLKZFLh
+ DuWbSVvC1Hhs9tzFHVcH5gUObmlrj7wQd3T5
+ Iq4ZHbQCHg4OWZbS2gn+90uL/G5OHncE2Ni9
+ ELp3puFG+mO5RJJbF6CpU6vVGRs+kQyHREmj
+ i9kQ6C/12SHPnuIW8v/IP6EUSNb92mJk5n9P
+ N7EW1E67zCrHSh0rURz627hZRkpt831uod9H
+ Yf/Uj88zyTkprnBYdflydOzsjBiLMJwMh1CZ
+ BQ4EkEuRinkFeE3fmKHzv26S/HSbhVIS9E2z
+ nF7InmHB67uJvqj0oBTP2YFQdrDx5KWNBrqG
+ 4wB+OYnc6RSKrJWuvzUzyK4mCK619lVhgMi5
+ Jl6kBo7swgeriVhEODJVcX1ZEkd5WUwkpumw
+ JReLYStQKM8AbulcLQ4/bPwurhVPDpoNK6WL
+ kuv0MXijsFWps43ojok6DGPD01c7FRWxAKZV
+ eywmEIGLSYHDnWAzVIErXuO7RPfvLIVlZJzq
+ nzVj0ZLDh2BrrwbLt5zoETY5Ka6d6/YUXJLQ
+ Y+lxqTaDuJHnTqF7vcvxdkjYtR6JhsA4nfAO
+ TJHTtETInoRdXBTHahG5Q6tkj3kbhqR7dBc= )
diff --git a/bin/tests/system/legacy/ns6/named.args b/bin/tests/system/legacy/ns6/named.args
new file mode 100644
index 0000000..ac08197
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -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..8080003
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "edns512" {
+ type master;
+ 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..ba083be
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/sign.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=legacy
+
+echo_i "sign edns512"
+
+zone=edns512
+infile=edns512.db.in
+zonefile=edns512.db
+outfile=edns512.db.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -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..007eefc
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/edns512-notcp.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.7
+txt500 60 TXT ( "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789" )
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..87c8036
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/edns512-notcp.db.signed
@@ -0,0 +1,248 @@
+; File written on Fri Dec 5 16:35:58 2014
+; dnssec_signzone version 9.11.0pre-alpha
+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 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ ESBGgT1akISzDYasx1vDn4479d3zRZKvHIEb
+ OJIn2UqPVl6YDzcuUIqRwvFoqV7/eT4tllJ/
+ DSywHFPKV5t42BvnF2bEtPJZb6GUg3ZCqja4
+ CEaUNtqd4xyIT8BMT29w+d0OE6wbjaF3F3rS
+ RePp8RXde62vuR1rseTYLCF/V3jh1RvZCf3b
+ HnmavjU7Gzu6SG1IyBnxxJ43lvUOpKPbEiLa
+ H2MTRNzMxQ1CB7nv953XuWDjlqv37LqzQgt+
+ qHYC+Tjqx5KVUMewOAbcc4sne+ohMgz9p04h
+ JS3TIejgOfybFcmsZnsiqPkR9GKlDJ/L6hBH
+ azWKrnaHgS5n/j1rIWteV70E/VKXmiVspWkj
+ asOQM5F/7+RZWBA/bVsJqQOUdt3o04h70bQ5
+ mbPYY3AFpcpfPRVHoPAhvhMd5jdQoAY2SiI3
+ Uehleuyt3K+tDPCdgRhkkFwI15OBH1Jh2Y59
+ 7jvcXLqgI7T9kzUAbRpKOpR3+73Sa+UCx/Vw
+ iZqr03mBT8sSaZR1Zyd9y4b9yAQ7W2gHY1VM
+ 0N3lStdS938bwhcU5gN4ElkqXrwkCgVP8BoY
+ 3FotvKHUcLmnvrfKgnjcwReCJ66GeI+i205x
+ NcbDnmSfxYcW4VsLYA8yoQM+0NWmBBXT5JT/
+ ybAmt683yRwbFnl/YovtNwXtNKMb8+FKJjw= )
+ 60 NS ns.edns512-notcp.
+ 60 RRSIG NS 10 1 60 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ FLwTgbguhIW1UHjObRRogJg6RA5/32Sd7623
+ +btt7TqXchUMJyQsiIdZ0g5+NKQNawnhY4CV
+ NwNTeEiW55fjrZJC1A+nwBXGeE0MP9a2ngkj
+ PNK6spLXe67hMqudgbdp3toSfx1M3jI4PJ0Q
+ ji1UryuIqleR6w77JiaSB55MpoVDUVui/y/Y
+ VYHJ2z4wVBA0upoLegE5S9fWWpWIuD8aCU9y
+ +WMWhUd92Jm1Z9NWc7M9cwPp5/CAmitV5wjZ
+ wWu17WytNbwpYBww+DB72CrvvMZvVw8fcbdC
+ 5FIxIr6Ed0dNjfoakcPTW5EtDTk9ms6AjdMn
+ edNRZXgVuGZEenqmmsfuHFvNCurrNZJHG/je
+ xm5qhN9N85pmBILWpJPArKxwC37i00t/28Wx
+ FY7H2a7RWgtHkxuvnh4pwpidr2ZD+L5hQQ+c
+ O7CpzQMmS+dFOLF4/FOs6d/Do/7rxs1plUgp
+ NjOW3ts4tK1OkKPypXovuMxyLQstrnTkCNjA
+ pA+K5OBXdEsmtbIhXVAlARcyXXoKnYVFqd9c
+ Czu0kS4xy8B/auWcBzPMVYuTWGhNWemm7J9P
+ 0zOOB4n6nsaM7/UIoWK7Qx1CJLLOiWdEYNur
+ ouS9X97/LnsRcO/SPWB0aBTJgsMVQBkDB073
+ 0eZBJmUIAMidot4okbC3hQ3atQ0pGhDaAIo= )
+ 0 NSEC ns.edns512-notcp. NS SOA RRSIG NSEC DNSKEY
+ 0 RRSIG NSEC 10 1 0 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ JEdGV3CAGd23NG76F0B6FT6uz6TNWmP3Ecck
+ aI8djQLmnhu8vV1eYf4JCAS/EBOU/gS7iP+R
+ ziiJ3bPrvA1JSJhieTGw8K5IplUSTGHmlaIq
+ PfKRqN41mB9f3qI3PkN8h0Y2SbLKjYMIrHG1
+ 1R3LubcKwyEc+Y4ylqySaYO7JPcGznvWiu8k
+ KLcvYsBOy2V9gjY2Q1BYP6TR0QyYMXDht7cR
+ 27YSG2D+LP0HDIFV4f7T1SLjGmDl6ROh2Rnn
+ i51tnK02IwoDs207RC1ExlVqD4n/3JZIkh+M
+ c5FoPK/fV6IRz5cdwLk1Mv2ovihxPjryFLdw
+ 1ULSEc7gK8EkYfedv336GgZbDEWhWQgmVhPE
+ h26vJNF+ZSqWlo0tkKLAKzbd8yEguPf6HY1e
+ 0v5KVnUV3lINJIOmWtXDZNXho8WzA4WViqqW
+ yn+nTnRBg/20WdpHEhVDJKywQvKY6zsXMN8G
+ J++lx6FalaFdgE4gNcQQsu11VQDnJO90kKBU
+ uVRkFQArPj0TEaUWq+ZC1eJLKtraO9w/5ybw
+ LaIKBJBAcyU2jy7ieRc+NEY6rE2XOfJs0kEa
+ 8q5vM9/AFbX01yUEKnYj2CO/VhtfUa2tHEVo
+ JhATux63HBiTwhiYcyjfKhYcML2KoEYUCYU/
+ DAdy4zrs352EC3gVxagyUxCNJZ1Bq0wq+jI= )
+ 60 DNSKEY 256 3 10 (
+ AwEAAcEBkn/cuVhdRTWMHt19O7h9F4Hx2t68
+ u1JUZg7swLLvwfljqnNYjsKYk9EzUhIaYOAH
+ tVe7//cYwoVU4BFhY2DGbx1YE1LnKIGxfqpo
+ pFxDZC34TTl6jpoTP6kvj+XpeO0HfF2+DcyN
+ gnQcMGgHXyLWeRUJFt1As6o9tmsBiInGIZMT
+ E3/rANhtAGMLNzhRLN7CS/Tc5GhKaL66ueby
+ EYenEOAyDVgsuhr8Q9D5ka6xZmxzXFVswy2K
+ vsSxu9aoxVq4nACjIeTZ4GJy0v83zclV7hA+
+ 5jlPDXMFtIpvwux5XALrNkUUPq+Fb5sc5/u1
+ 41LcvdASnlk58I77HbsnfausvDxdYYxEns7K
+ 9e9N85dwyreM/OGTmm8p4hNDngZESAea7MrS
+ CsJpOGn9XLkVe6gZnBgB1cra+ezzTSWn+4QH
+ 17lIhFXYNjMV83df2h/gH3Gmthqnr9RgknZg
+ a8B/Czc7TeX6iy2gAOshKGyb6w12eJim1L8t
+ S5T138V8d6SigzxZz1raiJNolVhXyA8SbbDp
+ gBrcoEXN/WjwvWI+2ol5gzlqMeNw/F9SMoWd
+ pGIWkkNCNWBbhLWhp6qfhpRLUFwVys54LGOI
+ GSVRd9uJmc2hPdXoP8ephnCIeNJb8Zp6Dnps
+ syN0JaF815dKkOHff9GEjaiRLj0xWvtZSqNF
+ aGoB
+ ) ; ZSK; alg = RSASHA512; key id = 59033
+ 60 DNSKEY 257 3 10 (
+ AwEAAcEBkn/cuVhdRTWMHt19O7h9F4Hx2t68
+ u1JUZg7swLLvwfljqnNYjsKYk9EzUhIaYOAH
+ tVe7//cYwoVU4BFhY2DGbx1YE1LnKIGxfqpo
+ pFxDZC34TTl6jpoTP6kvj+XpeO0HfF2+DcyN
+ gnQcMGgHXyLWeRUJFt1As6o9tmsBiInGIZMT
+ E3/rANhtAGMLNzhRLN7CS/Tc5GhKaL66ueby
+ EYenEOAyDVgsuhr8Q9D5ka6xZmxzXFVswy2K
+ vsSxu9aoxVq4nACjIeTZ4GJy0v83zclV7hA+
+ 5jlPDXMFtIpvwux5XALrNkUUPq+Fb5sc5/u1
+ 41LcvdASnlk58I77HbsnfausvDxdYYxEns7K
+ 9e9N85dwyreM/OGTmm8p4hNDngZESAea7MrS
+ CsJpOGn9XLkVe6gZnBgB1cra+ezzTSWn+4QH
+ 17lIhFXYNjMV83df2h/gH3Gmthqnr9RgknZg
+ a8B/Czc7TeX6iy2gAOshKGyb6w12eJim1L8t
+ S5T138V8d6SigzxZz1raiJNolVhXyA8SbbDp
+ gBrcoEXN/WjwvWI+2ol5gzlqMeNw/F9SMoWd
+ pGIWkkNCNWBbhLWhp6qfhpRLUFwVys54LGOI
+ GSVRd9uJmc2hPdXoP8ephnCIeNJb8Zp6Dnps
+ syN0JaF815dKkOHff9GEjaiRLj0xWvtZSqNF
+ aGoB
+ ) ; KSK; alg = RSASHA512; key id = 59034
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ IrMpyEssdfDiqBDfMI5BVicoN5Upu20Bq0eL
+ BKXuiYBoRhBJhBnv6bovD0XWMf0spgPMHz4f
+ lgc0zT+41lQykiydy6WDLJ184E4If35ip9jp
+ Lj2yJGKUCr1FrvtciYPmYuH3wBIWl5wNlzJd
+ qH3P6nO3xYU4lgsBQPDUKvLHX7HIuSJB+2by
+ wbs3jj5Q78Ri1ELqKCCicfKbZwsRY9vexjw8
+ ptuJh+Y8kvhM/Yh7NyG5PByb5GRVVCCZ20ms
+ msBCiniPb/5IFiy7iUUiderLsa3y4UauTOKD
+ pKiOkBbB0XfxZtAsTZFU2W5seo6eoW3LfLp5
+ fD/qqUKyRZzPZaqJmp2n7egmX3WmRw11ILXk
+ LEuXA3P65YVbfqv08lZHz5K6xFhWsIJoBeev
+ 2leb3hN6nmSFApltdF0PDEfq1ZV+sBpOBsKN
+ EekIGAYO28u3+7pjxMzMe5EMtDAajb9bZCT6
+ 3ZTMPjlyT5ChtNRSIvgzgbfYAn1bigtQ+Opu
+ Jp82U+N1FRBNaSz7uw2uDAiE/cSNgfGIC7Dd
+ KBzWE6z/HFCzQp/gF8006AjztDq/SnyHWnWX
+ RzfMi1pE2IOT/GoCKOQwQNei0cG/ar+/ntVp
+ 3yg9PbYdhdMH8IQ1GpwczFfD1/I2/wuOGzPw
+ 1iFhd3dT9Sz2xgF/8xS95Ljgy8YgP+pmE3c= )
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20441127043558 20141205043558 59034 edns512-notcp.
+ VusByVbeIayH6KfnbhxLKycQfjU2L2Ilfa9o
+ K/MjEve4vMjqKeYV0oNan2X4DvPZusKeMVJp
+ JhQxvBz2GXE6syjrL5eEQtdcn6MW5Ew40w2E
+ i7BCGiHYrxH+SJqSORl5pBjihe24dRWoHHt/
+ 3CVBE18TU+ubSdLgOT3SvBtffJ1NVtvtCgpP
+ /yIgffhHOU/F0J+ewL6lmYzrkj/48Ep8F9e9
+ suAoorKmRP4zmeiojQedM+4PfbRn0doOLFIR
+ 8RZK8rv9WeQv1mhUh9s0zY4UARRGRb9i8Zhr
+ ERor3lZprmujx/Ok6XndTW7vRY/0IfC2i99C
+ 0zfcIdzuZ96YtiUFFTynptz3yxrJqQxeJaFt
+ vuZ4rd5XqSb3uPu8wVzYJEwhNRPJGqBpRAba
+ vxqOV1HAw89t1sUKXQR2qQ4HvpIzRIxFpIKQ
+ hRPMyd6uz0EtPQFE6ri1C5JkZkbdZ0r5SauY
+ EqZMsIl8oGtt1S5kEK2Agqx4b1pUfSv6cOLb
+ 765SGYVr1RdjmFZ7ftYYZPyMKJl6t3/ruZ9f
+ iazQGzoO6O+nQq3DD8EjZynsnAedzyEe3Hxd
+ tJM1Rm3nWAPka4QV5hdzpU93N/ao4tRuCYp/
+ 4pnVlc8MStuyuy9RRapEoOMs0iIQFPdidU+V
+ aM+ZSOa6RbYwzvzmX7I1UxBf5gKJzuDydDA= )
+ns.edns512-notcp. 60 IN A 10.53.0.7
+ 60 RRSIG A 10 2 60 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ eY/gUZcEKDE0loJ4zaxwJDg4E/S+ILJOrJrC
+ Yb64VWSE7RAzoQt8gYXAcEec4NLo2ZFsckTL
+ O0jD4db+q1rJLtniw+Xg/fckXvjxt21jNR43
+ +rW17ZuEYYlOWg9o+NyP9QnLjxNOR22f6gSx
+ FCLOca+8Yoxf4bw7EsdV98KajMFpcljQu2iE
+ NOKCoDSdunaZnhdP8kVuXO7P+VEXRa1OFzxb
+ mm2axihSqXcA7vdEdpGmTWoUFdG7p61Kl8Jw
+ rQzT7RiA3PoeyYoQ2wC2oitRr4lnsN/IF1vz
+ D3ldJ6pnYNVYmSHaS2potOMNDSTZtgV2LUmx
+ pqsaa3coYaJPJj0ijWzxw77nAXXQ7u/YWIzz
+ vUhXKygQIZaInl1msFPkFRy4AqriDmDnAAfJ
+ YyPunq7VkR2ExUhU1iFGGmDFE35ktxFl6AWL
+ /0CWElHPwuvqGksLnxrE7Syr25TOC+EhqDUS
+ G5X7/7Cb+Hl/twlA4oYDv8eXCwxMsncMp1cn
+ VDfwOrN4/JWzYcqNLTZHFRr+Uz7Fo8tGAri0
+ p7yDVHg35QN7usMKfsU3WnoOm1VlD/sU8bTW
+ 32dudd3yauhdKlmytZ2s2PMrXBf7/fsjDlY6
+ ZEc91TwM9Yt71FQ27XKoP5eFGajlxG+haoyB
+ 6jfoV4cIDq4MVerLOSUlczFjczbBXLHwLno= )
+ 0 NSEC txt500.edns512-notcp. A RRSIG NSEC
+ 0 RRSIG NSEC 10 2 0 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ mR1PHdEWNP90/80SAlKkj7jV0hBj0eDxM5Q0
+ RGPbv2pb1fOT/W8dTe2Qm/qwE0aY4nmRfiah
+ 8klCAXH9gvVAQFbPlz8tkLKEOrKjZM/YP9Vd
+ EoUmYj6+G2OXYvvetVStpqfiSK731iPUhKUD
+ Y0uYUzTyqgmOyyKWApk1+C+b3fYNS2E0jA77
+ riOCULE2FSPim7cEGS7JWE22qRY4//ENQZ27
+ eA+KbkXWR+vdqnQ6vs1cIwsbGbFFzmcogMT2
+ 3cN1e2lNbzTZIpVd9ukwp8FqyT0p7oz+q5r/
+ so4Zq0EGx473OgThMfTMs6pOg7L6M60jMhmF
+ 8V50dpePHmFLxI/Nn4kvxcUt684L3TWGObFQ
+ y9vxO8Wh66+USSX8jyDnP8mtMnGEeHD9SVYz
+ WIbCDVUsvSkFqSi/2o1/SZYWQ+wXkj6qO2Mz
+ JIgJKucALub0dOfaoncPYa7kfOxEOmgwY39I
+ RQodc53Brhgn6IF/1zNxZd5/FpWUs4ivrpsN
+ MOKy/E+MJiaGOdj1RwNlDdZQNtamexxOjcaD
+ 6pWAD44LgakoELE0Ktxtl/oMmouky0Dx/zwN
+ e9nEBTe9nTbG99lbzuGZ2vWkfqA1EsliCryd
+ wH6+EF3l5w9EEKBdVgBIEoHZ92TaiiJfRmFQ
+ LwEjS+AYjQKzmvp47lGqQf8/ggvMxcv/SCE= )
+txt500.edns512-notcp. 60 IN TXT "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789"
+ 60 RRSIG TXT 10 2 60 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ fpzr1/DNby1CMHfZclvga7Pk9S3tqWn0wwC9
+ xsUhYoPRcaIN4o9g5rOC0fxX1W4Q6gEXt0l2
+ fKzUdxE9QqTgpJOAOcMJa7D1yRo2ifVoX3Oq
+ M2lUYusg3o0Wg1JuNnf3DXaSaLOiYOrS2ixs
+ XnPwU0pLiniGIT9Bh2OuMBPs5YP2dZRKKJ7z
+ VrxE4F213A0FQfN68tIbN5XrzwO8EfyjBTyM
+ YtApC33vMajYeILnFemLrs9VL5hbLoyKcyqg
+ 1n0eSXhneHlYgsS5anSXWOSd9sT46jqpFwYF
+ O+frR2DNmdua4eZiUqA9HMgvaQnNodVU2Z5r
+ 5lzrHSVSXS/Au7kp4FZtYCUj2W4m/grOidH9
+ ulwM0Ut+OZOOLHVcwBQGuedEEwU/h+YGbJH6
+ fomTvfW+NAaL6X3IJggcQnHmCOTf0f3xXeXT
+ iHK1hE+iabTQ8gCabt4KCQ11Oz8zu3j7ZB5T
+ 2byQ49N2jj+i8+p2wsRbnz5Algx15KP11NM0
+ lUb+fhPlIrhbgwqPtv8udeRsBpRAwHXWrz5m
+ BxWQ5X52frQAPNoi51q5tTWE7UlpLYFBeXtW
+ 0XY7o6+TqP+EN5lGwddNhS0wYRWE10M2Es8A
+ 2q1RKIBDSPB3XEeULrQ6ciDgiDQ7T55p1KKM
+ r25OyqYCGZs9obDHnNVNQP2rTjfm6062TSo= )
+ 0 NSEC edns512-notcp. TXT RRSIG NSEC
+ 0 RRSIG NSEC 10 2 0 (
+ 20441127043558 20141205043558 59033 edns512-notcp.
+ pTTiIXjWLSH1Qm59kZlX0QmXtm7gDhL4RdQF
+ sHMtxZA1JhWjBC3u48C8M19ZWTu1xmTrhuil
+ tPV9a4u9zTasPWOy2HSKnl/jMaqGZ3xa96mo
+ I1qULVqb8XRTYqPsJ3reD6x9jJepEFAsK+xa
+ /TdrFTfZ5Oc0RYLQxH2qrJVc2n7S5gCHp10O
+ extcck2cyhiaRnI/wha6PdAXKG0ikX/oKAQL
+ hMcNUpOeewJLTvXasVPf4cF9O0B1/wXun3C4
+ lkzKF+fYBe2qg6ikGgsHws72/TYD2xDOae41
+ yjkVwdthTECDzedPc6jbKeApyEGA1G2lc7Ie
+ DE1rLRP3OhME5X9bhPcQnop4k583RQI0QY60
+ PUdZ/cr99eM6Zj3Mal6zBrebPiBAJVnr8C4X
+ /ozv3MFmaoNalB0JuTVojCboQ6Sf7+UCumXk
+ VK56zx6ZiGcwtnKHRQZIGGsHpPt28zo33wKJ
+ 0xljGuxfnxstGGmUUCTrhi0U/8991ZdqnjHg
+ hBkWxmEm1X5ioIVy5c5M6baSoEmls4iwad/O
+ vU9cx0aXxqir7/5jYlMFjn6Xo2BuUVQWf/LY
+ E9rZRZUN0a4sh7Wj8pjKS1hJ5pTK9C3ijEqD
+ Y9B5OslWHcOhSlv4q9YwuZkBo/b8UiV6EOnS
+ vE/TgzfP7DcXjTI5qErka0iJMxz/m90VuiU= )
diff --git a/bin/tests/system/legacy/ns7/named.args b/bin/tests/system/legacy/ns7/named.args
new file mode 100644
index 0000000..ac08197
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -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..d48a190
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "edns512-notcp" {
+ type master;
+ 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..344a869
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/sign.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+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 -r $RANDFILE -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -g -o $zone -f $outfile -e +30y $zonefile > /dev/null 2> signer.err || cat signer.err
+
+keyfile_to_trusted_keys $keyname2 > trusted.conf
+cp trusted.conf ../ns1
diff --git a/bin/tests/system/legacy/setup.sh b/bin/tests/system/legacy/setup.sh
new file mode 100644
index 0000000..b41da9e
--- /dev/null
+++ b/bin/tests/system/legacy/setup.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
+copy_setports ns4/named.conf.in ns4/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+copy_setports ns6/named.conf.in ns6/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
diff --git a/bin/tests/system/legacy/tests.sh b/bin/tests/system/legacy/tests.sh
new file mode 100755
index 0000000..c4356f2
--- /dev/null
+++ b/bin/tests/system/legacy/tests.sh
@@ -0,0 +1,166 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+n=0
+
+n=`expr $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
+grep "connection timed out; 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
+grep "connection timed out; no servers could be reached" dig.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking recursive lookup to drop edns server succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +tcp @10.53.0.1 dropedns 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=`expr $status + $ret`
+
+n=`expr $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
+grep "connection timed out; 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
+grep "connection timed out; no servers could be reached" dig.out.2.test$n > /dev/null
+$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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking recursive lookup to drop edns + no tcp server succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +tcp @10.53.0.1 dropedns-notcp 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=`expr $status + $ret`
+
+n=`expr $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
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking recursive lookup to plain dns server succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +tcp @10.53.0.1 plain 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=`expr $status + $ret`
+
+n=`expr $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
+grep "connection timed out; no servers could be reached" dig.out.2.test$n > /dev/null
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking recursive lookup to plain dns + no tcp server succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +tcp @10.53.0.1 plain-notcp 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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "checking edns 512 server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.6 edns512 soa > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +tcp @10.53.0.6 edns512 soa > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns @10.53.0.6 txt500.edns512 txt > dig.out.3.test$n
+grep "connection timed out; no servers could be reached" dig.out.3.test$n > /dev/null
+$DIG $DIGOPTS +edns +bufsize=512 +ignor @10.53.0.6 txt500.edns512 txt > dig.out.4.test$n
+grep "status: NOERROR" dig.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking recursive lookup to edns 512 server succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +tcp @10.53.0.1 txt500.edns512 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking edns 512 + no tcp server setup ($n)"
+ret=0
+$DIG $DIGOPTS +noedns @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
+$DIG $DIGOPTS +noedns +tcp @10.53.0.7 edns512-notcp soa > dig.out.2.test$n
+grep "connection timed out; no servers could be reached" dig.out.2.test$n > /dev/null
+$DIG $DIGOPTS +edns @10.53.0.7 edns512-notcp soa > dig.out.3.test$n
+grep "connection timed out; no servers could be reached" dig.out.3.test$n > /dev/null
+$DIG $DIGOPTS +edns +bufsize=512 +ignor @10.53.0.7 edns512-notcp soa > dig.out.4.test$n
+grep "status: NOERROR" dig.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking recursive lookup to edns 512 + no tcp server succeeds ($n)"
+ret=0
+$DIG $DIGOPTS +tcp @10.53.0.1 edns512-notcp 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=`expr $status + $ret`
+
+if $SHELL ../testcrypto.sh > /dev/null 2>&1
+then
+ $PERL $SYSTEMTESTTOP/stop.pl . ns1
+
+ copy_setports ns1/named2.conf.in ns1/named.conf
+
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1
+
+ n=`expr $n + 1`
+ echo_i "checking recursive lookup to edns 512 + no tcp + trust anchor fails ($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp @10.53.0.1 edns512-notcp soa > dig.out.test$n
+ grep "status: SERVFAIL" dig.out.test$n > /dev/null ||
+ grep "connection timed out;" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+else
+ echo_i "skipping checking recursive lookup to edns 512 + no tcp + trust anchor fails as crypto not enabled"
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/limits/clean.sh b/bin/tests/system/limits/clean.sh
new file mode 100644
index 0000000..73f4bc3
--- /dev/null
+++ b/bin/tests/system/limits/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
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..1fc5ec6
--- /dev/null
+++ b/bin/tests/system/limits/ns1/example.db
@@ -0,0 +1,19110 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3189967
--- /dev/null
+++ b/bin/tests/system/limits/ns1/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ 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..12486d7
--- /dev/null
+++ b/bin/tests/system/limits/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7e60631
--- /dev/null
+++ b/bin/tests/system/limits/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..5fbdd1d
--- /dev/null
+++ b/bin/tests/system/limits/tests.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+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/logfileconfig/clean.sh b/bin/tests/system/logfileconfig/clean.sh
new file mode 100644
index 0000000..61d41e4
--- /dev/null
+++ b/bin/tests/system/logfileconfig/clean.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after log file tests
+#
+rm -f ns1/rndc.conf
+rm -f ns1/controls.conf
+rm -f ns1/named.conf
+rm -f ns1/named.pid ns1/named.run
+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/rndc.out.test*
+rm -f ns1/dig.out.test*
+rm -f ns1/named_vers
+rm -f ns1/named_vers.*
+rm -f ns1/named_unlimited
+rm -f ns1/named_unlimited.*
diff --git a/bin/tests/system/logfileconfig/ns1/controls.conf.in b/bin/tests/system/logfileconfig/ns1/controls.conf.in
new file mode 100644
index 0000000..74084d9
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/controls.conf.in
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls {
+ inet 127.0.0.1 port @CONTROLPORT@
+ allow { 127.0.0.1/32; ::1/128; }
+ keys { "rndc-key"; };
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.dirconf b/bin/tests/system/logfileconfig/ns1/named.dirconf
new file mode 100644
index 0000000..dcc02d3
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.dirconf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+logging {
+ channel default_log {
+ file "named_dir";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.pipeconf b/bin/tests/system/logfileconfig/ns1/named.pipeconf
new file mode 100644
index 0000000..cc8fe36
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.pipeconf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+logging {
+ channel default_log {
+ file "named_pipe";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.plain b/bin/tests/system/logfileconfig/ns1/named.plain
new file mode 100644
index 0000000..0ef7832
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.plain
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+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; };
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.plainconf b/bin/tests/system/logfileconfig/ns1/named.plainconf
new file mode 100644
index 0000000..75e0c79
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.plainconf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.symconf b/bin/tests/system/logfileconfig/ns1/named.symconf
new file mode 100644
index 0000000..34a0e12
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.symconf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+logging {
+ channel default_log {
+ file "named_sym";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.unlimited b/bin/tests/system/logfileconfig/ns1/named.unlimited
new file mode 100644
index 0000000..cca3982
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.unlimited
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+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; };
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.versconf b/bin/tests/system/logfileconfig/ns1/named.versconf
new file mode 100644
index 0000000..6e293c7
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.versconf
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+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; };
+};
+
+include "controls.conf";
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
+
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/rndc.conf.in b/bin/tests/system/logfileconfig/ns1/rndc.conf.in
new file mode 100644
index 0000000..7e67a24
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/rndc.conf.in
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ default-server 127.0.0.1;
+};
+
+server 127.0.0.1 {
+ key "rndc-key";
+ addresses { 127.0.0.1 port @CONTROLPORT@; };
+};
+
+key "rndc-key" {
+ algorithm hmac-sha256;
+ secret "Am9vCg==";
+};
diff --git a/bin/tests/system/logfileconfig/ns1/root.db b/bin/tests/system/logfileconfig/ns1/root.db
new file mode 100644
index 0000000..8aaa4ea
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/root.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/logfileconfig/setup.sh b/bin/tests/system/logfileconfig/setup.sh
new file mode 100644
index 0000000..d711288
--- /dev/null
+++ b/bin/tests/system/logfileconfig/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.plain ns1/named.conf
+copy_setports ns1/rndc.conf.in ns1/rndc.conf
+copy_setports ns1/controls.conf.in ns1/controls.conf
diff --git a/bin/tests/system/logfileconfig/tests.sh b/bin/tests/system/logfileconfig/tests.sh
new file mode 100644
index 0000000..ad63bdd
--- /dev/null
+++ b/bin/tests/system/logfileconfig/tests.sh
@@ -0,0 +1,364 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+THISDIR=`pwd`
+CONFDIR="ns1"
+
+PLAINCONF="${THISDIR}/${CONFDIR}/named.plainconf"
+PLAINFILE="named_log"
+DIRCONF="${THISDIR}/${CONFDIR}/named.dirconf"
+DIRFILE="named_dir"
+PIPECONF="${THISDIR}/${CONFDIR}/named.pipeconf"
+PIPEFILE="named_pipe"
+SYMCONF="${THISDIR}/${CONFDIR}/named.symconf"
+SYMFILE="named_sym"
+VERSCONF="${THISDIR}/${CONFDIR}/named.versconf"
+VERSFILE="named_vers"
+UNLIMITEDCONF="${THISDIR}/${CONFDIR}/named.unlimited"
+UNLIMITEDFILE="named_unlimited"
+DLFILE="named_deflog"
+
+PIDFILE="${THISDIR}/${CONFDIR}/named.pid"
+myRNDC="$RNDC -c ${THISDIR}/${CONFDIR}/rndc.conf"
+myNAMED="$NAMED -c ${THISDIR}/${CONFDIR}/named.conf -m record,size,mctx -T clienttest -T nosyslog -d 99 -X named.lock -U 4"
+
+# 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
+}
+
+waitforpidfile() {
+ for _w in 1 2 3 4 5 6 7 8 9 10
+ do
+ test -f $PIDFILE && break
+ sleep 1
+ done
+}
+
+status=0
+n=0
+
+cd $CONFDIR
+
+echo_i "testing log file validity (named -g + only plain files allowed)"
+
+n=`expr $n + 1`
+echo_i "testing plain file (named -g) ($n)"
+# First run with a known good config.
+echo > $PLAINFILE
+copy_setports $PLAINCONF named.conf
+$myRNDC reconfig > rndc.out.test$n 2>&1
+grep "reloading configuration failed" named.run > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ echo_i "testing plain file succeeded"
+else
+ echo_i "testing plain file failed (unexpected)"
+ echo_i "exit status: 1"
+ exit 1
+fi
+
+# Now try directory, expect failure
+n=`expr $n + 1`
+echo_i "testing directory as log file (named -g) ($n)"
+echo > named.run
+rm -rf $DIRFILE
+mkdir -p $DIRFILE >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ copy_setports $DIRCONF named.conf
+ echo > named.run
+ $myRNDC reconfig > rndc.out.test$n 2>&1
+ grep "checking logging configuration failed: invalid file" named.run > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo_i "testing directory as file succeeded (UNEXPECTED)"
+ echo_i "exit status: 1"
+ exit 1
+ else
+ echo_i "testing directory as log file failed (expected)"
+ fi
+else
+ echo_i "skipping directory test (unable to create directory)"
+fi
+
+# Now try pipe file, expect failure
+n=`expr $n + 1`
+echo_i "testing pipe file as log file (named -g) ($n)"
+echo > named.run
+rm -f $PIPEFILE
+mkfifo $PIPEFILE >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ copy_setports $PIPECONF named.conf
+ echo > named.run
+ $myRNDC reconfig > rndc.out.test$n 2>&1
+ grep "checking logging configuration failed: invalid file" named.run > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo_i "testing pipe file as log file succeeded (UNEXPECTED)"
+ echo_i "exit status: 1"
+ exit 1
+ else
+ echo_i "testing pipe file as log file failed (expected)"
+ fi
+else
+ echo_i "skipping pipe test (unable to create pipe)"
+fi
+
+# Now try symlink file to plain file, expect success
+n=`expr $n + 1`
+echo_i "testing symlink to plain file as log file (named -g) ($n)"
+# Assume success
+echo > named.run
+echo > $PLAINFILE
+rm -f $SYMFILE $SYMFILE
+ln -s $PLAINFILE $SYMFILE >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ copy_setports $SYMCONF named.conf
+ $myRNDC reconfig > rndc.out.test$n 2>&1
+ echo > named.run
+ grep "reloading configuration failed" named.run > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo_i "testing symlink to plain file succeeded"
+ else
+ echo_i "testing symlink to plain file failed (unexpected)"
+ echo_i "exit status: 1"
+ exit 1
+ fi
+else
+ echo_i "skipping symlink test (unable to create symlink)"
+fi
+# Stop the server and run through a series of tests with various config
+# files while controlling the stop/start of the server.
+# Have to stop the stock server because it uses "-g"
+#
+$PERL ../../stop.pl .. ns1
+
+$myNAMED > /dev/null 2>&1
+
+if [ $? -ne 0 ]
+then
+ echo_i "failed to start $myNAMED"
+ echo_i "exit status: $status"
+ exit $status
+fi
+
+status=0
+
+echo_i "testing log file validity (only plain files allowed)"
+
+n=`expr $n + 1`
+echo_i "testing plain file (named -g) ($n)"
+# First run with a known good config.
+echo > $PLAINFILE
+copy_setports $PLAINCONF named.conf
+$myRNDC reconfig > rndc.out.test$n 2>&1
+grep "reloading configuration failed" named.run > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ echo_i "testing plain file succeeded"
+else
+ echo_i "testing plain file failed (unexpected)"
+ echo_i "exit status: 1"
+ exit 1
+fi
+
+# Now try directory, expect failure
+n=`expr $n + 1`
+echo_i "testing directory as log file ($n)"
+echo > named.run
+rm -rf $DIRFILE
+mkdir -p $DIRFILE >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ copy_setports $DIRCONF named.conf
+ echo > named.run
+ $myRNDC reconfig > rndc.out.test$n 2>&1
+ grep "configuring logging: invalid file" named.run > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo_i "testing directory as file succeeded (UNEXPECTED)"
+ echo_i "exit status: 1"
+ exit 1
+ else
+ echo_i "testing directory as log file failed (expected)"
+ fi
+else
+ echo_i "skipping directory test (unable to create directory)"
+fi
+
+# Now try pipe file, expect failure
+n=`expr $n + 1`
+echo_i "testing pipe file as log file ($n)"
+echo > named.run
+rm -f $PIPEFILE
+mkfifo $PIPEFILE >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ copy_setports $PIPECONF named.conf
+ echo > named.run
+ $myRNDC reconfig > rndc.out.test$n 2>&1
+ grep "configuring logging: invalid file" named.run > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo_i "testing pipe file as log file succeeded (UNEXPECTED)"
+ echo_i "exit status: 1"
+ exit 1
+ else
+ echo_i "testing pipe file as log file failed (expected)"
+ fi
+else
+ echo_i "skipping pipe test (unable to create pipe)"
+fi
+
+# Now try symlink file to plain file, expect success
+n=`expr $n + 1`
+echo_i "testing symlink to plain file as log file ($n)"
+# Assume success
+status=0
+echo > named.run
+echo > $PLAINFILE
+rm -f $SYMFILE
+ln -s $PLAINFILE $SYMFILE >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ copy_setports $SYMCONF named.conf
+ $myRNDC reconfig > rndc.out.test$n 2>&1
+ echo > named.run
+ grep "reloading configuration failed" named.run > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ echo_i "testing symlink to plain file succeeded"
+ else
+ echo_i "testing symlink to plain file failed (unexpected)"
+ echo_i "exit status: 1"
+ exit 1
+ fi
+else
+ echo_i "skipping symlink test (unable to create symlink)"
+fi
+
+status=0
+
+n=`expr $n + 1`
+echo_i "testing default logfile using named -L file ($n)"
+# Now stop the server again and test the -L option
+rm -f $DLFILE
+$PERL ../../stop.pl .. ns1
+if ! test -f $PIDFILE; then
+ copy_setports $PLAINCONF named.conf
+ $myNAMED -L $DLFILE > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo_i "failed to start $myNAMED"
+ echo_i "exit status: $status"
+ exit $status
+ fi
+
+ waitforpidfile
+
+ sleep 1
+ if [ -f "$DLFILE" ]; then
+ echo_i "testing default logfile using named -L succeeded"
+ else
+ echo_i "testing default logfile using named -L failed"
+ echo_i "exit status: 1"
+ exit 1
+ fi
+else
+ echo_i "failed to cleanly stop $myNAMED"
+ echo_i "exit status: 1"
+ exit 1
+fi
+
+echo_i "testing logging functionality"
+
+n=`expr $n + 1`
+echo_i "testing explicit versions ($n)"
+copy_setports $VERSCONF named.conf
+# a seconds since epoch version number
+touch $VERSFILE.1480039317
+t1=`$PERL -e 'print time()."\n";'`
+$myRNDC reconfig > rndc.out.test$n 2>&1
+$DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+t2=`$PERL -e 'print time()."\n";'`
+t=`expr ${t2:-0} - ${t1:-0}`
+if test ${t:-1000} -gt 5
+then
+ echo_i "testing explicit versions failed: cleanup of old entries took too long ($t secs)"
+ status=`expr $status + 1`
+fi
+if ! grep "status: NOERROR" dig.out.test$n > /dev/null
+then
+ echo_i "testing explicit versions failed: DiG lookup failed"
+ status=`expr $status + 1`
+fi
+if test_with_retry -f $VERSFILE.1480039317
+then
+ echo_i "testing explicit versions failed: $VERSFILE.1480039317 not removed"
+ status=`expr $status + 1`
+fi
+if test_with_retry -f $VERSFILE.5
+then
+ echo_i "testing explicit versions failed: $VERSFILE.5 exists"
+ status=`expr $status + 1`
+fi
+if test_with_retry ! -f $VERSFILE.4
+then
+ echo_i "testing explicit versions failed: $VERSFILE.4 does not exist"
+ status=`expr $status + 1`
+fi
+
+n=`expr $n + 1`
+echo_i "testing unlimited versions ($n)"
+copy_setports $UNLIMITEDCONF named.conf
+# a seconds since epoch version number
+touch $UNLIMITEDFILE.1480039317
+t1=`$PERL -e 'print time()."\n";'`
+$myRNDC reconfig > rndc.out.test$n 2>&1
+$DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+t2=`$PERL -e 'print time()."\n";'`
+t=`expr ${t2:-0} - ${t1:-0}`
+if test ${t:-1000} -gt 5
+then
+ echo_i "testing unlimited versions failed: took too long ($t secs)"
+ status=`expr $status + 1`
+fi
+if ! grep "status: NOERROR" dig.out.test$n > /dev/null
+then
+ echo_i "testing unlimited versions failed: DiG lookup failed"
+ status=`expr $status + 1`
+fi
+if test_with_retry ! -f $UNLIMITEDFILE.1480039317
+then
+ echo_i "testing unlimited versions failed: $UNLIMITEDFILE.1480039317 removed"
+ status=`expr $status + 1`
+fi
+if test_with_retry ! -f $UNLIMITEDFILE.4
+then
+ echo_i "testing unlimited versions failed: $UNLIMITEDFILE.4 does not exist"
+ status=`expr $status + 1`
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/lwresd/Makefile.in b/bin/tests/system/lwresd/Makefile.in
new file mode 100644
index 0000000..47a3a1a
--- /dev/null
+++ b/bin/tests/system/lwresd/Makefile.in
@@ -0,0 +1,50 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.22 2009/12/05 23:31:40 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${LWRES_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+LWRESLIBS = ../../../../lib/lwres/liblwres.@A@
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+LWRESDEPLIBS = ../../../../lib/lwres/liblwres.@A@
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${LWRESDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = lwtest@EXEEXT@
+
+OBJS = lwtest.@O@
+
+SRCS = lwtest.c
+
+@BIND9_MAKE_RULES@
+
+all: lwtest@EXEEXT@
+
+lwtest@EXEEXT@: ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/tests/system/lwresd/clean.sh b/bin/tests/system/lwresd/clean.sh
new file mode 100644
index 0000000..155c479
--- /dev/null
+++ b/bin/tests/system/lwresd/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after lwresd tests.
+#
+rm -f */named.memstats
+rm -f */named.run
+rm -f dig.out
+rm -f lwresd1/lwresd.run.resolv
+rm -f lwresd1/lwresd.run.lwresd
+rm -f ns*/named.lock
+rm -f lwresd*/lwresd.lock
+rm -f lwresd*/lwresd.run
diff --git a/bin/tests/system/lwresd/lwresd1/lwresd.conf b/bin/tests/system/lwresd/lwresd1/lwresd.conf
new file mode 100644
index 0000000..5c30f88
--- /dev/null
+++ b/bin/tests/system/lwresd/lwresd1/lwresd.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwresd.conf,v 1.8 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ port 5300;
+ pid-file "lwresd.pid";
+ forwarders {10.53.0.1;};
+ forward only;
+};
+
+lwres {
+ listen-on {10.53.0.1 port 9210;};
+ view "_default";
+ search {example1.;};
+ ndots 1;
+};
diff --git a/bin/tests/system/lwresd/lwresd1/nosearch.conf b/bin/tests/system/lwresd/lwresd1/nosearch.conf
new file mode 100644
index 0000000..52c0b7d
--- /dev/null
+++ b/bin/tests/system/lwresd/lwresd1/nosearch.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwresd.conf,v 1.8 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ port 5300;
+ pid-file "lwresd.pid";
+ forwarders {10.53.0.1;};
+ forward only;
+};
+
+lwres {
+ listen-on {10.53.0.1 port 9210;};
+ view "_default";
+ ndots 1;
+};
diff --git a/bin/tests/system/lwresd/lwresd1/resolv.conf b/bin/tests/system/lwresd/lwresd1/resolv.conf
new file mode 100644
index 0000000..0d6f111
--- /dev/null
+++ b/bin/tests/system/lwresd/lwresd1/resolv.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: resolv.conf,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+nameserver 10.53.0.1
+lwserver 10.53.0.1
+search example1.
+ndots 1
diff --git a/bin/tests/system/lwresd/lwtest.c b/bin/tests/system/lwresd/lwtest.c
new file mode 100644
index 0000000..b690c75
--- /dev/null
+++ b/bin/tests/system/lwresd/lwtest.c
@@ -0,0 +1,797 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: lwtest.c,v 1.32 2008/04/02 02:37:42 marka Exp $ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+#include <lwres/netdb.h>
+#include <lwres/net.h>
+
+/*
+ * XXX getnameinfo errors, which don't appear to be standard.
+ */
+#define ENI_NOSERVNAME 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+#define ENI_NOSOCKET 7
+
+static int fails = 0;
+
+static void
+CHECK(lwres_result_t val, const char *msg) {
+ if (val != 0) {
+ printf("I:%s returned %d\n", msg, val);
+ exit(1);
+ }
+}
+
+static unsigned char TESTSTRING[] =
+ "This is a test. This is only a test. !!!";
+
+static lwres_context_t *ctx;
+
+static void
+test_noop(void) {
+ lwres_result_t ret;
+ lwres_lwpacket_t pkt, pkt2;
+ lwres_nooprequest_t nooprequest, *nooprequest2;
+ lwres_noopresponse_t noopresponse, *noopresponse2;
+ lwres_buffer_t b;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0;
+
+ nooprequest.datalength = strlen((char *)TESTSTRING);
+ nooprequest.data = TESTSTRING;
+ ret = lwres_nooprequest_render(ctx, &nooprequest, &pkt, &b);
+ CHECK(ret, "lwres_nooprequest_render");
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ nooprequest2 = NULL;
+ ret = lwres_nooprequest_parse(ctx, &b, &pkt2, &nooprequest2);
+ CHECK(ret, "lwres_nooprequest_parse");
+
+ assert(nooprequest.datalength == nooprequest2->datalength);
+ assert(memcmp(nooprequest.data, nooprequest2->data,
+ nooprequest.datalength) == 0);
+
+ lwres_nooprequest_free(ctx, &nooprequest2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0xdeadbeef;
+
+ noopresponse.datalength = strlen((char *)TESTSTRING);
+ noopresponse.data = TESTSTRING;
+ ret = lwres_noopresponse_render(ctx, &noopresponse, &pkt, &b);
+ CHECK(ret, "lwres_noopresponse_render");
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ noopresponse2 = NULL;
+ ret = lwres_noopresponse_parse(ctx, &b, &pkt2, &noopresponse2);
+ CHECK(ret, "lwres_noopresponse_parse");
+
+ assert(noopresponse.datalength == noopresponse2->datalength);
+ assert(memcmp(noopresponse.data, noopresponse2->data,
+ noopresponse.datalength) == 0);
+
+ lwres_noopresponse_free(ctx, &noopresponse2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+}
+
+static void
+test_gabn(const char *target, lwres_result_t expected, const char *address,
+ uint32_t af)
+{
+ lwres_gabnresponse_t *res;
+ unsigned char addrbuf[16];
+ lwres_addr_t *addr;
+ char outbuf[64];
+ unsigned int len;
+ lwres_result_t ret;
+
+ res = NULL;
+ ret = lwres_getaddrsbyname(ctx, target,
+ LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6,
+ &res);
+ if (ret != expected) {
+ printf("I:gabn(%s) failed: %d\n", target, ret);
+ if (res != NULL)
+ lwres_gabnresponse_free(ctx, &res);
+ fails++;
+ return;
+ }
+ if (ret == LWRES_R_SUCCESS) {
+ if (af == LWRES_ADDRTYPE_V4) {
+ len = 4;
+ ret = inet_pton(AF_INET, address, addrbuf);
+ assert(ret == 1);
+ } else {
+ len = 16;
+ ret = inet_pton(AF_INET6, address, addrbuf);
+ assert(ret == 1);
+ }
+ addr = LWRES_LIST_HEAD(res->addrs);
+ if (addr == NULL) {
+ printf("I:gabn(%s) returned empty list\n", target);
+ fails++;
+ return;
+ }
+ while (addr != NULL) {
+ if (addr->family != af || addr->length != len ||
+ memcmp(addr->address, addrbuf, len) == 0)
+ break;
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+ if (addr == NULL) {
+ addr = LWRES_LIST_HEAD(res->addrs);
+ if (addr->family == LWRES_ADDRTYPE_V4)
+ (void)inet_ntop(AF_INET, addr->address,
+ outbuf, sizeof(outbuf));
+ else
+ (void)inet_ntop(AF_INET6, addr->address,
+ outbuf, sizeof(outbuf));
+ printf("I:gabn(%s) returned %s, expected %s\n",
+ target, outbuf, address);
+ fails++;
+ return;
+ }
+ }
+ if (res != NULL)
+ lwres_gabnresponse_free(ctx, &res);
+}
+
+static void
+test_gnba(const char *target, uint32_t af, lwres_result_t expected,
+ const char *name)
+{
+ lwres_gnbaresponse_t *res;
+ lwres_result_t ret;
+ unsigned char addrbuf[16];
+ unsigned int len;
+
+ if (af == LWRES_ADDRTYPE_V4) {
+ len = 4;
+ ret = inet_pton(AF_INET, target, addrbuf);
+ assert(ret == 1);
+ } else {
+ len = 16;
+ ret = inet_pton(AF_INET6, target, addrbuf);
+ assert(ret == 1);
+ }
+
+ res = NULL;
+ ret = lwres_getnamebyaddr(ctx, af, len, addrbuf, &res);
+ if (ret != expected) {
+ printf("I:gnba(%s) failed: %d\n", target, ret);
+ if (res != NULL)
+ lwres_gnbaresponse_free(ctx, &res);
+ fails++;
+ return;
+ }
+ if (ret == LWRES_R_SUCCESS && strcasecmp(res->realname, name) != 0) {
+ printf("I:gnba(%s) returned %s, expected %s\n",
+ target, res->realname, name);
+ fails++;
+ return;
+ }
+ if (res != NULL)
+ lwres_gnbaresponse_free(ctx, &res);
+}
+
+static void
+test_gethostbyname(const char *name, const char *address) {
+ struct hostent *hp;
+ unsigned char addrbuf[16];
+ int ret;
+
+ hp = gethostbyname(name);
+ if (hp == NULL) {
+ if (address == NULL && h_errno == HOST_NOT_FOUND)
+ return;
+ else if (h_errno != HOST_NOT_FOUND) {
+ printf("I:gethostbyname(%s) failed: %s\n",
+ name, hstrerror(h_errno));
+ fails++;
+ return;
+ } else {
+ printf("I:gethostbyname(%s) returned not found\n",
+ name);
+ fails++;
+ return;
+ }
+ } else {
+ ret = inet_pton(AF_INET, address, addrbuf);
+ assert(ret == 1);
+ if (memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0) {
+ char outbuf[16];
+ (void)inet_ntop(AF_INET, hp->h_addr_list[0],
+ outbuf, sizeof(outbuf));
+ printf("I:gethostbyname(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_gethostbyname2(const char *name, const char *address, int af) {
+ struct hostent *hp;
+ unsigned char addrbuf[16];
+ int len, ret;
+
+ hp = gethostbyname2(name, af);
+ if (hp == NULL) {
+ if (address == NULL && h_errno == HOST_NOT_FOUND)
+ return;
+ else if (h_errno != HOST_NOT_FOUND) {
+ printf("I:gethostbyname(%s) failed: %s\n",
+ name, hstrerror(h_errno));
+ fails++;
+ return;
+ } else {
+ printf("I:gethostbyname(%s) returned not found\n",
+ name);
+ fails++;
+ return;
+ }
+ } else {
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+ if (hp->h_addrtype != af) {
+ printf("I:gethostbyname(%s) returned wrong family\n",
+ name);
+ fails++;
+ return;
+ }
+ if (len != (int)hp->h_length ||
+ memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0)
+ {
+ char outbuf[16];
+ (void)inet_ntop(af, hp->h_addr_list[0],
+ outbuf, sizeof(outbuf));
+ printf("I:gethostbyname(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_getipnodebyname(const char *name, const char *address, int af,
+ int v4map, int all)
+{
+ struct hostent *hp;
+ unsigned char addrbuf[16];
+ int len, ret;
+ int error_num;
+ int flags = 0;
+
+ if (v4map)
+ flags |= AI_V4MAPPED;
+ if (all)
+ flags |= AI_ALL;
+
+ hp = getipnodebyname(name, af, flags, &error_num);
+ if (hp == NULL) {
+ if (address == NULL && error_num == HOST_NOT_FOUND)
+ return;
+ else if (error_num != HOST_NOT_FOUND) {
+ printf("I:getipnodebyname(%s) failed: %d\n",
+ name, error_num);
+ fails++;
+ return;
+ } else {
+ printf("I:getipnodebyname(%s) returned not found\n",
+ name);
+ fails++;
+ return;
+ }
+ } else {
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+ if (hp->h_addrtype != af) {
+ printf("I:getipnodebyname(%s) returned wrong family\n",
+ name);
+ freehostent(hp);
+ fails++;
+ return;
+ }
+ if (len != (int)hp->h_length ||
+ memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0)
+ {
+ char outbuf[16];
+ (void)inet_ntop(af, hp->h_addr_list[0],
+ outbuf, sizeof(outbuf));
+ printf("I:getipnodebyname(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ freehostent(hp);
+ fails++;
+ return;
+ }
+ freehostent(hp);
+ }
+}
+
+static void
+test_gethostbyaddr(const char *address, int af, const char *name) {
+ struct hostent *hp;
+ char addrbuf[16];
+ int len, ret;
+
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+
+ hp = gethostbyaddr(addrbuf, len, af);
+
+ if (hp == NULL) {
+ if (name == NULL && h_errno == HOST_NOT_FOUND)
+ return;
+ else if (h_errno != HOST_NOT_FOUND) {
+ printf("I:gethostbyaddr(%s) failed: %s\n",
+ address, hstrerror(h_errno));
+ fails++;
+ return;
+ } else {
+ printf("I:gethostbyaddr(%s) returned not found\n",
+ address);
+ fails++;
+ return;
+ }
+ } else {
+ if (name != NULL && strcmp(hp->h_name, name) != 0) {
+ printf("I:gethostbyname(%s) returned %s, "
+ "expected %s\n", address, hp->h_name, name);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_getipnodebyaddr(const char *address, int af, const char *name) {
+ struct hostent *hp;
+ char addrbuf[16];
+ int len, ret;
+ int error_num;
+
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+
+ hp = getipnodebyaddr(addrbuf, len, af, &error_num);
+
+ if (hp == NULL) {
+ if (name == NULL && error_num == HOST_NOT_FOUND)
+ return;
+ else if (error_num != HOST_NOT_FOUND) {
+ printf("I:getipnodebyaddr(%s) failed: %d\n",
+ address, error_num);
+ fails++;
+ return;
+ } else {
+ printf("I:getipnodebyaddr(%s) returned not found\n",
+ address);
+ fails++;
+ return;
+ }
+ } else {
+ if (name != NULL && strcmp(hp->h_name, name) != 0) {
+ printf("I:getipnodebyaddr(%s) returned %s, "
+ "expected %s\n", address, hp->h_name, name);
+ freehostent(hp);
+ fails++;
+ return;
+ }
+ freehostent(hp);
+ }
+}
+
+static void
+test_getaddrinfo(const char *name, int af, int v4ok, int v6ok,
+ const char *address)
+{
+ unsigned int len;
+ int ret;
+ struct addrinfo *ai;
+ struct addrinfo hint;
+ unsigned char addrbuf[16];
+
+ if (v4ok == 1 && v6ok== 1) {
+ ret = getaddrinfo(name, NULL, NULL, &ai);
+ } else {
+ memset(&hint, 0, sizeof(hint));
+ if (v4ok)
+ hint.ai_family = AF_INET;
+ else
+ hint.ai_family = AF_INET6;
+ ret = getaddrinfo(name, NULL, &hint, &ai);
+ }
+ if (ret != 0) {
+ if (address == NULL && ret == EAI_NODATA)
+ return;
+ else if (ret != EAI_NODATA) {
+ printf("I:getaddrinfo(%s,%d,%d) failed: %s\n",
+ name, v4ok, v6ok, gai_strerror(ret));
+ fails++;
+ return;
+ } else {
+ printf("I:getaddrinfo(%s,%d,%d) returned not found\n",
+ name, v4ok, v6ok);
+ fails++;
+ return;
+ }
+ } else {
+ if (af == AF_INET)
+ len = sizeof(struct sockaddr_in);
+ else
+ len = sizeof(struct sockaddr_in6);
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+ if (ai->ai_family != af) {
+ printf("I:getaddrinfo(%s) returned wrong family\n",
+ name);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ }
+ if (len != (unsigned int) ai->ai_addrlen) {
+ char outbuf[16];
+ (void)inet_ntop(af, ai->ai_addr,
+ outbuf, sizeof(outbuf));
+ printf("I:getaddrinfo(%s) returned %lub, "
+ "expected %ub\n", name,
+ (unsigned long)ai->ai_addrlen, len);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ } else if (af == AF_INET) {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *) ai->ai_addr;
+ if (memcmp(&sin->sin_addr.s_addr, addrbuf, 4) != 0) {
+ char outbuf[16];
+ (void)inet_ntop(af, &sin->sin_addr.s_addr,
+ outbuf, sizeof(outbuf));
+ printf("I:getaddrinfo(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ }
+ } else {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *) ai->ai_addr;
+ if (memcmp(sin6->sin6_addr.s6_addr, addrbuf, 16) != 0)
+ {
+ char outbuf[16];
+ (void)inet_ntop(af, &sin6->sin6_addr.s6_addr,
+ outbuf, sizeof(outbuf));
+ printf("I:getaddrinfo(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ }
+ }
+ freeaddrinfo(ai);
+ }
+}
+
+static void
+test_getnameinfo(const char *address, int af, const char *name) {
+ int ret;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *sa;
+ int salen;
+ char host[1025];
+
+ if (af == AF_INET) {
+ memset(&sin, 0, sizeof(sin));
+ ret = inet_pton(AF_INET, address, &sin.sin_addr.s_addr);
+ assert(ret == 1);
+ sin.sin_family = AF_INET;
+#ifdef LWRES_PLATFORM_HAVESALEN
+ sin.sin_len = sizeof(sin);
+#endif
+ sa = (struct sockaddr *) &sin;
+ salen = sizeof(sin);
+ } else {
+ memset(&sin6, 0, sizeof(sin6));
+ ret = inet_pton(AF_INET6, address, sin6.sin6_addr.s6_addr);
+ assert(ret == 1);
+ sin6.sin6_family = AF_INET6;
+#ifdef LWRES_PLATFORM_HAVESALEN
+ sin6.sin6_len = sizeof(sin6);
+#endif
+ sa = (struct sockaddr *) &sin6;
+ salen = sizeof(sin6);
+ }
+ sa->sa_family = af;
+
+ ret = getnameinfo(sa, salen, host, sizeof(host), NULL, 0, NI_NAMEREQD);
+
+ if (ret != 0) {
+ if (name == NULL && ret == ENI_NOHOSTNAME)
+ return;
+ else if (ret != ENI_NOHOSTNAME) {
+ printf("I:getnameinfo(%s) failed: %d\n",
+ address, ret);
+ fails++;
+ return;
+ } else {
+ printf("I:getnameinfo(%s) returned not found\n",
+ address);
+ fails++;
+ return;
+ }
+ } else {
+ if (name == NULL) {
+ printf("I:getnameinfo(%s) returned %s, "
+ "expected NULL\n", address, host);
+ fails++;
+ return;
+ } else if (strcmp(host, name) != 0) {
+ printf("I:getnameinfo(%s) returned %s, expected %s\n",
+ address, host, name);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_getrrsetbyname(const char *name, int rdclass, int rdtype,
+ unsigned int nrdatas, unsigned int nsigs,
+ int should_pass)
+{
+ int ret;
+ struct rrsetinfo *rrinfo = NULL;
+ ret = getrrsetbyname(name, rdclass, rdtype, 0, &rrinfo);
+ if (ret != 0 && should_pass == 1) {
+ printf("I:getrrsetbyname(%s, %d) failed\n", name, rdtype);
+ fails++;
+ return;
+ } else if (ret == 0 && should_pass == 0) {
+ printf("I:getrrsetbyname(%s, %d) unexpectedly succeeded\n",
+ name, rdtype);
+ fails++;
+ freerrset(rrinfo);
+ return;
+ } else if (ret != 0)
+ return;
+ if (rrinfo->rri_nrdatas != nrdatas) {
+ printf("I:getrrsetbyname(%s, %d): got %d rr, expected %d\n",
+ name, rdtype, rrinfo->rri_nrdatas, nrdatas);
+ fails++;
+ }
+ if (rrinfo->rri_nsigs != nsigs) {
+ printf("I:getrrsetbyname(%s, %d): got %d sig, expected %d\n",
+ name, rdtype, rrinfo->rri_nsigs, nsigs);
+ fails++;
+ }
+ freerrset(rrinfo);
+ return;
+}
+
+int
+main(int argc, char **argv) {
+ lwres_result_t ret;
+ int nosearch = 0;
+
+ UNUSED(argc);
+
+ lwres_udp_port = 9210;
+ lwres_resolv_conf = "resolv.conf";
+
+ if (argv[1] != NULL && strcmp(argv[1], "-nosearch") == 0)
+ nosearch = 1;
+
+ ret = lwres_context_create(&ctx, NULL, NULL, NULL, 0);
+ CHECK(ret, "lwres_context_create");
+
+ ret = lwres_conf_parse(ctx, "resolv.conf");
+ CHECK(ret, "lwres_conf_parse");
+
+ test_noop();
+
+ test_gabn("a.example1", LWRES_R_SUCCESS, "10.0.1.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example1.", LWRES_R_SUCCESS, "10.0.1.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example2", LWRES_R_SUCCESS, "10.0.2.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example2.", LWRES_R_SUCCESS, "10.0.2.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example3", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+ test_gabn("a.example3.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+ if (nosearch)
+ test_gabn("a", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+ else
+ test_gabn("a", LWRES_R_SUCCESS, "10.0.1.1", LWRES_ADDRTYPE_V4);
+ test_gabn("a.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+
+ if (nosearch)
+ test_gabn("a2", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+ else
+ test_gabn("a2", LWRES_R_SUCCESS, "10.0.1.1", LWRES_ADDRTYPE_V4);
+ test_gabn("a3", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+
+ test_gabn("b.example1", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example1.", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example2", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example2.", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example3", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+ test_gabn("b.example3.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+ if (nosearch)
+ test_gabn("b", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+ else
+ test_gabn("b", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+
+ test_gabn("d.example1", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+
+ test_gabn("x", LWRES_R_SUCCESS, "10.1.10.1", LWRES_ADDRTYPE_V4);
+ test_gabn("x.", LWRES_R_SUCCESS, "10.1.10.1", LWRES_ADDRTYPE_V4);
+
+ test_gnba("10.10.10.1", LWRES_ADDRTYPE_V4, LWRES_R_SUCCESS,
+ "ipv4.example");
+ test_gnba("10.10.10.17", LWRES_ADDRTYPE_V4, LWRES_R_NOTFOUND,
+ NULL);
+ test_gnba("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ LWRES_ADDRTYPE_V6, LWRES_R_SUCCESS, "ip6.int.example");
+ test_gnba("0123:4567:89ab:cdef:0123:4567:89ab:cde0",
+ LWRES_ADDRTYPE_V6, LWRES_R_NOTFOUND, NULL);
+ test_gnba("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ LWRES_ADDRTYPE_V6, LWRES_R_SUCCESS, "ip6.arpa.example");
+ test_gnba("1123:4567:89ab:cdef:0123:4567:89ab:cde0",
+ LWRES_ADDRTYPE_V6, LWRES_R_NOTFOUND, NULL);
+
+ test_gethostbyname("a.example1.", "10.0.1.1");
+ test_gethostbyname("q.example1.", NULL);
+
+ test_gethostbyname2("a.example1.", "10.0.1.1", AF_INET);
+ test_gethostbyname2("b.example1.",
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ AF_INET6);
+ test_gethostbyname2("q.example1.", NULL, AF_INET);
+
+ test_getipnodebyname("a.example1.", "10.0.1.1", AF_INET, 0, 0);
+ test_getipnodebyname("b.example1.",
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ AF_INET6, 0, 0);
+ test_getipnodebyname("a.example1.",
+ "::ffff:10.0.1.1", AF_INET6, 1, 0);
+ test_getipnodebyname("a.example1.",
+ "::ffff:10.0.1.1", AF_INET6, 1, 1);
+ test_getipnodebyname("b.example1.",
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ AF_INET6, 1, 1);
+ test_getipnodebyname("q.example1.", NULL, AF_INET, 0, 0);
+
+ test_gethostbyaddr("10.10.10.1", AF_INET, "ipv4.example");
+ test_gethostbyaddr("10.10.10.17", AF_INET, NULL);
+ test_gethostbyaddr("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.int.example");
+ test_gethostbyaddr("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.arpa.example");
+
+ test_getipnodebyaddr("10.10.10.1", AF_INET, "ipv4.example");
+ test_getipnodebyaddr("10.10.10.17", AF_INET, NULL);
+ test_getipnodebyaddr("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.int.example");
+ test_getipnodebyaddr("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.arpa.example");
+
+ test_getaddrinfo("a.example1.", AF_INET, 1, 1, "10.0.1.1");
+ test_getaddrinfo("a.example1.", AF_INET, 1, 0, "10.0.1.1");
+ test_getaddrinfo("a.example1.", AF_INET, 0, 1, NULL);
+ test_getaddrinfo("b.example1.", AF_INET6, 1, 1,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff");
+ test_getaddrinfo("b.example1.", AF_INET6, 1, 0, NULL);
+ test_getaddrinfo("b.example1.", AF_INET6, 0, 1,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff");
+
+ test_getnameinfo("10.10.10.1", AF_INET, "ipv4.example");
+ test_getnameinfo("10.10.10.17", AF_INET, NULL);
+ test_getnameinfo("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.int.example");
+ test_getnameinfo("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.arpa.example");
+ test_getnameinfo("1122:3344:5566:7788:99aa:bbcc:ddee:ff00",
+ AF_INET6, "dname.example1");
+
+ if (nosearch)
+ test_getrrsetbyname("a", 1, 1, 0, 0, 0);
+ else
+ test_getrrsetbyname("a", 1, 1, 1, 0, 1);
+ test_getrrsetbyname("a.example1.", 1, 1, 1, 0, 1);
+ test_getrrsetbyname("e.example1.", 1, 1, 1, 1, 1);
+ test_getrrsetbyname("e.example1.", 1, 255, 1, 1, 0);
+ test_getrrsetbyname("e.example1.", 1, 2, 1, 1, 1);
+ test_getrrsetbyname("e.example1.", 1, 46, 2, 0, 1);
+ test_getrrsetbyname("", 1, 1, 0, 0, 0);
+
+ test_getrrsetbyname("123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789", 1, 1, 0, 0, 0);
+
+ if (fails == 0)
+ printf("I:ok\n");
+ return (fails);
+}
diff --git a/bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db b/bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db
new file mode 100644
index 0000000..dcd8915
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; $Id: 10.10.10.in-addr.arpa.db,v 1.10 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000062001 ; 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
+
+1 PTR ipv4.example.
diff --git a/bin/tests/system/lwresd/ns1/e.example1.db b/bin/tests/system/lwresd/ns1/e.example1.db
new file mode 100644
index 0000000..2d9587c
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/e.example1.db
@@ -0,0 +1,54 @@
+; File written on Wed Mar 5 10:20:40 2008
+; dnssec_signzone version 9.3.4-P1
+e.example1. 300 IN SOA mname1. . (
+ 2002082210 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ 300 RRSIG SOA 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ KtYwrnKM7Tu53BNf8XuTix53r9kDdCneJ1X7
+ xklFbp4YjRKC3NhwVK9PFe0jdHOkIDMtrwxn
+ n7/Rp07xIyURqw== )
+ 300 NS ns.e.example1.
+ 300 RRSIG NS 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ KBPx3XmNl4swVPdwuUEFuzZedMSfsyK2a0Fu
+ o2wBnbCuS7G7DtfW9690lP/eTyixLOIwlFLQ
+ MrjN3+XgpkdgIw== )
+ 300 A 10.0.1.1
+ 300 RRSIG A 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ KYlxMQUvv8DQtVgS23lNL5tFYmRppJ7vTgH3
+ btvgKbyHxW/04ewRsgCa82iu3iJipdEhKM11
+ ALkRNhqL7frnig== )
+ 3600 NSEC ns.e.example1. A NS SOA RRSIG NSEC DNSKEY
+ 3600 RRSIG NSEC 5 2 3600 20010101000000 (
+ 20000101000000 14043 e.example1.
+ azSgagb7bldM06qSZg8nDZWOY2FbqeZY0/T8
+ nC+6VhCs7YTfNvXynLWmvmpqL7gVT6/O+Yi2
+ 2lmdntld7GORrQ== )
+ 300 DNSKEY 256 3 5 (
+ AwEAAcvAUMfH7wA0z077fJaF7RMrxAFyvo0/
+ 7aAL4d2/yA5TqTaUCVnJtE+XgGO34kH9mwae
+ we+Nyv2kRWDeLl6nhGk=
+ ) ; key id = 14043
+ 300 RRSIG DNSKEY 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ BQFWOHopXuBNdzcopkdl1YVKGF0QvIaYpywM
+ fcpG5gi+sy9EoTofQ1UGsLOjU3nFXCvJFG4K
+ 1gUhzEEti440/g== )
+ns.e.example1. 300 IN A 10.53.0.1
+ 300 RRSIG A 5 3 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ cYPzsWNQ/eL4h2lihKRjKT2jhGpOqV9woGJA
+ /Jstx2iethOAvYtgY22CsAbCUr/6E4bSgBZR
+ TMoC604cNdFzIw== )
+ 3600 NSEC e.example1. A RRSIG NSEC
+ 3600 RRSIG NSEC 5 3 3600 20010101000000 (
+ 20000101000000 14043 e.example1.
+ J8Md544zDLP4GjyAtkjH/rSFvpzXY/7bgJRS
+ YDoARwFQRmlrJvavXEjqElb2fTQqlNNz1cal
+ QROz/WJ3GLwOWw== )
diff --git a/bin/tests/system/lwresd/ns1/example1.db b/bin/tests/system/lwresd/ns1/example1.db
new file mode 100644
index 0000000..c2f0d80
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/example1.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; $Id: example1.db,v 1.19 2008/04/02 23:46:57 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2002082210 ; 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 10.0.1.1
+a2 CNAME a
+a3 CNAME nowhere
+b AAAA eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff
+8.8.7.7 DNAME net
+0.0.f.f.e.e.d.d.c.c.b.b.a.a.9.9.net PTR dname
+e NS ns.e
diff --git a/bin/tests/system/lwresd/ns1/example2.db b/bin/tests/system/lwresd/ns1/example2.db
new file mode 100644
index 0000000..1eeedcd
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/example2.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; $Id: example2.db,v 1.10 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000062001 ; 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 10.0.2.1
+b AAAA eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff
diff --git a/bin/tests/system/lwresd/ns1/ip6.arpa.db b/bin/tests/system/lwresd/ns1/ip6.arpa.db
new file mode 100644
index 0000000..dbcfe22
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/ip6.arpa.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; $Id: ip6.arpa.db,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2002082300 ; 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
+
+f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.1 PTR ip6.arpa.example.
+6.6.5.5.4.4.3.3.2.2.1.1 DNAME example1.
diff --git a/bin/tests/system/lwresd/ns1/ip6.int.db b/bin/tests/system/lwresd/ns1/ip6.int.db
new file mode 100644
index 0000000..e2675c6
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/ip6.int.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2002082300 ; 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
+
+f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0 PTR ip6.int.example.
diff --git a/bin/tests/system/lwresd/ns1/named.conf b/bin/tests/system/lwresd/ns1/named.conf
new file mode 100644
index 0000000..7e9e448
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/named.conf
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: named.conf,v 1.21 2008/04/02 23:46:57 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example1." {
+ type master;
+ file "example1.db";
+};
+
+zone "e.example1." {
+ type master;
+ file "e.example1.db";
+};
+
+zone "example2." {
+ type master;
+ file "example2.db";
+};
+
+zone "10.10.10.in-addr.arpa." {
+ type master;
+ file "10.10.10.in-addr.arpa.db";
+};
+
+zone "ip6.int." {
+ type master;
+ file "ip6.int.db";
+};
+
+zone "ip6.arpa." {
+ type master;
+ file "ip6.arpa.db";
+};
diff --git a/bin/tests/system/lwresd/ns1/root.db b/bin/tests/system/lwresd/ns1/root.db
new file mode 100644
index 0000000..e903f66
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/root.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; $Id: root.db,v 1.9 2007/06/19 23:47:04 tbox Exp $
+
+$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.2
+example2. NS ns.example2.
+ns.example2. A 10.53.0.2
+x A 10.1.10.1
diff --git a/bin/tests/system/lwresd/resolv.conf b/bin/tests/system/lwresd/resolv.conf
new file mode 100644
index 0000000..0d6f111
--- /dev/null
+++ b/bin/tests/system/lwresd/resolv.conf
@@ -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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: resolv.conf,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+nameserver 10.53.0.1
+lwserver 10.53.0.1
+search example1.
+ndots 1
diff --git a/bin/tests/system/lwresd/tests.sh b/bin/tests/system/lwresd/tests.sh
new file mode 100644
index 0000000..e753ce1
--- /dev/null
+++ b/bin/tests/system/lwresd/tests.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: tests.sh,v 1.22 2012/02/03 23:46:58 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+echo "I:waiting for nameserver to load"
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ for zone in . example1 e.example1 example2 10.10.10.in-addr.arpa \
+ ip6.int ip6.arpa
+ do
+ $DIG +tcp -p 5300 @10.53.0.1 soa $zone > dig.out
+ grep "status: NOERROR" dig.out > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out > /dev/null || ret=1
+ done
+ test $ret = 0 && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:using resolv.conf"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ grep ' running$' lwresd1/lwresd.run > /dev/null && break
+ sleep 1
+done
+$LWTEST || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+$PERL $SYSTEMTESTTOP/stop.pl . lwresd1
+
+mv lwresd1/lwresd.run lwresd1/lwresd.run.resolv
+
+$PERL $SYSTEMTESTTOP/start.pl . lwresd1 -- "-X lwresd.lock -m record,size,mctx -c lwresd.conf -d 99 -g"
+
+echo "I:using lwresd.conf"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ grep ' running$' lwresd1/lwresd.run > /dev/null && break
+ sleep 1
+done
+$LWTEST || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+$PERL $SYSTEMTESTTOP/stop.pl . lwresd1
+
+mv lwresd1/lwresd.run lwresd1/lwresd.run.lwresd
+
+$PERL $SYSTEMTESTTOP/start.pl . lwresd1 -- "-X lwresd.lock -m record,size,mctx -c nosearch.conf -d 99 -g"
+
+echo "I:using nosearch.conf"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ grep ' running$' lwresd1/lwresd.run > /dev/null && break
+ sleep 1
+done
+$LWTEST -nosearch || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/masterfile/clean.sh b/bin/tests/system/masterfile/clean.sh
new file mode 100644
index 0000000..894e75a
--- /dev/null
+++ b/bin/tests/system/masterfile/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f checkzone.out*
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..7836f96
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/include.db
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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..13a813d
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "include" {
+ type master;
+ file "include.db";
+};
+
+zone "ttl1" {
+ type master;
+ file "ttl1.db";
+};
+
+zone "ttl2" {
+ type master;
+ 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..5c84cec
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/sub.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+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..6aa8f36
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/ttl1.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN SOA 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..452d209
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/ttl2.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..562a995
--- /dev/null
+++ b/bin/tests/system/masterfile/ns2/example.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..96e7978
--- /dev/null
+++ b/bin/tests/system/masterfile/ns2/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "missing" {
+ type master;
+ 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..85855f3
--- /dev/null
+++ b/bin/tests/system/masterfile/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/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..f31e249
--- /dev/null
+++ b/bin/tests/system/masterfile/tests.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+n=0
+
+ret=0
+n=`expr $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=`expr $status + $ret`
+
+ret=0
+n=`expr $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=`expr $status + $ret`
+
+ret=0
+n=`expr $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=`expr $status + $ret`
+
+ret=0
+n=`expr $n + 1`
+echo_i "test owner inheritence 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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/masterfile/zone/inheritownerafterinclude.db b/bin/tests/system/masterfile/zone/inheritownerafterinclude.db
new file mode 100644
index 0000000..ce7bffe
--- /dev/null
+++ b/bin/tests/system/masterfile/zone/inheritownerafterinclude.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..76a1e89
--- /dev/null
+++ b/bin/tests/system/masterfile/zone/nameservers.db
@@ -0,0 +1,10 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN NS .
diff --git a/bin/tests/system/masterformat/clean.sh b/bin/tests/system/masterformat/clean.sh
new file mode 100755
index 0000000..d50ed95
--- /dev/null
+++ b/bin/tests/system/masterformat/clean.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f named-compilezone
+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/example.db.map ns1/signed.db.map
+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.map ns3/dynamic.db.map
+rm -f baseline.txt text.1 text.2 raw.1 raw.2 map.1 map.2 map.5 text.5 badmap
+rm -f ns1/Ksigned.* ns1/dsset-signed. ns1/signed.db.signed
+rm -f rndc.out
+rm -f ns*/named.lock
diff --git a/bin/tests/system/masterformat/ns1/compile.sh b/bin/tests/system/masterformat/ns1/compile.sh
new file mode 100755
index 0000000..b85b8d2
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/compile.sh
@@ -0,0 +1,32 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+../named-compilezone -D -F raw -o example.db.raw example \
+ example.db > /dev/null 2>&1
+../named-compilezone -D -F map -o ../ns3/example.db.map example \
+ example.db > /dev/null 2>&1
+../named-compilezone -D -F map -o ../ns3/dynamic.db.map dynamic \
+ example.db > /dev/null 2>&1
+../named-compilezone -D -F raw=1 -o example.db.raw1 example-explicit \
+ example.db > /dev/null 2>&1
+../named-compilezone -D -F raw=0 -o example.db.compat example-compat \
+ example.db > /dev/null 2>&1
+../named-compilezone -D -F raw -L 3333 -o example.db.serial.raw example \
+ example.db > /dev/null 2>&1
+../named-compilezone -D -F raw -o large.db.raw large large.db > /dev/null 2>&1
+../named-compilezone -D -F map -o example.db.map example-map \
+ example.db > /dev/null 2>&1
+
+$KEYGEN -q -r $RANDFILE signed > /dev/null 2>&1
+$KEYGEN -q -r $RANDFILE -fk signed > /dev/null 2>&1
+$SIGNER -S -f signed.db.signed -o signed signed.db > /dev/null 2>&1
+../named-compilezone -D -F map -o signed.db.map 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..b8e3247
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/example.db
@@ -0,0 +1,56 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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 1 (
+ AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg
+ +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD
+ Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R
+ b9VIE5x7KNHAYTvTO5d4S8M=
+ )
+ds 300 DS 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+cdnskey 300 CDNSKEY 256 3 1 (
+ AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg
+ +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD
+ Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R
+ b9VIE5x7KNHAYTvTO5d4S8M=
+ )
+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..b30b456
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/large.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..e986041
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/named.conf.in
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ pid-file "named.pid";
+ listen-on port @PORT@ { 10.53.0.1; };
+ port @PORT@;
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+ session-keyfile "session.key";
+ servfail-ttl 0;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type master;
+ masterfile-format raw;
+ file "example.db.raw";
+};
+
+zone "compat-example" {
+ type master;
+ masterfile-format raw;
+ file "example.db.compat";
+};
+
+zone "transfer1" {
+ type master;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "transfer2" {
+ type master;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "transfer3" {
+ type master;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "transfer4" {
+ type master;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+
+zone "large" {
+ type master;
+ file "large.db.raw";
+ masterfile-format raw;
+ allow-transfer { any; };
+};
+
+zone "signed" {
+ type master;
+ file "signed.db.map";
+ masterfile-format map;
+ 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..20fd00e
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/signed.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8007aa1
--- /dev/null
+++ b/bin/tests/system/masterformat/ns2/formerly-text.db.in
@@ -0,0 +1,46 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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 1 (
+ AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg+Ge4noWR
+ OpTWOIBvm76zeJPWs4Zfqa1IsswDIx5Mqeg0zwclz59u
+ ecKsKyx5w9IhtZ8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=
+ ) ; ZSK; alg = RSAMD5; key id = 30795
+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..ae28603
--- /dev/null
+++ b/bin/tests/system/masterformat/ns2/named.conf.in
@@ -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 http://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;
+ dnssec-enable yes;
+ servfail-ttl 0;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "transfer1" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "transfer.db.raw";
+};
+
+zone "transfer2" {
+ type slave;
+ masters { 10.53.0.1; };
+ masterfile-format text;
+ file "transfer.db.txt";
+};
+
+zone "transfer3" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "formerly-text.db";
+};
+
+zone "transfer4" {
+ type slave;
+ masters { 10.53.0.1; };
+ masterfile-format text;
+ masterfile-style full;
+ file "transfer.db.full";
+};
+
+zone "large" {
+ type slave;
+ masters { 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..f41dc2e
--- /dev/null
+++ b/bin/tests/system/masterformat/ns3/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ pid-file "named.pid";
+ listen-on port @PORT@ { 10.53.0.3; };
+ port @PORT@;
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type master;
+ masterfile-format map;
+ file "example.db.map";
+};
+
+zone "dynamic" {
+ type master;
+ masterfile-format map;
+ file "dynamic.db.map";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/masterformat/prereq.sh b/bin/tests/system/masterformat/prereq.sh
new file mode 100755
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/masterformat/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/masterformat/setup.sh b/bin/tests/system/masterformat/setup.sh
new file mode 100755
index 0000000..e6bac43
--- /dev/null
+++ b/bin/tests/system/masterformat/setup.sh
@@ -0,0 +1,31 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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
+
+rm -f named-compilezone
+ln -s $CHECKZONE named-compilezone
+
+rm -f ns1/example.db.raw
+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..14d90d5
--- /dev/null
+++ b/bin/tests/system/masterformat/tests.sh
@@ -0,0 +1,298 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+ismap () {
+ $PERL -e 'binmode STDIN;
+ read(STDIN, $input, 8);
+ ($style, $version) = unpack("NN", $input);
+ exit 1 if ($style != 3 || $version > 1);' < $1
+ return $?
+}
+
+israw () {
+ $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 () {
+ $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 or map\n");' < $1
+}
+
+sourceserial () {
+ $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 () {
+ $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);' $1 $2 $3 $4
+}
+
+restart () {
+ sleep 1
+ (cd ..; $PERL start.pl --noclean --restart --port ${PORT} masterformat ns3)
+}
+
+DIGOPTS="+tcp +noauth +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+
+echo_i "checking that master files in raw format loaded"
+ret=0
+set -- 1 2 3
+for zone in example example-explicit example-compat; do
+ for server in $*; do
+ for name in ns mx a aaaa cname dname txt rrsig nsec \
+ dnskey ds cdnskey cds; do
+ $DIG $DIGOPTS $name.$zone. $name @10.53.0.$server
+ echo
+ done > dig.out.$zone.$server
+ done
+ digcomp dig.out.$zone.1 dig.out.$zone.2 || ret=1
+ if [ $zone = "example" ]; then
+ set -- 1 2
+ digcomp dig.out.$zone.1 dig.out.$zone.3 || ret=1
+ fi
+done
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking raw format versions"
+ret=0
+israw ns1/example.db.raw || ret=1
+israw ns1/example.db.raw1 || ret=1
+israw ns1/example.db.compat || ret=1
+ismap ns1/example.db.map || ret=1
+[ "`rawversion ns1/example.db.raw`" = 1 ] || ret=1
+[ "`rawversion ns1/example.db.raw1`" = 1 ] || ret=1
+[ "`rawversion ns1/example.db.compat`" = 0 ] || ret=1
+[ "`rawversion ns1/example.db.map`" = 1 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking source serial numbers"
+ret=0
+[ "`sourceserial ns1/example.db.raw`" = "UNSET" ] || ret=1
+[ "`sourceserial ns1/example.db.serial.raw`" = "3333" ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $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 slave was saved in raw format by default"
+ret=0
+israw ns2/transfer.db.raw || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking that slave was saved in text format when configured"
+ret=0
+israw ns2/transfer.db.txt && ret=1
+isfull ns2/transfer.db.txt && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking that slave was saved in 'full' style when configured"
+ret=0
+isfull ns2/transfer.db.full > /dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking that slave formerly in text format is now raw"
+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`" = 1 ] || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking that large rdatasets loaded"
+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
+ grep "status: NOERROR" dig.out > /dev/null || ret=1
+done
+[ $ret -eq 0 ] && break
+sleep 1
+done
+
+echo_i "checking format transitions: text->raw->map->text"
+ret=0
+./named-compilezone -D -f text -F text -o baseline.txt example.nil ns1/example.db > /dev/null
+./named-compilezone -D -f text -F raw -o raw.1 example.nil baseline.txt > /dev/null
+./named-compilezone -D -f raw -F map -o map.1 example.nil raw.1 > /dev/null
+./named-compilezone -D -f map -F text -o text.1 example.nil map.1 > /dev/null
+cmp -s baseline.txt text.1 || ret=0
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking format transitions: text->map->raw->text"
+ret=0
+./named-compilezone -D -f text -F map -o map.2 example.nil baseline.txt > /dev/null
+./named-compilezone -D -f map -F raw -o raw.2 example.nil map.2 > /dev/null
+./named-compilezone -D -f raw -F text -o text.2 example.nil raw.2 > /dev/null
+cmp -s baseline.txt text.2 || ret=0
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking map format loading with journal file rollforward"
+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 $DIGOPTS @10.53.0.3 newtext.dynamic txt > dig.out.dynamic.3.1
+grep "added text" dig.out.dynamic.3.1 > /dev/null 2>&1 || ret=1
+$DIG $DIGOPTS +comm @10.53.0.3 added.dynamic txt > dig.out.dynamic.3.2
+grep "NXDOMAIN" dig.out.dynamic.3.2 > /dev/null 2>&1 || ret=1
+# using "rndc halt" ensures that we don't dump the zone file
+$RNDCCMD 10.53.0.3 halt 2>&1 | sed 's/^/ns3 /' | cat_i
+restart
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ lret=0
+ $DIG $DIGOPTS @10.53.0.3 newtext.dynamic txt > dig.out.dynamic.3.3
+ grep "added text" dig.out.dynamic.3.3 > /dev/null 2>&1 || lret=1
+ [ $lret -eq 0 ] && break;
+done
+[ $lret -eq 1 ] && ret=1
+$DIG $DIGOPTS +comm @10.53.0.3 added.dynamic txt > dig.out.dynamic.3.4
+grep "NXDOMAIN" dig.out.dynamic.3.4 > /dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking map format file dumps correctly"
+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 $DIGOPTS @10.53.0.3 moretext.dynamic txt > dig.out.dynamic.3.5
+grep "more text" dig.out.dynamic.3.5 > /dev/null 2>&1 || ret=1
+# using "rndc stop" will cause the zone file to flush before shutdown
+$RNDCCMD 10.53.0.3 stop 2>&1 | sed 's/^/ns3 /' | cat_i
+rm ns3/*.jnl
+restart
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ lret=0
+ $DIG $DIGOPTS +comm @10.53.0.3 moretext.dynamic txt > dig.out.dynamic.3.6
+ grep "more text" dig.out.dynamic.3.6 > /dev/null 2>&1 || lret=1
+ [ $lret -eq 0 ] && break;
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+# stomp on the file header
+echo_i "checking corrupt map files fail to load (bad file header)"
+ret=0
+./named-compilezone -D -f text -F map -o map.5 example.nil baseline.txt > /dev/null
+cp map.5 badmap
+stomp badmap 0 32 99
+./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null
+[ $? = 1 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+# stomp on the file data so it hashes differently.
+# these are small and subtle changes, so that the resulting file
+# would appear to be a legitimate map file and would not trigger an
+# assertion failure if loaded into memory, but should still fail to
+# load because of a SHA1 hash mismatch.
+echo_i "checking corrupt map files fail to load (bad node header)"
+ret=0
+cp map.5 badmap
+stomp badmap 2754 2 99
+./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null
+[ $? = 1 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking corrupt map files fail to load (bad node data)"
+ret=0
+cp map.5 badmap
+stomp badmap 2897 5 127
+./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null
+[ $? = 1 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking map format zone is scheduled for resigning (compilezone)"
+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
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking map format zone is scheduled for resigning (signzone)"
+ret=0
+$RNDCCMD 10.53.0.1 freeze signed > rndc.out 2>&1 || ret=1
+cd ns1
+$SIGNER -S -O map -f signed.db.map -o signed signed.db > /dev/null 2>&1
+cd ..
+$RNDCCMD 10.53.0.1 reload signed > rndc.out 2>&1 || ret=1
+$RNDCCMD 10.53.0.1 zonestatus signed > rndc.out 2>&1 || ret=1
+grep 'next resign' rndc.out > /dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/metadata/child.db b/bin/tests/system/metadata/child.db
new file mode 100644
index 0000000..2905a56
--- /dev/null
+++ b/bin/tests/system/metadata/child.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..af83095
--- /dev/null
+++ b/bin/tests/system/metadata/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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..6c6567f
--- /dev/null
+++ b/bin/tests/system/metadata/parent.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/metadata/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/metadata/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/metadata/setup.sh b/bin/tests/system/metadata/setup.sh
new file mode 100644
index 0000000..ae5b11f
--- /dev/null
+++ b/bin/tests/system/metadata/setup.sh
@@ -0,0 +1,63 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL ./clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+pzone=parent.nil
+czone=child.parent.nil
+
+echo_i "generating keys"
+
+# active zsk
+zsk=`$KEYGEN -q -r $RANDFILE $czone`
+echo $zsk > zsk.key
+
+# not yet published or active
+pending=`$KEYGEN -q -r $RANDFILE -P none -A none $czone`
+echo $pending > pending.key
+
+# published but not active
+standby=`$KEYGEN -q -r $RANDFILE -A none $czone`
+echo $standby > standby.key
+
+# inactive
+inact=`$KEYGEN -q -r $RANDFILE -P now-24h -A now-24h -I now $czone`
+echo $inact > inact.key
+
+# active ksk
+ksk=`$KEYGEN -q -r $RANDFILE -fk $czone`
+echo $ksk > ksk.key
+
+# published but not YET active; will be active in 15 seconds
+rolling=`$KEYGEN -q -r $RANDFILE -fk $czone`
+$SETTIME -A now+15s $rolling > /dev/null
+echo $rolling > rolling.key
+
+# revoked
+revoke1=`$KEYGEN -q -r $RANDFILE -fk $czone`
+echo $revoke1 > prerev.key
+revoke2=`$REVOKE $revoke1`
+echo $revoke2 | sed -e 's#\./##' -e "s/\.key.*$//" > postrev.key
+
+pzsk=`$KEYGEN -q -r $RANDFILE $pzone`
+echo $pzsk > parent.zsk.key
+
+pksk=`$KEYGEN -q -r $RANDFILE -fk $pzone`
+echo $pksk > parent.ksk.key
+
+oldstyle=`$KEYGEN -Cq -r $RANDFILE $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..5eb0938
--- /dev/null
+++ b/bin/tests/system/metadata/tests.sh
@@ -0,0 +1,211 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < inact.key`
+ksk=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < ksk.key`
+pending=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < pending.key`
+postrev=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < postrev.key`
+prerev=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < prerev.key`
+rolling=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < rolling.key`
+standby=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < standby.key`
+zsk=`sed 's/^K'${czone}'.+005+0*\([0-9]\)/\1/' < zsk.key`
+
+echo_i "signing zones"
+$SIGNER -Sg -o $czone $cfile > /dev/null 2>&1
+$SIGNER -Sg -o $pzone $pfile > /dev/null 2>&1
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that ZSK signed ($n)"
+ret=0
+grep "SOA $zsk"'$' sigs > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that standby ZSK did not sign ($n)"
+ret=0
+grep " $standby"'$' sigs > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that inactive key did not sign ($n)"
+ret=0
+grep " $inact"'$' sigs > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that pending key was not published ($n)"
+ret=0
+grep " $pending"'$' keys > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+egrep "DS[ ]*$rolling[ ]" ${pfile}.signed > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 2>&1
+
+echo_i "checking that standby KSK is now active ($n)"
+ret=0
+grep "DNSKEY $rolling"'$' sigs > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking warning about permissions change on key with dnssec-settime ($n)"
+uname=`uname -o 2> /dev/null`
+if [ Cygwin == "$uname" ]; then
+ echo_i "Cygwin detected, skipping"
+else
+ 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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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 -r $RANDFILE -I now+15s -D now $czone > tmp.out 2>&1 || ret=1
+grep "warning" tmp.out > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking correct behavior setting activation without publication date ($n)"
+ret=0
+key=`$KEYGEN -q -r $RANDFILE -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 -r $RANDFILE -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 -r $RANDFILE -A +1w -P never $czone`
+pub=`$SETTIME -upP $key | awk '{print $2}'`
+[ $pub = "UNSET" ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking calculation of dates for a successor key ($n)"
+ret=0
+oldkey=`$KEYGEN -q -r $RANDFILE $czone`
+newkey=`$KEYGEN -q -r $RANDFILE $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/mkeys/README b/bin/tests/system/mkeys/README
new file mode 100644
index 0000000..700e6c2
--- /dev/null
+++ b/bin/tests/system/mkeys/README
@@ -0,0 +1,18 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This is for testing managed-keys, in particular with problems
+with 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 key in managed-keys.
+
+ns5 is a validator which is prevented from getting a response from the
+root server, causing key refresh queries to fail.
diff --git a/bin/tests/system/mkeys/clean.sh b/bin/tests/system/mkeys/clean.sh
new file mode 100644
index 0000000..17bd50f
--- /dev/null
+++ b/bin/tests/system/mkeys/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */*.signed */trusted.conf */*.jnl */*.bk
+rm -f dsset-. ns1/dsset-.
+rm -f ns*/named.lock
+rm -f */managed-keys.bind* */named.secroots
+rm -f */managed.conf ns1/managed.key ns1/managed.key.id
+rm -f */named.memstats */named.run */named.run.prev
+rm -f dig.out* delv.out* rndc.out* signer.out*
+rm -f ns1/named.secroots ns1/root.db.signed* ns1/root.db.tmp
+rm -f */named.conf
+rm -f ns5/named.args
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..412556b
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/named1.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+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-enable yes;
+ dnssec-validation yes;
+ allow-query { allowed; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db.signed";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
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..5cb096b
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/named2.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+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-enable yes;
+ dnssec-validation yes;
+ allow-query { allowed; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.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..a0f1dd3
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/named3.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.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..6ba922a
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/root.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 20
+. IN SOA 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."
diff --git a/bin/tests/system/mkeys/ns1/sign.sh b/bin/tests/system/mkeys/ns1/sign.sh
new file mode 100644
index 0000000..ccc7889
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/sign.sh
@@ -0,0 +1,37 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+zonefile=root.db
+
+keyname=`$KEYGEN -qfk -r $RANDFILE $zone`
+zskkeyname=`$KEYGEN -q -r $RANDFILE $zone`
+
+$SIGNER -Sg -r $RANDFILE -o $zone $zonefile > /dev/null 2>/dev/null
+
+# Configure the resolving server with a managed trusted key.
+keyfile_to_managed_keys $keyname > managed.conf
+cp managed.conf ../ns2/managed.conf
+cp managed.conf ../ns5/managed.conf
+
+# Configure a trusted key statement (used by delv)
+keyfile_to_trusted_keys $keyname > trusted.conf
+
+#
+# Save keyname and keyid for managed key id test.
+#
+echo "$keyname" > managed.key
+keyid=`expr $keyname : 'K\.+00.+\([0-9]*\)'`
+keyid=`expr $keyid + 0`
+echo "$keyid" > managed.key.id
diff --git a/bin/tests/system/mkeys/ns2/named.args b/bin/tests/system/mkeys/ns2/named.args
new file mode 100644
index 0000000..5c5a6b2
--- /dev/null
+++ b/bin/tests/system/mkeys/ns2/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -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..9076243
--- /dev/null
+++ b/bin/tests/system/mkeys/ns2/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ servfail-ttl 0;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..02f8f67
--- /dev/null
+++ b/bin/tests/system/mkeys/ns3/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -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..0227aba
--- /dev/null
+++ b/bin/tests/system/mkeys/ns3/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ bindkeys-file "managed.conf";
+ trust-anchor-telemetry no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+# purposely broken key for testing
+managed-keys {
+ "." initial-key 257 3 5 "PURPOSELYBROKEN/xs9iVj7QekClcpzjCf0JrvXW1z07hNMqMm6Q2FtIXMbRgfvTtHF3/ZNvcewT9hpfczC+JACHsQSYYdr7UI8oe4nJfal9+2F3pz4a+HR6CqkgrR6WLWQI1Q==";
+};
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..f2eb35d
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/mkeys/ns5/named1.args b/bin/tests/system/mkeys/ns5/named1.args
new file mode 100644
index 0000000..efb102a
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/named1.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g
diff --git a/bin/tests/system/mkeys/ns5/named2.args b/bin/tests/system/mkeys/ns5/named2.args
new file mode 100644
index 0000000..d222b7f
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/named2.args
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -T mkeytimers=2/20/40
diff --git a/bin/tests/system/mkeys/prereq.sh b/bin/tests/system/mkeys/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/mkeys/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/mkeys/setup.sh b/bin/tests/system/mkeys/setup.sh
new file mode 100644
index 0000000..bd3169f
--- /dev/null
+++ b/bin/tests/system/mkeys/setup.sh
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+
+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 ns5/named.conf.in ns5/named.conf
+
+cp ns5/named1.args ns5/named.args
+
+( cd ns1 && $SHELL sign.sh )
diff --git a/bin/tests/system/mkeys/tests.sh b/bin/tests/system/mkeys/tests.sh
new file mode 100644
index 0000000..f65f49e
--- /dev/null
+++ b/bin/tests/system/mkeys/tests.sh
@@ -0,0 +1,714 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+DELVOPTS="-a ns1/trusted.conf -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+wait_for_log() {
+ msg=$1
+ file=$2
+ for i in 1 2 3 4 5 6 7 8 9 10; do
+ nextpart "$file" | grep "$msg" > /dev/null && return
+ sleep 1
+ done
+ echo_i "exceeded time limit waiting for '$msg' in $file"
+ ret=1
+}
+
+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
+ $RNDCCMD 10.53.0.${nsidx} reload . | sed "s/^/ns${nsidx} /" | cat_i
+ wait_for_log "loaded serial" ns${nsidx}/named.run
+}
+
+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 "next key event" ns${nsidx}/named.run
+}
+
+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 "Returned from key fetch in keyfetch_done()" ns${nsidx}/named.run
+}
+
+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
+ $RNDCCMD 10.53.0.${nsidx} managed-keys sync | sed "s/^/ns${nsidx} /" | cat_i
+}
+
+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 $DIGOPTS +norec example. @10.53.0.1 TXT > dig.out.ns1.test$n || ret=1
+grep "^example\.[ ]*[0-9].*[ ]*IN[ ]*TXT[ ]*\"This is a test\.\"" dig.out.ns1.test$n > /dev/null || ret=1
+grep "^example\.[ ]*[0-9].*[ ]*IN[ ]*RRSIG[ ]*TXT[ ]" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check positive validation with valid trust anchor ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+ret=0
+echo_i "check positive validation using delv ($n)"
+$DELV $DELVOPTS @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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check for failed validation due to wrong key in managed-keys ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check new trust anchor can be added ($n)"
+ret=0
+standby1=`$KEYGEN -qfk -r $RANDFILE -K ns1 .`
+mkeys_loadkeys_on 1
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# there should be two keys listed now
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# one indicates current trust
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# one indicates pending trust
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check new trust anchor can't be added with bad initial key ($n)"
+ret=0
+mkeys_refresh_on 3
+mkeys_status_on 3 > rndc.out.$n 2>&1
+# there should be one key listed now
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# one line indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# ... and the key is not trusted
+count=`grep -c "no trust" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "remove untrusted standby key, check timer restarts ($n)"
+ret=0
+mkeys_sync_on 2
+t1=`grep "trust pending" ns2/managed-keys.bind`
+$SETTIME -D now -K ns1 $standby1 > /dev/null
+mkeys_loadkeys_on 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
+mkeys_sync_on 2
+t2=`grep "trust pending" ns2/managed-keys.bind`
+# trust pending date must be different
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+# 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
+mkeys_sync_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=`grep "trust pending" ns2/managed-keys.bind`
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+mkeys_sync_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=`grep "trust pending" ns2/managed-keys.bind`
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+$SETTIME -D none -K ns1 $original > /dev/null
+mkeys_loadkeys_on 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
+mkeys_sync_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=`grep "trust pending" ns2/managed-keys.bind`
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "reinitialize trust anchors"
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns2
+rm -f ns2/managed-keys.bind*
+nextpart ns2/named.run > /dev/null
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns2
+
+n=`expr $n + 1`
+echo_i "check that standby key is now trusted ($n)"
+ret=0
+wait_for_log "Returned from key fetch in keyfetch_done()" ns2/named.run
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# both indicate current trust
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "revoke original key, add new standby ($n)"
+ret=0
+standby2=`$KEYGEN -qfk -r $RANDFILE -K ns1 .`
+$SETTIME -R now -K ns1 $original > /dev/null
+mkeys_loadkeys_on 1
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# three keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 3 ] || ret=1
+# one is revoked
+count=`grep -c "REVOKE" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# three lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 3 ] || ret=1
+# one indicates current trust
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# one indicates revoked trust
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# one indicates trust pending
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "revoke standby before it is trusted ($n)"
+ret=0
+standby3=`$KEYGEN -qfk -r $RANDFILE -K ns1 .`
+mkeys_loadkeys_on 1
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.a.$n 2>&1
+# four keys listed
+count=`grep -c "keyid: " rndc.out.a.$n`
+[ "$count" -eq 4 ] || { echo "keyid: count ($count) != 4"; ret=1; }
+# one revoked
+count=`grep -c "trust revoked" rndc.out.a.$n`
+[ "$count" -eq 1 ] || { echo "trust revoked count ($count) != 1"; ret=1; }
+# two pending
+count=`grep -c "trust pending" rndc.out.a.$n`
+[ "$count" -eq 2 ] || { echo "trust pending count ($count) != 2"; ret=1; }
+$SETTIME -R now -K ns1 $standby3 > /dev/null
+mkeys_loadkeys_on 1
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.b.$n 2>&1
+# now three keys listed
+count=`grep -c "keyid: " rndc.out.b.$n`
+[ "$count" -eq 3 ] || { echo "keyid: count ($count) != 3"; ret=1; }
+# one revoked
+count=`grep -c "trust revoked" rndc.out.b.$n`
+[ "$count" -eq 1 ] || { echo "trust revoked count ($count) != 1"; ret=1; }
+# one pending
+count=`grep -c "trust pending" rndc.out.b.$n`
+[ "$count" -eq 1 ] || { echo "trust pending count ($count) != 1"; ret=1; }
+$SETTIME -D now -K ns1 $standby3 > /dev/null
+mkeys_loadkeys_on 1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "wait 20 seconds for key add/remove holddowns to expire ($n)"
+ret=0
+sleep 20
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# none revoked
+count=`grep -c "REVOKE" rndc.out.$n`
+[ "$count" -eq 0 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# both indicate current trust
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# both revoked
+count=`grep -c "REVOKE" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# both indicate trust revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+# both have removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check for insecure response ($n)"
+ret=0
+mkeys_refresh_on 2
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+echo_i "reset the root server"
+$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
+$SIGNER -Sg -K ns1 -N unixtime -r $RANDFILE -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
+
+echo_i "reinitialize trust anchors"
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} . ns2
+rm -f ns2/managed-keys.bind*
+nextpart ns2/named.run > /dev/null
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns2
+
+n=`expr $n + 1`
+echo_i "check positive validation ($n)"
+ret=0
+wait_for_log "Returned from key fetch in keyfetch_done()" ns2/named.run
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "revoke key with bad signature, check revocation is ignored ($n)"
+ret=0
+revoked=`$REVOKE -K ns1 $original`
+rkeyid=`expr $revoked : 'ns1/K\.+00.+0*\([1-9]*[0-9]*[0-9]\)'`
+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 -r $RANDFILE -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
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# one key listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 1 ] || { echo "'keyid:' count ($count) != 1"; ret=1; }
+# it's the original key id
+count=`grep -c "keyid: $originalid" rndc.out.$n`
+[ "$count" -eq 1 ] || { echo "'keyid: $originalid' count ($count) != 1"; ret=1; }
+# not revoked
+count=`grep -c "REVOKE" rndc.out.$n`
+[ "$count" -eq 0 ] || { echo "'REVOKE' count ($count) != 0"; ret=1; }
+# trust is still current
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 1 ] || { echo "'trust' count != 1"; ret=1; }
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 1 ] || { echo "'trusted since' count != 1"; ret=1; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check validation fails with bad DNSKEY rrset ($n)"
+ret=0
+mkeys_flush_on 2
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $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 -r $RANDFILE -o . ns1/root.db > /dev/null 2>/dev/null
+mkeys_reload_on 1
+mkeys_flush_on 2
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $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
+mkeys_status_on 2 > rndc.out.$n 2>&1
+t1=`grep 'next refresh:' rndc.out.$n`
+$PERL $SYSTEMTESTTOP/stop.pl --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
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1
+wait_for_log "loaded serial" ns1/named.run
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# one key listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# it's the original key id
+count=`grep -c "keyid: $originalid" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# not revoked
+count=`grep -c "REVOKE" rndc.out.$n`
+[ "$count" -eq 0 ] || ret=1
+# trust is still current
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+t2=`grep 'next refresh:' rndc.out.$n`
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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
+mkeys_status_on 2 > rndc.out.$n 2>&1
+t1=`grep 'next refresh:' rndc.out.$n`
+$PERL $SYSTEMTESTTOP/stop.pl --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
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1
+wait_for_log "loaded serial" ns1/named.run
+# 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
+mkeys_status_on 2 > rndc.out.$n 2>&1
+# one key listed
+count=`grep -c "keyid: " rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# it's the original key id
+count=`grep -c "keyid: $originalid" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# not revoked
+count=`grep -c "REVOKE" rndc.out.$n`
+[ "$count" -eq 0 ] || ret=1
+# trust is still current
+count=`grep -c "trust" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+count=`grep -c "trusted since" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+t2=`grep 'next refresh:' rndc.out.$n`
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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 -r $RANDFILE -o . ns1/root.db > /dev/null 2>/dev/null
+mkeys_reload_on 1
+mkeys_refresh_on 2
+mkeys_status_on 2 > rndc.out.$n 2>&1
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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/'`
+tatkey=`$PERL -e 'printf("%d\n", hex(@ARGV[0]));' $tathex`
+realkey=`$RNDCCMD 10.53.0.2 secroots - | sed -n 's#.*SHA1/\([0-9][0-9]*\) ; .*managed.*#\1#p'`
+[ "$tatkey" -eq "$realkey" ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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.
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} . ns5
+nextpart ns5/named.run > /dev/null
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns5
+wait_for_log "Returned from key fetch in keyfetch_done()" ns5/named.run
+# 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`
+[ $count -lt 2 ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check key refreshes are resumed after root servers become available ($n)"
+ret=0
+$PERL $SYSTEMTESTTOP/stop.pl --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
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns5
+wait_for_log "Returned from key fetch in keyfetch_done() for '.': failure" ns5/named.run
+# ns1 should still REFUSE queries from ns5, so resolving should be impossible
+$DIG $DIGOPTS +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
+wait_for_log "Returned from key fetch in keyfetch_done() for '.': success" ns5/named.run
+# ns1 should not longer REFUSE queries from ns5, so managed keys should be
+# correctly refreshed and resolving should succeed
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/names/clean.sh b/bin/tests/system/names/clean.sh
new file mode 100644
index 0000000..b7e34eb
--- /dev/null
+++ b/bin/tests/system/names/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
diff --git a/bin/tests/system/names/ns1/example.db b/bin/tests/system/names/ns1/example.db
new file mode 100644
index 0000000..0ce948a
--- /dev/null
+++ b/bin/tests/system/names/ns1/example.db
@@ -0,0 +1,49 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..f885cc9
--- /dev/null
+++ b/bin/tests/system/names/ns1/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+
+view compress {
+ match-clients { 10.53.0.1/32; };
+ zone "example" {
+ type master;
+ file "example.db";
+ };
+};
+
+view nocompress {
+ match-clients { 10.53.0.2/32; };
+ message-compression no;
+ zone "example" {
+ type master;
+ 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..a3c89c8
--- /dev/null
+++ b/bin/tests/system/names/setup.sh
@@ -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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/names/tests.sh b/bin/tests/system/names/tests.sh
new file mode 100644
index 0000000..2320226
--- /dev/null
+++ b/bin/tests/system/names/tests.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+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=$?
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "Checking if message with compression disabled is significantly larger"
+echo_i "Disabled $COMPDIS vs enabled $COMPEN"
+val=`expr \( $COMPDIS \* 3 / 2 \) / $COMPEN`
+if [ $val -le 1 ]; then
+ echo_i "failed"
+ status=`expr $status + 1`
+fi;
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/notify/clean.sh b/bin/tests/system/notify/clean.sh
new file mode 100644
index 0000000..7f0b407
--- /dev/null
+++ b/bin/tests/system/notify/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f */named.memstats
+rm -f */named.run */named.run.prev
+rm -f */named.conf
+rm -f */named.port
+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*/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..b4a2fa8
--- /dev/null
+++ b/bin/tests/system/notify/ns1/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/notify/ns1/root.db b/bin/tests/system/notify/ns1/root.db
new file mode 100644
index 0000000..dab5cea
--- /dev/null
+++ b/bin/tests/system/notify/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..38dd443
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example1.db
@@ -0,0 +1,142 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..5de0776
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example2.db
@@ -0,0 +1,142 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..01befbc
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example3.db
@@ -0,0 +1,142 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..9ff70f8
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example4.db
@@ -0,0 +1,142 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..fc688ab
--- /dev/null
+++ b/bin/tests/system/notify/ns2/generic.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2e5bd28
--- /dev/null
+++ b/bin/tests/system/notify/ns2/named.conf.in
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ startup-notify-rate 5;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ // Check that named can handle a empty also-notify.
+ also-notify { /* empty */ };
+};
+
+masters noport { 10.53.0.4; };
+
+masters x21 port @EXTRAPORT1@ { noport; };
+
+zone x1 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x2 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x3 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x4 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x5 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x6 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x7 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x8 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x9 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x10 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x11 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x12 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x13 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x14 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x15 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x16 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x17 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x18 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x19 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x20 { type master; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x21 { type master; 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..70d90ae
--- /dev/null
+++ b/bin/tests/system/notify/ns3/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
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..607cdda
--- /dev/null
+++ b/bin/tests/system/notify/ns4/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "x21" {
+ type slave;
+ masters { 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..cfcfe8f
--- /dev/null
+++ b/bin/tests/system/notify/ns5/named.conf.in
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ acache-enable yes;
+ notify yes;
+};
+
+view "a" {
+ match-clients { key "a"; };
+ zone "x21" {
+ type master;
+ 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 slave;
+ masters { 10.53.0.5 key "a"; };
+ file "x21.bk-b";
+ notify no;
+ };
+};
+
+view "c" {
+ match-clients { key "c"; };
+ zone "x21" {
+ type slave;
+ masters { 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..e380043
--- /dev/null
+++ b/bin/tests/system/notify/ns5/x21.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3af216c
--- /dev/null
+++ b/bin/tests/system/notify/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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 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..ad20e3e
--- /dev/null
+++ b/bin/tests/system/notify/tests.sh
@@ -0,0 +1,212 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+#
+# 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 'x[0-9].*sending notify to' ns2/named.run | wc -l`
+ [ $nr -eq 20 ] || ret=1
+ [ $ret = 0 ] && break
+ sleep 1
+done
+
+n=`expr $n + 1`
+echo_i "checking initial status ($n)"
+ret=0
+$DIG $DIGOPTS 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 $DIGOPTS 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
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking startup notify rate limit ($n)"
+ret=0
+grep 'x[0-9].*sending notify to' ns2/named.run |
+ sed 's/.*:\([0-9][0-9]\)\..*/\1/' | uniq -c | awk '{print $1}' > log.out
+# the notifies should span at least 4 seconds
+wc -l log.out | awk '$1 < 4 { exit(1) }' || ret=1
+# ... with no more than 5 in any one second
+awk '$1 > 5 { exit(1) }' log.out || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+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
+if [ ! "$CYGWIN" ]; then
+ echo_i "reloading with example2 using HUP and waiting up to 45 seconds"
+ $KILL -HUP `cat ns2/named.pid`
+else
+ echo_i "reloading with example2 using rndc and waiting up to 45 seconds"
+ $RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/I:ns2 /'
+fi
+
+try=0
+while test $try -lt 45
+do
+ nextpart ns3/named.run > tmp
+ grep "transfer of 'example/IN' from 10.53.0.2#.*success" tmp > /dev/null && break
+ sleep 1
+ try=`expr $try + 1`
+done
+
+n=`expr $n + 1`
+echo_i "checking notify message was logged ($n)"
+ret=0
+grep 'notify from 10.53.0.2#[0-9][0-9]*: serial 2$' ns3/named.run > /dev/null || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking example2 loaded ($n)"
+ret=0
+$DIG $DIGOPTS 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
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking example2 contents have been transferred after HUP reload ($n)"
+ret=0
+$DIG $DIGOPTS 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 $DIGOPTS 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
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+echo_i "stopping master and restarting with example4 then waiting up to 45 seconds"
+$PERL $SYSTEMTESTTOP/stop.pl . ns2
+
+rm -f ns2/example.db
+cp -f ns2/example4.db ns2/example.db
+
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns2
+
+try=0
+while test $try -lt 45
+do
+ nextpart ns3/named.run > tmp
+ grep "transfer of 'example/IN' from 10.53.0.2#.*success" tmp > /dev/null && break
+ sleep 1
+ try=`expr $try + 1`
+done
+
+n=`expr $n + 1`
+echo_i "checking notify message was logged ($n)"
+ret=0
+grep 'notify from 10.53.0.2#[0-9][0-9]*: serial 4$' ns3/named.run > /dev/null || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking example4 loaded ($n)"
+ret=0
+$DIG $DIGOPTS 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
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking example4 contents have been transfered after restart ($n)"
+ret=0
+$DIG $DIGOPTS 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 $DIGOPTS 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
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking notify to alternate port with master inheritance ($n)"
+$NSUPDATE << EOF
+server 10.53.0.2 ${PORT}
+zone x21
+update add added.x21 0 in txt "test string"
+send
+EOF
+for i in 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS added.x21. @10.53.0.4 txt -p $EXTRAPORT1 > dig.out.ns4.test$n || ret=1
+ grep "test string" dig.out.ns4.test$n > /dev/null && break
+ sleep 1
+done
+grep "test string" dig.out.ns4.test$n > /dev/null || ret=1
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+n=`expr $n + 1`
+echo_i "checking notify to multiple views using tsig ($n)"
+ret=0
+$NSUPDATE << EOF
+server 10.53.0.5 ${PORT}
+zone x21
+key a aaaaaaaaaaaaaaaaaaaa
+update add added.x21 0 in txt "test string"
+send
+EOF
+
+for i in 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS added.x21. -y b:bbbbbbbbbbbbbbbbbbbb @10.53.0.5 \
+ txt > dig.out.b.ns5.test$n || ret=1
+ $DIG $DIGOPTS added.x21. -y c:cccccccccccccccccccc @10.53.0.5 \
+ txt > dig.out.c.ns5.test$n || ret=1
+ grep "test string" dig.out.b.ns5.test$n > /dev/null &&
+ grep "test string" dig.out.c.ns5.test$n > /dev/null &&
+ break
+ sleep 1
+done
+grep "test string" dig.out.b.ns5.test$n > /dev/null || ret=1
+grep "test string" dig.out.c.ns5.test$n > /dev/null || ret=1
+
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $ret + $status`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/nslookup/clean.sh b/bin/tests/system/nslookup/clean.sh
new file mode 100644
index 0000000..46d78fa
--- /dev/null
+++ b/bin/tests/system/nslookup/clean.sh
@@ -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 http://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 ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.conf
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..e9c133b
--- /dev/null
+++ b/bin/tests/system/nslookup/ns1/example.net.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..2be830f
--- /dev/null
+++ b/bin/tests/system/nslookup/ns1/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "example.net" {
+ type master;
+ 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..8134fb6
--- /dev/null
+++ b/bin/tests/system/nslookup/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+$SHELL ../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..8630434
--- /dev/null
+++ b/bin/tests/system/nslookup/tests.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+n=`expr $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 > nslookup.out${n} || ret=1
+grep "origin = ns1.example" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Check A only lookup"
+ret=0
+$NSLOOKUP -port=${PORT} a-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep a-only.example.net nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Check AAAA only lookup"
+ret=0
+$NSLOOKUP -port=${PORT} aaaa-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep aaaa-only.example.net nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Check dual A + AAAA lookup"
+ret=0
+$NSLOOKUP -port=${PORT} dual.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep dual.example.net nslookup.out${n} | wc -l`
+test $lines = 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Check CNAME to A only lookup"
+ret=0
+$NSLOOKUP -port=${PORT} cname-a-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep "canonical name" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep a-only.example.net nslookup.out${n} | grep -v "canonical name" | wc -l`
+test $lines = 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Check CNAME to AAAA only lookup"
+ret=0
+$NSLOOKUP -port=${PORT} cname-aaaa-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep "canonical name" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep aaaa-only.example.net nslookup.out${n} | grep -v "canonical name" |wc -l`
+test $lines = 1 || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "Check CNAME to dual A + AAAA lookup"
+ret=0
+$NSLOOKUP -port=${PORT} cname-dual.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep "canonical name" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep dual.example.net nslookup.out${n} | grep -v "canonical name" | wc -l`
+test $lines = 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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/nsupdate/ans4/ans.pl b/bin/tests/system/nsupdate/ans4/ans.pl
new file mode 100644
index 0000000..6a4461b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ans4/ans.pl
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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 "$!";
+
+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;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ }
+}
diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh
new file mode 100644
index 0000000..c780219
--- /dev/null
+++ b/bin/tests/system/nsupdate/clean.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f verylarge
+rm -f */named.memstats
+rm -f */named.run */ans.run
+rm -f */named.conf
+rm -f Kxxx.*
+rm -f dig.out.*
+rm -f jp.out.ns3.*
+rm -f ns*/named.lock
+rm -f */*.jnl
+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/md5.key ns1/sha1.key ns1/sha224.key ns1/sha256.key ns1/sha384.key
+rm -f ns1/sha512.key ns1/ddns.key
+rm -f ns2/example.bk
+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/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/in-addr.db
+rm -f ns7/example.com.db
+rm -f ns7/_default.tsigkeys
+rm -f ns8/in-addr.db
+rm -f ns8/example.com.db
+rm -f ns8/_default.tsigkeys
+rm -f ns9/in-addr.db
+rm -f ns9/example.com.db
+rm -f ns9/_default.tsigkeys
+rm -f ns10/example.com.db
+rm -f ns10/in-addr.db
+rm -f ns10/_default.tsigkeys
+rm -f nsupdate.out*
+rm -f typelist.out.*
+rm -f ns1/sample.db
+rm -f ns2/sample.db
+rm -f update.out.*
+rm -f check.out.*
+rm -f update.out.*
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..3c37777
--- /dev/null
+++ b/bin/tests/system/nsupdate/krb/setup.sh
@@ -0,0 +1,113 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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=`expr 2147483647 - $now`
+lifetime=`expr $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.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..1ca6589
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/example1.db
@@ -0,0 +1,144 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/many.test.db.in b/bin/tests/system/nsupdate/ns1/many.test.db.in
new file mode 100644
index 0000000..2c84670
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/many.test.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+many.test 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)
+ )
+many.test NS ns1.example.nil.
+many.test 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..0250960
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/max-ttl.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/named.conf.in b/bin/tests/system/nsupdate/ns1/named.conf.in
new file mode 100644
index 0000000..1d999ad
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/named.conf.in
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1 dscp 1;
+ notify-source 10.53.0.1 dscp 22;
+ transfer-source 10.53.0.1 dscp 3;
+ 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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key altkey {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+include "ddns.key";
+
+zone "example.nil" {
+ type master;
+ file "example.db";
+ check-integrity no;
+ check-mx ignore;
+ update-policy {
+ grant ddns-key.example.nil subdomain example.nil ANY;
+ };
+ allow-transfer { any; };
+};
+
+zone "max-ttl.nil" {
+ type master;
+ file "max-ttl.db";
+ max-zone-ttl 300;
+ check-integrity no;
+ allow-update { any; };
+ allow-transfer { any; };
+};
+
+zone "other.nil" {
+ type master;
+ file "other.db";
+ check-integrity no;
+ check-mx warn;
+ update-policy local;
+ allow-query-on { 10.53.0.1; 127.0.0.1; };
+ allow-transfer { any; };
+};
+
+masters othermasters {
+ 10.53.0.2 port @PORT@;
+ 10.53.0.2 port @PORT@ key altkey;
+};
+
+zone "update.nil" {
+ type master;
+ file "update.db";
+ check-integrity no;
+ check-mx fail;
+ allow-update { any; };
+ allow-transfer { any; };
+ also-notify { othermasters; };
+};
+
+zone "unixtime.nil" {
+ type master;
+ file "unixtime.db";
+ check-integrity no;
+ allow-update { any; };
+ allow-transfer { any; };
+ serial-update-method unixtime;
+};
+
+zone "yyyymmddvv.nil" {
+ type master;
+ 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";
+
+zone "keytests.nil" {
+ type master;
+ 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;
+ };
+};
+
+zone "many.test" {
+ type master;
+ allow-update { any; };
+ file "many.test.db";
+};
+
+zone "sample" {
+ type master;
+ allow-update { any; };
+ file "sample.db";
+};
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..49212a1
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/sample.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..984274b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/example.com.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
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..984274b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/in-addr.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
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..44b207a
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.10 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type master;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM ms-subdomain . PTR; };
+};
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM ms-selfsub . ANY;
+ grant EXAMPLE.COM ms-subdomain _tcp.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..b4ecf96
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns2/named.conf.in
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2 dscp 4;
+ notify-source 10.53.0.2 dscp 5;
+ transfer-source 10.53.0.2 dscp 6;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+ serial-query-rate 1; // workaround for KB AA-01213
+};
+
+key altkey {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+view alternate {
+ match-clients { key altkey; };
+
+ zone "update.nil" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "update.alt.bk";
+ allow-transfer { any; };
+ };
+};
+
+view primary {
+ match-clients { any; };
+
+ zone "example.nil" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "example.bk";
+ allow-transfer { any; };
+ };
+
+ zone "update.nil" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "update.bk";
+ allow-transfer { any; };
+ };
+
+ zone "sample" {
+ type master;
+ 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..0c8a1c0
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns2/sample.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..a75bcd2
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/delegation.test.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..d3393a2
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/dnskey.test.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..e151333
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/example.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+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/named.conf.in b/bin/tests/system/nsupdate/ns3/named.conf.in
new file mode 100644
index 0000000..e5b414f
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/named.conf.in
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.3 dscp 7;
+ notify-source 10.53.0.3 dscp 8;
+ transfer-source 10.53.0.3 dscp 9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "example" {
+ type master;
+ allow-update { any; };
+ file "example.db";
+};
+
+zone "nsec3param.test" {
+ type master;
+ allow-update { any; };
+ file "nsec3param.test.db.signed";
+};
+
+zone "dnskey.test" {
+ type master;
+ allow-update { any; };
+ file "dnskey.test.db.signed";
+};
+
+zone "many.test" {
+ type slave;
+ masters { 10.53.0.1; };
+ allow-update-forwarding { any; };
+ file "many.test.bk";
+};
+
+zone "delegation.test" {
+ type master;
+ allow-update { any; };
+ file "delegation.test.db.signed";
+};
+
+zone "too-big.test" {
+ type master;
+ allow-update { any; };
+ max-records 3;
+ file "too-big.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..6969414
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/nsec3param.test.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4e6e645
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/sign.sh
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=nsec3param.test.
+infile=nsec3param.test.db.in
+zonefile=nsec3param.test.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -f KSK $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -3 - -H 1 -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+zone=dnskey.test.
+infile=dnskey.test.db.in
+zonefile=dnskey.test.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+zone=delegation.test.
+infile=delegation.test.db.in
+zonefile=delegation.test.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -3 -f KSK $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -3 $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -A -3 - -P -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
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..f271d27
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/too-big.test.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..08f16b8
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns5/local.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..49cb45e
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns5/named.args
@@ -0,0 +1 @@
+-D nsupdate-ns5 -m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -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..2ffacb1
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns5/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "local.nil" {
+ type master;
+ 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..c719192
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns6/in-addr.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..75ca529
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns6/named.args
@@ -0,0 +1 @@
+-D nsupdate-ns6 -m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -U 4 -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..da64d06
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns6/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type master;
+ file "in-addr.db";
+ update-policy { grant * tcp-self . PTR; };
+};
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..c327325
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/example.com.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
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..c327325
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/in-addr.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
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/named.conf.in b/bin/tests/system/nsupdate/ns7/named.conf.in
new file mode 100644
index 0000000..f0ef6d3
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type master;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM krb5-subdomain . PTR; };
+};
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM krb5-self . ANY;
+ grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV;
+ };
+};
diff --git a/bin/tests/system/nsupdate/ns8/dns.keytab b/bin/tests/system/nsupdate/ns8/dns.keytab
new file mode 100644
index 0000000..3340049
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/dns.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..eb24766
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/example.com.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..eb24766
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/in-addr.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..56195cd
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type master;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM krb5-subdomain . PTR; };
+};
+
+zone "example.com" {
+ type master;
+ 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..a618fdc
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/example.com.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..a618fdc
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/in-addr.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..1b41cc6
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type master;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM ms-subdomain . PTR; };
+};
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM ms-self . ANY;
+ grant EXAMPLE.COM ms-subdomain _tcp.example.com SRV;
+ };
+};
diff --git a/bin/tests/system/nsupdate/prereq.sh b/bin/tests/system/nsupdate/prereq.sh
new file mode 100644
index 0000000..9c1d276
--- /dev/null
+++ b/bin/tests/system/nsupdate/prereq.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION >= 0.69 && $Net::DNS::VERSION <= 0.70);' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS versions 0.69 to 0.70 have bugs that cause this test to fail: please update." >&2
+ exit 1
+ fi
+fi
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh
new file mode 100644
index 0000000..d6647fa
--- /dev/null
+++ b/bin/tests/system/nsupdate/setup.sh
@@ -0,0 +1,90 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+$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/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 verylarge.in verylarge
+
+#
+# jnl and database files MUST be removed before we start
+#
+
+rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk
+rm -f ns2/update.bk ns2/update.alt.bk
+rm -f ns3/example.db.jnl
+rm -f ns3/too-big.test.db.jnl
+
+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
+
+$DDNSCONFGEN -q -r $RANDFILE -z example.nil > ns1/ddns.key
+
+$DDNSCONFGEN -q -r $RANDFILE -a hmac-md5 -k md5-key -z keytests.nil > ns1/md5.key
+$DDNSCONFGEN -q -r $RANDFILE -a hmac-sha1 -k sha1-key -z keytests.nil > ns1/sha1.key
+$DDNSCONFGEN -q -r $RANDFILE -a hmac-sha224 -k sha224-key -z keytests.nil > ns1/sha224.key
+$DDNSCONFGEN -q -r $RANDFILE -a hmac-sha256 -k sha256-key -z keytests.nil > ns1/sha256.key
+$DDNSCONFGEN -q -r $RANDFILE -a hmac-sha384 -k sha384-key -z keytests.nil > ns1/sha384.key
+$DDNSCONFGEN -q -r $RANDFILE -a hmac-sha512 -k sha512-key -z keytests.nil > ns1/sha512.key
+
+(cd ns3; $SHELL -e sign.sh)
+
+cp -f ns1/many.test.db.in ns1/many.test.db
+rm -f ns1/many.test.db.jnl
+
+cp ns1/sample.db.in ns1/sample.db
+cp ns2/sample.db.in ns2/sample.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 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..9f26572
--- /dev/null
+++ b/bin/tests/system/nsupdate/tests.sh
@@ -0,0 +1,1253 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+#
+# 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
+
+# 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=`expr $tries + 1`
+ sleep 1
+ fi
+done
+
+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 "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 -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 -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 -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 -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 -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 -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 -r $RANDFILE -a NSEC3RSASHA1 -b 512 -T KEY -n ENTITY xxx`
+echo "" | $NSUPDATE -k ${key}.private > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=`expr $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=`expr $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=`expr $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
+$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=`expr $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
+$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=`expr $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
+$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=`expr $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=`expr $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; }
+
+ret=0
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ echo_i "running update.pl test"
+ {
+ $PERL update_test.pl -s 10.53.0.1 -p ${PORT} update.nil. || ret=1
+ } | cat_i
+ [ $ret -eq 1 ] && { echo_i "failed"; status=1; }
+else
+ echo_i "The second part of this test requires the Net::DNS library." >&2
+fi
+
+ret=0
+echo_i "fetching first copy of test zone"
+$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 test zone"
+$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 zones"
+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
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1
+then
+ echo_i "restarted server ns1"
+else
+ echo_i "could not restart server ns1"
+ exit 1
+fi
+sleep 10
+
+ret=0
+echo_i "fetching ns1 after hard restart"
+$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; }
+
+ret=0
+echo_i "comparing zones"
+digcomp dig.out.ns1 dig.out.ns1.after || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "begin RT #482 regression test"
+
+ret=0
+echo_i "update master"
+$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
+
+if [ ! "$CYGWIN" ]; then
+ echo_i "SIGHUP slave"
+ $KILL -HUP `cat ns2/named.pid`
+else
+ echo_i "reload slave"
+ $RNDCCMD 10.53.0.2 reload > /dev/null 2>&1
+fi
+
+sleep 5
+
+ret=0
+echo_i "update master again"
+$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
+
+if [ ! "$CYGWIN" ]; then
+ echo_i "SIGHUP slave again"
+ $KILL -HUP `cat ns2/named.pid`
+else
+ echo_i "reload slave again"
+ $RNDCCMD 10.53.0.2 reload > /dev/null 2>&1
+fi
+
+sleep 5
+
+echo_i "check to 'out of sync' message"
+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=`expr $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
+
+sleep 1
+
+# 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=`expr $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
+
+sleep 1
+
+$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=`expr $n + 1`
+ret=0
+echo_i "add a new the NSEC3PARAM via update ($n)"
+$NSUPDATE << EOF
+server 10.53.0.3 ${PORT}
+update add nsec3param.test 3600 NSEC3PARAM 1 0 4 -
+send
+EOF
+
+sleep 1
+
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocmd +norec nsec3param.test.\
+ @10.53.0.3 nsec3param > dig.out.ns3.$n || ret=1
+grep "ANSWER: 2" dig.out.ns3.$n > /dev/null || ret=1
+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=`expr $ret + $status`; fi
+
+n=`expr $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
+
+sleep 1
+
+$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 "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=`expr $ret + $status`; fi
+
+
+
+ret=0
+echo_i "testing that rndc stop updates the master 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
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} . ns1
+# Removing the journal file and restarting the server means
+# that the data served by the new server process are exactly
+# those dumped to the master file by "rndc stop".
+rm -f ns1/*jnl
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd updated4.example.nil.\
+ @10.53.0.1 a > dig.out.ns1 || status=1
+digcomp knowngood.ns1.afterstop dig.out.ns1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "check that 'nsupdate -l' with a missing keyfile reports the missing file"
+$NSUPDATE -l -p ${PORT} -k ns1/nonexistant.key 2> nsupdate.out < /dev/null
+grep ns1/nonexistant.key nsupdate.out > /dev/null || ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=`expr $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=`expr $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=`expr $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
+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=`expr $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=`expr $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
+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=`expr $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 | \
+ sed -n 's/\(.*\)10.IN/update add \1600 IN/p' |
+ (echo server 10.53.0.3 ${PORT}; cat - ; echo send ) |
+$NSUPDATE
+
+$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=`expr $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=`expr $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=`expr $n + 1`
+ret=0
+echo_i "check command list ($n)"
+(
+while read cmd
+do
+ echo "$cmd" | $NSUPDATE > /dev/null 2>&1
+ if test $? -gt 1 ; then
+ echo_i "failed ($cmd)"
+ ret=1
+ fi
+ echo "$cmd " | $NSUPDATE > /dev/null 2>&1
+ if test $? -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=`expr $n + 1`
+ret=0
+echo_i "check TSIG key algorithms ($n)"
+for alg in md5 sha1 sha224 sha256 sha384 sha512; 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 md5 sha1 sha224 sha256 sha384 sha512; 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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $n + 1`
+echo_i "check check-names processing ($n)"
+ret=0
+$NSUPDATE << EOF > nsupdate.out1-$n 2>&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
+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
+update add . 0 in mx 0 #
+EOF
+grep "bad name" nsupdate.out3-$n > /dev/null || ret=1
+
+$NSUPDATE << EOF > nsupdate.out4-$n 2>&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=`expr $n + 1`
+echo_i "check adding of delegating NS records processing ($n)"
+ret=0
+$NSUPDATE -v << EOF > nsupdate.out-$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=`expr $n + 1`
+echo_i "check deleting of delegating NS records processing ($n)"
+ret=0
+$NSUPDATE -v << EOF > nsupdate.out-$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=`expr $n + 1`
+echo_i "check that adding too many records is blocked ($n)"
+ret=0
+$NSUPDATE -v << EOF > nsupdate.out-$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-$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=`expr $n + 1`
+ret=0
+echo_i "check whether valid addresses are used for master failover ($n)"
+$NSUPDATE -t 1 <<END > nsupdate.out-$n 2>&1 && ret=1
+server 10.53.0.4 ${PORT}
+zone unreachable.
+update add unreachable. 600 A 192.0.2.1
+send
+END
+grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out-$n > /dev/null 2>&1 || ret=1
+grep "not implemented" nsupdate.out-$n > /dev/null 2>&1 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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..': not found" nsupdate.out > /dev/null || ret=1
+grep "syntax error" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=`expr $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..': not found" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=`expr $n + 1`
+ret=0
+echo_i "check that TKEY in a update is rejected ($n)"
+$NSUPDATE -d <<END > nsupdate.out-$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-$n > /dev/null 2>&1 || ret=1
+grep "UPDATE, status: FORMERR" nsupdate.out-$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+if $FEATURETEST --gssapi ; then
+ n=`expr $n + 1`
+ ret=0
+ echo_i "check krb5-self match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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=`expr $n + 1`
+ ret=0
+ echo_i "check krb5-self no-match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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-$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=`expr $n + 1`
+ ret=0
+ echo_i "check krb5-subdomain match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out-$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=`expr $n + 1`
+ ret=0
+ echo_i "check krb5-subdomain no-match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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-$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=`expr $n + 1`
+ ret=0
+ echo_i "check krb5-selfsub match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns8/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out-$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=`expr $n + 1`
+ ret=0
+ echo_i "check krb5-selfsub no-match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns8/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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-$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=`expr $n + 1`
+ ret=0
+
+ echo_i "check ms-self match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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=`expr $n + 1`
+ ret=0
+ echo_i "check ms-self no-match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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-$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=`expr $n + 1`
+ ret=0
+ echo_i "check ms-subdomain match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out-$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=`expr $n + 1`
+ ret=0
+ echo_i "check ms-subdomain no-match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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-$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=`expr $n + 1`
+ ret=0
+ echo_i "check ms-selfsub match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns10/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out-$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=`expr $n + 1`
+ ret=0
+ echo_i "check ms-selfsub no-match ($n)"
+ KRB5CCNAME="FILE:"`pwd`/ns10/machine.ccache
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out-$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-$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
+#
+# Add client library tests here
+#
+
+if test unset != "${SAMPLEUPDATE:-unset}" -a -x "${SAMPLEUPDATE}"
+then
+
+ n=`expr $n + 1`
+ ret=0
+ echo_i "check that dns_client_update handles prerequisite NXDOMAIN failure ($n)"
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.1 -a 10.53.0.2 -p "nxdomain exists.sample" \
+ add "nxdomain-exists.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.2 -p "nxdomain exists.sample" \
+ add "check-nxdomain-exists.sample 0 in a 1.2.3.4" > update.out.check$n 2>&1
+ $DIG $DIGOPTS +tcp @10.53.0.1 a nxdomain-exists.sample > dig.out.ns1.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a nxdomain-exists.sample > dig.out.ns2.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a check-nxdomain-exists.sample > check.out.ns2.test$n
+ grep "update failed: YXDOMAIN" update.out.test$n > /dev/null || ret=1
+ grep "update succeeded" update.out.check$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=`expr $n + 1`
+ ret=0
+ echo_i "check that dns_client_update handles prerequisite YXDOMAIN failure ($n)"
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.1 -a 10.53.0.2 -p "yxdomain nxdomain.sample" \
+ add "yxdomain-nxdomain.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.2 -p "yxdomain nxdomain.sample" \
+ add "check-yxdomain-nxdomain.sample 0 in a 1.2.3.4" > update.out.check$n 2>&1
+ $DIG $DIGOPTS +tcp @10.53.0.1 a nxdomain-exists.sample > dig.out.ns1.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a nxdomain-exists.sample > dig.out.ns2.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a check-nxdomain-exists.sample > check.out.ns2.test$n
+ grep "update failed: NXDOMAIN" update.out.test$n > /dev/null || ret=1
+ grep "update succeeded" update.out.check$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=`expr $n + 1`
+ ret=0
+ echo_i "check that dns_client_update handles prerequisite NXRRSET failure ($n)"
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.1 -a 10.53.0.2 -p "nxrrset exists.sample TXT This RRset exists." \
+ add "nxrrset-exists.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.2 -p "nxrrset exists.sample TXT This RRset exists." \
+ add "check-nxrrset-exists.sample 0 in a 1.2.3.4" > update.out.check$n 2>&1
+ $DIG $DIGOPTS +tcp @10.53.0.1 a nxrrset-exists.sample > dig.out.ns1.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a nxrrset-exists.sample > dig.out.ns2.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a check-nxrrset-exists.sample > check.out.ns2.test$n
+ grep "update failed: YXRRSET" update.out.test$n > /dev/null || ret=1
+ grep "update succeeded" update.out.check$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=`expr $n + 1`
+ ret=0
+ echo_i "check that dns_client_update handles prerequisite YXRRSET failure ($n)"
+ $SAMPLEUPDATE -s -P ${PORT} -a 10.53.0.1 -a 10.53.0.2 \
+ -p "yxrrset no-txt.sample TXT" \
+ add "yxrrset-nxrrset.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
+ $SAMPLEUPDATE -P ${PORT} -a 10.53.0.2 -p "yxrrset no-txt.sample TXT" \
+ add "check-yxrrset-nxrrset.sample 0 in a 1.2.3.4" > update.out.check$n 2>&1
+ $DIG $DIGOPTS +tcp @10.53.0.1 a yxrrset-nxrrset.sample > dig.out.ns1.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a yxrrset-nxrrset.sample > dig.out.ns2.test$n
+ $DIG $DIGOPTS +tcp @10.53.0.2 a check-yxrrset-nxrrset.sample > check.out.ns2.test$n
+ grep "update failed: NXRRSET" update.out.test$n > /dev/null || ret=1
+ grep "update succeeded" update.out.check$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
+ grep "2nd update failed: NXRRSET" update.out.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+fi
+
+#
+# End client library tests here
+#
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/nsupdate/update_test.pl b/bin/tests/system/nsupdate/update_test.pl
new file mode 100644
index 0000000..b9f083f
--- /dev/null
+++ b/bin/tests/system/nsupdate/update_test.pl
@@ -0,0 +1,418 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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";
+ }
+}
+
+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 ($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..8b58ed3
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */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
diff --git a/bin/tests/system/nzd2nzf/ns1/added.db b/bin/tests/system/nzd2nzf/ns1/added.db
new file mode 100644
index 0000000..9b54d19
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/ns1/added.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+;$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..2a0fb7e
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..85e0360
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/prereq.sh
@@ -0,0 +1,18 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if [ -z "$NZD" ]; then
+ echo_i "This test requires LMDB support (--with-lmdb)"
+ exit 255
+fi
+
+exit 0
diff --git a/bin/tests/system/nzd2nzf/setup.sh b/bin/tests/system/nzd2nzf/setup.sh
new file mode 100644
index 0000000..b3e0450
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..85f1721
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/tests.sh
@@ -0,0 +1,72 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "querying for non-existing zone data ($n)"
+ret=0
+$DIG $DIGOPTS @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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "adding a new zone into default NZD using rndc addzone ($n)"
+$RNDCCMD 10.53.0.1 addzone "added.example { type master; file \"added.db\";
+};" 2>&1 | sed 's/^/ns1 /' | cat_i
+sleep 2
+
+n=`expr $n + 1`
+echo_i "querying for existing zone data ($n)"
+ret=0
+$DIG $DIGOPTS @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=`expr $status + $ret`
+
+echo_i "stopping ns1"
+$PERL $SYSTEMTESTTOP/stop.pl . ns1
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that _default.nzf contains the expected content ($n)"
+grep 'zone "added.example" { type master; file "added.db"; };' ns1/_default.nzf > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "deleting _default.nzd database"
+rm -f ns1/_default.nzd
+
+echo_i "starting ns1 which should migrate the .nzf to .nzd"
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns1
+
+n=`expr $n + 1`
+echo_i "querying for zone data from migrated zone config ($n)"
+ret=0
+$DIG $DIGOPTS @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
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+exit $status
diff --git a/bin/tests/system/org.isc.bind.system b/bin/tests/system/org.isc.bind.system
new file mode 100644
index 0000000..2096af2
--- /dev/null
+++ b/bin/tests/system/org.isc.bind.system
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+for ns in 1 2 3 4 5 6 7 8
+do
+ /sbin/ifconfig lo0 10.53.0.$ns alias
+ /sbin/ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns alias
+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..9cd55d6
--- /dev/null
+++ b/bin/tests/system/packet.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 hexidecimal.
+# 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] [-t (tcp|udp)] [file]\n");
+ exit 1;
+}
+
+my %options={};
+getopts("a:p:t:", \%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 $proto = "udp";
+$proto = lc $options{t} if defined $options{t};
+usage if ($proto !~ /^(udp|tcp)$/);
+
+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 => $proto,) or die "$!";
+
+my $bytes;
+if ($proto eq "udp") {
+ $bytes = $sock->send($data);
+} else {
+ $bytes = $sock->syswrite(pack("n", $len), 2);
+ $bytes += $sock->syswrite($data, $len);
+}
+
+print ("sent $bytes bytes to $addr:$port\n");
+$sock->close;
+close $file;
diff --git a/bin/tests/system/pending/clean.sh b/bin/tests/system/pending/clean.sh
new file mode 100644
index 0000000..f004183
--- /dev/null
+++ b/bin/tests/system/pending/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -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
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..e36b0b1
--- /dev/null
+++ b/bin/tests/system/pending/ns1/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+zone "." {
+ type master;
+ 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..271a8e5
--- /dev/null
+++ b/bin/tests/system/pending/ns1/root.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8a69e1a
--- /dev/null
+++ b/bin/tests/system/pending/ns1/sign.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL -e sign.sh )
+
+cp ../ns2/dsset-example$TP .
+cp ../ns2/dsset-example.com$TP .
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -f KSK -n zone $zone`
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $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..6ec9362
--- /dev/null
+++ b/bin/tests/system/pending/ns2/example.com.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..a5dc49c
--- /dev/null
+++ b/bin/tests/system/pending/ns2/example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..89f9459
--- /dev/null
+++ b/bin/tests/system/pending/ns2/forgery.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..df2e168
--- /dev/null
+++ b/bin/tests/system/pending/ns2/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db.signed";
+};
+
+zone "example.com" {
+ type master;
+ file "example.com.db.signed";
+ allow-update { 10.53.0.0/16; };
+};
+
+zone "good" {
+ type master;
+ 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..df3f500
--- /dev/null
+++ b/bin/tests/system/pending/ns2/sign.sh
@@ -0,0 +1,32 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+for domain in example example.com; do
+ zone=${domain}.
+ infile=${domain}.db.in
+ zonefile=${domain}.db
+
+ keyname1=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+ keyname2=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -f KSK -n zone $zone`
+
+ cat $infile $keyname1.key $keyname2.key > $zonefile
+
+ $SIGNER -3 bebe -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+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..021258a
--- /dev/null
+++ b/bin/tests/system/pending/ns3/hostile.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2da8b45
--- /dev/null
+++ b/bin/tests/system/pending/ns3/mail.example.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..97129c9
--- /dev/null
+++ b/bin/tests/system/pending/ns3/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "mail.example" {
+ type master;
+ file "mail.example.db";
+};
+
+zone "hostile" {
+ type master;
+ 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..78ffed7
--- /dev/null
+++ b/bin/tests/system/pending/ns4/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/pending/prereq.sh b/bin/tests/system/pending/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/pending/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/pending/setup.sh b/bin/tests/system/pending/setup.sh
new file mode 100644
index 0000000..e6e003f
--- /dev/null
+++ b/bin/tests/system/pending/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..e934758
--- /dev/null
+++ b/bin/tests/system/pending/tests.sh
@@ -0,0 +1,197 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+# 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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo_i "Replacing pending AAAA"
+ret=0
+replace_data mail.example.com. AAAA 2001:db8::2 2001:db8::3 || ret=1
+status=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/pipelined/Makefile.in b/bin/tests/system/pipelined/Makefile.in
new file mode 100644
index 0000000..f140d52
--- /dev/null
+++ b/bin/tests/system/pipelined/Makefile.in
@@ -0,0 +1,46 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@
+CWARNINGS =
+
+DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+DNSDEPLIBS = ../../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = pipequeries@EXEEXT@
+
+SRCS = pipequeries.c
+
+@BIND9_MAKE_RULES@
+
+all: pipequeries@EXEEXT@
+
+pipequeries@EXEEXT@: pipequeries.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ pipequeries.@O@ ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/tests/system/pipelined/clean.sh b/bin/tests/system/pipelined/clean.sh
new file mode 100644
index 0000000..f4c4b13
--- /dev/null
+++ b/bin/tests/system/pipelined/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f raw* output*
+rm -f ns*/named.lock
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..828bc40
--- /dev/null
+++ b/bin/tests/system/pipelined/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ 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..2cddcd2
--- /dev/null
+++ b/bin/tests/system/pipelined/ns1/root.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.2
+
+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..9f0427e
--- /dev/null
+++ b/bin/tests/system/pipelined/ns2/examplea.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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.2
+
+$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..6df0c66
--- /dev/null
+++ b/bin/tests/system/pipelined/ns2/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "examplea" {
+ type master;
+ 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..98a61f0
--- /dev/null
+++ b/bin/tests/system/pipelined/ns3/exampleb.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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.args b/bin/tests/system/pipelined/ns3/named.args
new file mode 100644
index 0000000..51b9cc3
--- /dev/null
+++ b/bin/tests/system/pipelined/ns3/named.args
@@ -0,0 +1 @@
+-m record,size,mctx -c named.conf -d 99 -X named.lock -g -T delay=200
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..a17babd
--- /dev/null
+++ b/bin/tests/system/pipelined/ns3/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "exampleb" {
+ type master;
+ 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..0b8a54b
--- /dev/null
+++ b/bin/tests/system/pipelined/ns4/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c
new file mode 100644
index 0000000..2fcc064
--- /dev/null
+++ b/bin/tests/system/pipelined/pipequeries.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#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/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/parseint.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <dns/events.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/types.h>
+
+#include <dst/result.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;
+static dns_requestmgr_t *requestmgr;
+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, *response;
+ 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;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + 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_destroy(&query);
+ dns_message_destroy(&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;
+ dns_message_t *message;
+ dns_name_t *qname;
+ dns_rdataset_t *qrdataset;
+ 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);
+
+ message = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+ CHECK("dns_message_create", result);
+
+ message->opcode = dns_opcode_query;
+ message->flags |= DNS_MESSAGEFLAG_RD;
+ message->rdclass = dns_rdataclass_in;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ qname = NULL;
+ result = dns_message_gettempname(message, &qname);
+ CHECK("dns_message_gettempname", result);
+
+ qrdataset = NULL;
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ CHECK("dns_message_gettemprdataset", result);
+
+ dns_name_init(qname, NULL);
+ 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);
+
+ request = NULL;
+ result = dns_request_createvia(requestmgr, message,
+ have_src ? &srcaddr : NULL, &dstaddr,
+ DNS_REQUESTOPT_TCP|DNS_REQUESTOPT_SHARE,
+ NULL, TIMEOUT, 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;
+ isc_logconfig_t *lcfg;
+ isc_entropy_t *ectx;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ unsigned int attrs, attrmask;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ uint16_t port = PORT;
+ int c;
+
+ UNUSED(argv);
+
+ isc_commandline_errprint = false;
+ while ((c = isc_commandline_parse(argc, argv, "p:")) != -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 '?':
+ fprintf(stderr, "%s: invalid argument '%c'",
+ argv[0], c);
+ break;
+ default:
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 0) {
+ have_src = true;
+ }
+
+ RUNCHECK(isc_app_start());
+
+ dns_result_register();
+
+ 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);
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ lctx = NULL;
+ lcfg = NULL;
+ RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "../random.data"));
+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
+
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ have_src ? &srcaddr : &bind_any,
+ 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ view = NULL;
+ 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_destroy(&dispatchmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+
+ dst_lib_destroy();
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ 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..82b8ffd
--- /dev/null
+++ b/bin/tests/system/pipelined/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..a6720ce
--- /dev/null
+++ b/bin/tests/system/pipelined/tests.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+MDIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/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=`expr $status + $ret`
+
+# flush resolver so queries will be from others again
+$RNDCCMD 10.53.0.4 flush
+sleep 1
+
+echo_i "check pipelined TCP queries using mdig"
+ret=0
+$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=`expr $status + $ret`
+
+echo_i "check keep-response-order"
+ret=0
+$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=`expr $status + $ret`
+
+echo_i "check keep-response-order using mdig"
+ret=0
+$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=`expr $status + $ret`
+
+echo_i "check mdig -4 -6"
+ret=0
+$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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/pkcs11/clean.sh b/bin/tests/system/pkcs11/clean.sh
new file mode 100644
index 0000000..f5be432
--- /dev/null
+++ b/bin/tests/system/pkcs11/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f K* ns1/K* keyset-* dsset-* ns1/*.db ns1/*.signed ns1/*.jnl
+rm -f dig.out* pin upd.log*
+rm -f ns1/*.key ns1/named.memstats
+rm -f supported
+rm -f ns*/named.lock
diff --git a/bin/tests/system/pkcs11/ns1/example.db.in b/bin/tests/system/pkcs11/ns1/example.db.in
new file mode 100644
index 0000000..95d2a63
--- /dev/null
+++ b/bin/tests/system/pkcs11/ns1/example.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/pkcs11/ns1/named.conf b/bin/tests/system/pkcs11/ns1/named.conf
new file mode 100644
index 0000000..5ac9a2f
--- /dev/null
+++ b/bin/tests/system/pkcs11/ns1/named.conf
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "rsa.example." {
+ type master;
+ file "rsa.example.db.signed";
+ allow-update { any; };
+};
+
+zone "ecc.example." {
+ type master;
+ file "ecc.example.db.signed";
+ allow-update { any; };
+};
+
+zone "ecx.example." {
+ type master;
+ file "ecx.example.db.signed";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/pkcs11/prereq.sh b/bin/tests/system/pkcs11/prereq.sh
new file mode 100644
index 0000000..0eb3b78
--- /dev/null
+++ b/bin/tests/system/pkcs11/prereq.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+echo "I:(Native PKCS#11)" >&2
+rsafail=0 eccfail=0 ecxfail=0
+
+$SHELL ../testcrypto.sh -q rsa || rsafail=1
+$SHELL ../testcrypto.sh -q ecdsa || eccfail=1
+$SHELL ../testcrypto.sh -q eddsa || ecxfail=1
+
+if [ $rsafail = 1 -a $eccfail = 1 ]; then
+ echo "I:This test requires PKCS#11 support for either RSA or ECDSA cryptography." >&2
+ exit 255
+fi
+rm -f supported
+touch supported
+if [ $rsafail = 0 ]; then
+ echo rsa >> supported
+fi
+if [ $eccfail = 0 ]; then
+ echo ecc >> supported
+fi
+if [ $ecxfail = 0 ]; then
+ echo ecx >> supported
+fi
diff --git a/bin/tests/system/pkcs11/setup.sh b/bin/tests/system/pkcs11/setup.sh
new file mode 100644
index 0000000..4fc5ec5
--- /dev/null
+++ b/bin/tests/system/pkcs11/setup.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+infile=ns1/example.db.in
+
+/bin/echo -n ${HSMPIN:-1234}> pin
+PWD=`pwd`
+
+zone=rsa.example
+zonefile=ns1/rsa.example.db
+have_rsa=`grep rsa supported`
+if [ "x$have_rsa" != "x" ]; then
+ $PK11GEN -a RSA -b 1024 -l robie-rsa-zsk1 -i 01
+ $PK11GEN -a RSA -b 1024 -l robie-rsa-zsk2 -i 02
+ $PK11GEN -a RSA -b 2048 -l robie-rsa-ksk
+
+ rsazsk1=`$KEYFRLAB -a RSASHA1 \
+ -l "object=robie-rsa-zsk1;pin-source=$PWD/pin" rsa.example`
+ rsazsk2=`$KEYFRLAB -a RSASHA1 \
+ -l "object=robie-rsa-zsk2;pin-source=$PWD/pin" rsa.example`
+ rsaksk=`$KEYFRLAB -a RSASHA1 -f ksk \
+ -l "object=robie-rsa-ksk;pin-source=$PWD/pin" rsa.example`
+
+ cat $infile $rsazsk1.key $rsaksk.key > $zonefile
+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+ cp $rsazsk2.key ns1/rsa.key
+ mv Krsa* ns1
+else
+ # RSA not available and will not be tested; make a placeholder
+ cp $infile ${zonefile}.signed
+fi
+
+zone=ecc.example
+zonefile=ns1/ecc.example.db
+have_ecc=`grep ecc supported`
+if [ "x$have_ecc" != "x" ]; then
+ $PK11GEN -a ECC -b 256 -l robie-ecc-zsk1 -i 03
+ $PK11GEN -a ECC -b 256 -l robie-ecc-zsk2 -i 04
+ $PK11GEN -a ECC -b 384 -l robie-ecc-ksk
+
+ ecczsk1=`$KEYFRLAB -a ECDSAP256SHA256 \
+ -l "object=robie-ecc-zsk1;pin-source=$PWD/pin" ecc.example`
+ ecczsk2=`$KEYFRLAB -a ECDSAP256SHA256 \
+ -l "object=robie-ecc-zsk2;pin-source=$PWD/pin" ecc.example`
+ eccksk=`$KEYFRLAB -a ECDSAP384SHA384 -f ksk \
+ -l "object=robie-ecc-ksk;pin-source=$PWD/pin" ecc.example`
+
+ cat $infile $ecczsk1.key $eccksk.key > $zonefile
+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+ cp $ecczsk2.key ns1/ecc.key
+ mv Kecc* ns1
+else
+ # ECC not available and will not be tested; make a placeholder
+ cp $infile ${zonefile}.signed
+fi
+
+zone=ecx.example
+zonefile=ns1/ecx.example.db
+have_ecx=`grep ecx supported`
+if [ "x$have_ecx" != "x" ]; then
+ $PK11GEN -a ECX -b 256 -l robie-ecx-zsk1 -i 05
+ $PK11GEN -a ECX -b 256 -l robie-ecx-zsk2 -i 06
+ $PK11GEN -a ECX -b 256 -l robie-ecx-ksk
+# $PK11GEN -a ECX -b 456 -l robie-ecx-ksk
+
+ ecxzsk1=`$KEYFRLAB -a ED25519 \
+ -l "object=robie-ecx-zsk1;pin-source=$PWD/pin" ecx.example`
+ ecxzsk2=`$KEYFRLAB -a ED25519 \
+ -l "object=robie-ecx-zsk2;pin-source=$PWD/pin" ecx.example`
+ ecxksk=`$KEYFRLAB -a ED25519 -f ksk \
+ -l "object=robie-ecx-ksk;pin-source=$PWD/pin" ecx.example`
+# ecxksk=`$KEYFRLAB -a ED448 -f ksk \
+# -l "object=robie-ecx-ksk;pin-source=$PWD/pin" ecx.example`
+
+ cat $infile $ecxzsk1.key $ecxksk.key > $zonefile
+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+ cp $ecxzsk2.key ns1/ecx.key
+ mv Kecx* ns1
+else
+ # ECX not available and will not be tested; make a placeholder
+ cp $infile ${zonefile}.signed
+fi
+
+rm -f signer.err
diff --git a/bin/tests/system/pkcs11/tests.sh b/bin/tests/system/pkcs11/tests.sh
new file mode 100644
index 0000000..cf3b549
--- /dev/null
+++ b/bin/tests/system/pkcs11/tests.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+status=0
+ret=0
+
+algs=""
+have_rsa=`grep rsa supported`
+if [ "x$have_rsa" != "x" ]; then
+ algs="rsa "
+fi
+have_ecc=`grep ecc supported`
+if [ "x$have_ecc" != "x" ]; then
+ algs=$algs"ecc "
+fi
+have_ecx=`grep ecc supported`
+if [ "x$have_ecx" != "x" ]; then
+ algs=$algs"ecx "
+fi
+
+for alg in $algs; do
+ zonefile=ns1/$alg.example.db
+ echo "I:testing PKCS#11 key generation ($alg)"
+ count=`$PK11LIST | grep robie-$alg-ksk | wc -l`
+ if [ $count != 2 ]; then echo "I:failed"; status=1; fi
+
+ echo "I:testing offline signing with PKCS#11 keys ($alg)"
+
+ count=`grep RRSIG $zonefile.signed | wc -l`
+ if [ $count != 12 ]; then echo "I:failed"; status=1; fi
+
+ echo "I:testing inline signing with PKCS#11 keys ($alg)"
+
+ $DIG $DIGOPTS ns.$alg.example. @10.53.0.1 a > dig.out.$alg.0 || ret=1
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+ count0=`grep RRSIG dig.out.$alg.0 | wc -l`
+
+ $NSUPDATE -v > upd.log.$alg <<END || status=1
+server 10.53.0.1 5300
+ttl 300
+zone $alg.example.
+update add `grep -v ';' ns1/${alg}.key`
+send
+END
+
+ echo "I:waiting 20 seconds for key changes to take effect"
+ sleep 20
+
+ $DIG $DIGOPTS ns.$alg.example. @10.53.0.1 a > dig.out.$alg || ret=1
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+ count=`grep RRSIG dig.out.$alg | wc -l`
+ if [ $count -le $count0 ]; then echo "I:failed"; status=1; fi
+
+ echo "I:testing PKCS#11 key destroy ($alg)"
+ ret=0
+ $PK11DEL -l robie-$alg-ksk -w0 > /dev/null 2>&1 || ret=1
+ $PK11DEL -l robie-$alg-zsk1 -w0 > /dev/null 2>&1 || ret=1
+ case $alg in
+ rsa) id=02 ;;
+ ecc) id=04 ;;
+ ecx) id=06 ;;
+ esac
+ $PK11DEL -i $id -w0 > /dev/null 2>&1 || ret=1
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+ count=`$PK11LIST | grep robie-$alg | wc -l`
+ if [ $count != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $count`
+done
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/pkcs11/usepkcs11 b/bin/tests/system/pkcs11/usepkcs11
new file mode 100644
index 0000000..ef46412
--- /dev/null
+++ b/bin/tests/system/pkcs11/usepkcs11
@@ -0,0 +1 @@
+This test relies on PKCS#11!
diff --git a/bin/tests/system/pkcs11ssl/clean.sh b/bin/tests/system/pkcs11ssl/clean.sh
new file mode 100644
index 0000000..4af1c39
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f K* ns1/K* keyset-* dsset-* ns1/*.db ns1/*.signed ns1/*.jnl
+rm -f dig.out pin
+rm -f ns1/*.key ns1/named.memstats
+rm -f supported
+rm -f ns*/named.lock
diff --git a/bin/tests/system/pkcs11ssl/ns1/example.db.in b/bin/tests/system/pkcs11ssl/ns1/example.db.in
new file mode 100644
index 0000000..95d2a63
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/ns1/example.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/pkcs11ssl/ns1/named.conf b/bin/tests/system/pkcs11ssl/ns1/named.conf
new file mode 100644
index 0000000..7cd8074
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/ns1/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "rsa.example." {
+ type master;
+ file "rsa.example.db.signed";
+ allow-update { any; };
+};
+
+zone "ecc.example." {
+ type master;
+ file "ecc.example.db.signed";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/pkcs11ssl/prereq.sh b/bin/tests/system/pkcs11ssl/prereq.sh
new file mode 100644
index 0000000..489bebb
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/prereq.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+echo "I:(PKCS#11 via OpenSSL)" >&2
+exec $SHELL ../testcrypto.sh rsa
diff --git a/bin/tests/system/pkcs11ssl/setup.sh b/bin/tests/system/pkcs11ssl/setup.sh
new file mode 100644
index 0000000..d2fbe92
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/setup.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+infile=ns1/example.db.in
+
+/bin/echo -n ${HSMPIN:-1234}> pin
+PWD=`pwd`
+
+zone=rsa.example
+zonefile=ns1/rsa.example.db
+
+$PK11GEN -a RSA -b 1024 -l robie-rsa-zsk1 -i 01
+$PK11GEN -a RSA -b 1024 -l robie-rsa-zsk2 -i 02
+$PK11GEN -a RSA -b 2048 -l robie-rsa-ksk
+
+rsazsk1=`$KEYFRLAB -a RSASHA1 \
+ -l "robie-rsa-zsk1" rsa.example`
+rsazsk2=`$KEYFRLAB -a RSASHA1 \
+ -l "robie-rsa-zsk2" rsa.example`
+rsaksk=`$KEYFRLAB -a RSASHA1 -f ksk \
+ -l "robie-rsa-ksk" rsa.example`
+
+cat $infile $rsazsk1.key $rsaksk.key > $zonefile
+$SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+cp $rsazsk2.key ns1/rsa.key
+mv Krsa* ns1
+
+rm -f signer.err
diff --git a/bin/tests/system/pkcs11ssl/tests.sh b/bin/tests/system/pkcs11ssl/tests.sh
new file mode 100644
index 0000000..2d7437e
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/tests.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+status=0
+ret=0
+
+alg=rsa
+zonefile=ns1/rsa.example.db
+echo "I:testing PKCS#11 key generation (rsa)"
+count=`$PK11LIST | grep robie-rsa-ksk | wc -l`
+if [ $count != 2 ]; then echo "I:failed"; status=1; fi
+
+echo "I:testing offline signing with PKCS#11 keys (rsa)"
+
+count=`grep RRSIG $zonefile.signed | wc -l`
+if [ $count != 12 ]; then echo "I:failed"; status=1; fi
+
+echo "I:testing inline signing with PKCS#11 keys (rsa)"
+
+$NSUPDATE > /dev/null <<END || status=1
+server 10.53.0.1 5300
+ttl 300
+zone rsa.example.
+update add `grep -v ';' ns1/${alg}.key`
+send
+END
+
+echo "I:waiting 20 seconds for key changes to take effect"
+sleep 20
+
+$DIG $DIGOPTS ns.rsa.example. @10.53.0.1 a > dig.out || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+count=`grep RRSIG dig.out | wc -l`
+if [ $count != 4 ]; then echo "I:failed"; status=1; fi
+
+echo "I:testing PKCS#11 key destroy (rsa)"
+ret=0
+$PK11DEL -l robie-rsa-ksk -w0 > /dev/null 2>&1 || ret=1
+$PK11DEL -l robie-rsa-zsk1 -w0 > /dev/null 2>&1 || ret=1
+$PK11DEL -i $id -w0 > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+count=`$PK11LIST | grep robie-rsa | wc -l`
+if [ $count != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $count`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/pkcs11ssl/usepkcs11 b/bin/tests/system/pkcs11ssl/usepkcs11
new file mode 100644
index 0000000..ef46412
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/usepkcs11
@@ -0,0 +1 @@
+This test relies on PKCS#11!
diff --git a/bin/tests/system/reclimit/README b/bin/tests/system/reclimit/README
new file mode 100644
index 0000000..bb7f596
--- /dev/null
+++ b/bin/tests/system/reclimit/README
@@ -0,0 +1,13 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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)
+ for example.net: delegate every query to 15 more name servers, with
+ "victim" address
+ns3 -- resolver under test
+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..988445d
--- /dev/null
+++ b/bin/tests/system/reclimit/ans2/ans.pl
@@ -0,0 +1,233 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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, $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;
+ }
+ $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/ans7/ans.pl b/bin/tests/system/reclimit/ans7/ans.pl
new file mode 100644
index 0000000..5050427
--- /dev/null
+++ b/bin/tests/system/reclimit/ans7/ans.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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 authoritive (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..f856c86
--- /dev/null
+++ b/bin/tests/system/reclimit/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out*
+rm -f ans?/ans.run
+rm -f ans2/ans.limit
+rm -f ns?/named.memstats
+rm -f ns?/named.run
+rm -f ns*/named.conf
+rm -f ns*/named.lock
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..f8868f5
--- /dev/null
+++ b/bin/tests/system/reclimit/ns1/named.conf.in
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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;
+};
+
+zone "." { type master; 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..6a04ed2
--- /dev/null
+++ b/bin/tests/system/reclimit/ns1/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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
diff --git a/bin/tests/system/reclimit/ns3/hints.db b/bin/tests/system/reclimit/ns3/hints.db
new file mode 100644
index 0000000..f763729
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/hints.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..f7f6c6a
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named1.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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;
+ max-recursion-depth 12;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "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..f051cf5
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named2.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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;
+ max-recursion-depth 5;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "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..6c235af
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named3.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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;
+ max-recursion-depth 100;
+ max-recursion-queries 50;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "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..2d7d5c1
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named4.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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;
+ max-recursion-depth 100;
+ max-recursion-queries 40;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints.db"; };
diff --git a/bin/tests/system/reclimit/prereq.sh b/bin/tests/system/reclimit/prereq.sh
new file mode 100644
index 0000000..3c854d2
--- /dev/null
+++ b/bin/tests/system/reclimit/prereq.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION <= 0.78);' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS versions up to 0.78 have a bug that causes this test to fail: please update." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires the Net::DNS library." >&2
+ exit 1
+fi
+
+if $PERL -e 'use Net::DNS::Nameserver;' 2>/dev/null
+then
+ :
+else
+ echo_i "This test requires the Net::DNS::Nameserver library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/reclimit/setup.sh b/bin/tests/system/reclimit/setup.sh
new file mode 100644
index 0000000..a191bf8
--- /dev/null
+++ b/bin/tests/system/reclimit/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..bafdc82
--- /dev/null
+++ b/bin/tests/system/reclimit/tests.sh
@@ -0,0 +1,191 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+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() {
+ count=`sed 's/[^0-9]//g;' $1`
+ expected_count_with_aaaa=$2
+ expected_count_without_aaaa=$3
+
+ 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) != $expected_count"
+ ret=1
+ fi
+}
+
+echo_i "set max-recursion-depth=12"
+
+n=`expr $n + 1`
+echo_i "attempt excessive-depth lookup ($n)"
+ret=0
+echo "1000" > ans2/ans.limit
+$DIG $DIGOPTS @10.53.0.2 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
+check_query_count dig.out.2.test$n 26 14
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "attempt permissible lookup ($n)"
+ret=0
+echo "12" > ans2/ans.limit
+ns3_reset ns3/named1.conf.in
+$DIG $DIGOPTS @10.53.0.2 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
+check_query_count dig.out.2.test$n 49 26
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "set max-recursion-depth=5"
+
+n=`expr $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.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
+check_query_count dig.out.2.test$n 12 7
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "attempt permissible lookup ($n)"
+ret=0
+echo "5" > 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.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
+check_query_count dig.out.2.test$n 21 12
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "set max-recursion-depth=100, max-recursion-queries=50"
+
+n=`expr $n + 1`
+echo_i "attempt excessive-queries lookup ($n)"
+ret=0
+echo "13" > 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 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
+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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "set max-recursion-depth=100, max-recursion-queries=40"
+
+n=`expr $n + 1`
+echo_i "attempt excessive-queries lookup ($n)"
+ret=0
+echo "10" > 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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/redirect/clean.sh b/bin/tests/system/redirect/clean.sh
new file mode 100644
index 0000000..c13d918
--- /dev/null
+++ b/bin/tests/system/redirect/clean.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */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 rndc.out
diff --git a/bin/tests/system/redirect/conf/bad1.conf b/bin/tests/system/redirect/conf/bad1.conf
new file mode 100644
index 0000000..4928878
--- /dev/null
+++ b/bin/tests/system/redirect/conf/bad1.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..87a23fd
--- /dev/null
+++ b/bin/tests/system/redirect/conf/bad2.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..ad7063c
--- /dev/null
+++ b/bin/tests/system/redirect/conf/bad3.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..4e09210
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good1.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..a01d645
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good2.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type master;
+ file "master.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..3d91ba3
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good3.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type slave;
+ file "slave.db";
+ masters { 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..f70b723
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good4.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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..83140c2
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/example.db
@@ -0,0 +1,48 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..47b385a
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/named.conf.in
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "signed" {
+ type master;
+ file "signed.db.signed";
+};
+
+zone "nsec3" {
+ type master;
+ 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..0797462
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/redirect.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..532063c
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..fb38190
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/sign.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=signed
+infile=example.db
+zonefile=signed.db
+
+key1=`$KEYGEN -q -r $RANDFILE $zone`
+key2=`$KEYGEN -q -r $RANDFILE -fk $zone`
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=nsec3
+infile=example.db
+zonefile=nsec3.db
+
+key1=`$KEYGEN -q -r $RANDFILE -3 $zone`
+key2=`$KEYGEN -q -r $RANDFILE -3 -fk $zone`
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -3 - -g -r $RANDFILE -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..bb8b66d
--- /dev/null
+++ b/bin/tests/system/redirect/ns2/example.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3e89790
--- /dev/null
+++ b/bin/tests/system/redirect/ns2/named.conf.in
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ 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..46e5db8
--- /dev/null
+++ b/bin/tests/system/redirect/ns2/redirect.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..065ad2d
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/example.db
@@ -0,0 +1,48 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..04a651b
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/named.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "signed" {
+ type master;
+ file "signed.db.signed";
+};
+
+zone "nsec3" {
+ type master;
+ file "nsec3.db.signed";
+};
+
+zone "redirect" {
+ type master;
+ 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..b8ca047
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/redirect.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..1befd93
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/root.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..fb38190
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/sign.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=signed
+infile=example.db
+zonefile=signed.db
+
+key1=`$KEYGEN -q -r $RANDFILE $zone`
+key2=`$KEYGEN -q -r $RANDFILE -fk $zone`
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=nsec3
+infile=example.db
+zonefile=nsec3.db
+
+key1=`$KEYGEN -q -r $RANDFILE -3 $zone`
+key2=`$KEYGEN -q -r $RANDFILE -3 -fk $zone`
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -3 - -g -r $RANDFILE -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..4d3a082
--- /dev/null
+++ b/bin/tests/system/redirect/ns4/example.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..70f0df0
--- /dev/null
+++ b/bin/tests/system/redirect/ns4/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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.3 */
+ 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-enable yes;
+ dnssec-validation yes;
+ nxdomain-redirect "redirect";
+
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "example" {
+ type master;
+ 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..20d2a27
--- /dev/null
+++ b/bin/tests/system/redirect/ns4/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/redirect/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/redirect/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/redirect/setup.sh b/bin/tests/system/redirect/setup.sh
new file mode 100644
index 0000000..90d2089
--- /dev/null
+++ b/bin/tests/system/redirect/setup.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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/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 )
diff --git a/bin/tests/system/redirect/tests.sh b/bin/tests/system/redirect/tests.sh
new file mode 100644
index 0000000..0e2adf7
--- /dev/null
+++ b/bin/tests/system/redirect/tests.sh
@@ -0,0 +1,522 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking A zone redirect updates statistics ($n)"
+ret=0
+rm 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 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 [ `expr $POST - $PRE` != 1 ]; then ret=1; fi
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that redirect zones reload correctly"
+ret=0
+sleep 1 # ensure file mtime will have changed
+sed -e 's/0 0 0 0 0/1 0 0 0 0/' < ns2/example.db.in > ns2/example.db
+sed -e 's/0 0 0 0 0/1 0 0 0 0/' -e 's/\.1$/.2/' < ns2/redirect.db.in > ns2/redirect.db
+$RNDCCMD 10.53.0.2 reload > rndc.out || ret=1
+sed 's/^/ns2 /' rndc.out | cat_i
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking AAAA nxdomain-redirect works for nonexist ($n)"
+ret=0
+rm 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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking AAAA nxdomain-redirect updates statistics ($n)"
+ret=0
+rm 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 [ `expr $POST_RED - $PRE_RED` != 1 ]; then ret=1; fi
+if [ `expr $POST_SUC - $PRE_SUC` != 1 ]; then ret=1; fi
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/resolver/ans2/ans.pl b/bin/tests/system/resolver/ans2/ans.pl
new file mode 100644
index 0000000..a242a99
--- /dev/null
+++ b/bin/tests/system/resolver/ans2/ans.pl
@@ -0,0 +1,115 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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 "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"));
+ } elsif ($qname =~ /\.broken/) {
+ # Delegation to broken TLD.
+ $packet->push("authority", new Net::DNS::RR("broken 300 NS ns.broken"));
+ $packet->push("additional", new Net::DNS::RR("ns.broken 300 A 10.53.0.4"));
+ } 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..46d7673
--- /dev/null
+++ b/bin/tests/system/resolver/ans3/ans.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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.3",
+ 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);
+ $packet->header->aa(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+
+ if ($qname eq "badcname.example.net") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 CNAME badcname.example.org"));
+ } 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 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"));
+ } else {
+ $packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
+ }
+
+ $sock->send($packet->data);
+
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+}
diff --git a/bin/tests/system/resolver/ans8/ans.pl b/bin/tests/system/resolver/ans8/ans.pl
new file mode 100644
index 0000000..6d13110
--- /dev/null
+++ b/bin/tests/system/resolver/ans8/ans.pl
@@ -0,0 +1,145 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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;
+
+ # 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
+ return (pack("nnnnnn", $id, 0x8600, 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 $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ $packet->push("answer", new Net::DNS::RR("$qname 300 A 1.2.3.4"));
+ push(@results, $packet->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..4dfde1f
--- /dev/null
+++ b/bin/tests/system/resolver/clean.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after resolver tests.
+#
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */ans.run
+rm -f */*.jdb
+rm -f dig.out dig.out.*
+rm -f dig.*.out.*
+rm -f dig.*.foo.*
+rm -f dig.*.bar.*
+rm -f dig.*.prime.*
+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/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
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..a2c19db
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/named.conf.in
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1 dscp 1;
+ notify-source 10.53.0.1 dscp 2;
+ transfer-source 10.53.0.1 dscp 3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable 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.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 {
+ match-clients { none; };
+};
+
+/*
+ * 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";
+ };
+};
diff --git a/bin/tests/system/resolver/ns1/root.hint b/bin/tests/system/resolver/ns1/root.hint
new file mode 100644
index 0000000..64769b9
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..886614c
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/broken.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..e0dc65e
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/child.server.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..cfd04de
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/moves.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c679dc3
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/named.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4 dscp 4;
+ notify-source 10.53.0.4 dscp 5;
+ transfer-source 10.53.0.4 dscp 6;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ // minimal-responses yes;
+ /* test that named loads with root-delegation-only */
+ root-delegation-only;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "moves" {
+ type master;
+ file "moves.db";
+};
+
+zone "child.server" {
+ type master;
+ file "child.server.db";
+};
+
+zone "tld" {
+ type master;
+ file "tld.db";
+};
+
+zone "broken" {
+ type master;
+ file "broken.db";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..0f215fc
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/named.noaa
@@ -0,0 +1,5 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..721765d
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
diff --git a/bin/tests/system/resolver/ns4/tld1.db b/bin/tests/system/resolver/ns4/tld1.db
new file mode 100644
index 0000000..6b90e1b
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/tld1.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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 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
diff --git a/bin/tests/system/resolver/ns4/tld2.db b/bin/tests/system/resolver/ns4/tld2.db
new file mode 100644
index 0000000..22e1d4e
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/tld2.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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 10 TXT A short ttl
+fetchall 10 TXT A short ttl
+fetchall 10 A 1.2.3.4
+fetchall 10 AAAA ::1
+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
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..73eb847
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/child.server.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..d2594b6
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/moves.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..07205c9
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+options {
+ query-source address 10.53.0.5 dscp 7;
+ notify-source 10.53.0.5 dscp 8;
+ transfer-source 10.53.0.5 dscp 9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ querylog yes;
+};
+
+server 10.53.0.7 {
+ edns-version 0;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "moves" {
+ type master;
+ file "moves.db";
+};
+
+zone "child.server" {
+ type master;
+ file "child.server.db";
+};
+
+zone "delegation-only" {
+ type delegation-only;
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/resolver/ns5/root.hint b/bin/tests/system/resolver/ns5/root.hint
new file mode 100644
index 0000000..e8cdaec
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..10edff8
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/broken.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..29e9adb
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/delegation-only.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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 21366 7 1 E6C1716CFB6BDC84E84CE1AB5510DAC69173B5B2
+@ 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..d38d1a9
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/ds.example.net.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..fa4e96a
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/example.net.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+fetch 10 IN TXT A short ttl
+non-zero 10 IN TXT A short ttl
+zero 0 IN TXT A zero ttl
+$TTL 10
+ds IN NS ns.ds
+ns.ds IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/keygen.sh b/bin/tests/system/resolver/ns6/keygen.sh
new file mode 100644
index 0000000..7b87d97
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/keygen.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=ds.example.net
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
+zsk=`$KEYGEN -q -3 -r $RANDFILE -b 2048 $zone`
+cat $ksk.key $zsk.key >> $zonefile
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+zone=example.net
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cp $infile $zonefile
+ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
+zsk=`$KEYGEN -q -3 -r $RANDFILE $zone`
+cat $ksk.key $zsk.key dsset-ds.example.net$TP >> $zonefile
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+# Configure a trusted key statement (used by delv)
+keyfile_to_trusted_keys $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..27ce6d1
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/moves.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7df4855
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/named.conf.in
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ query-source address 10.53.0.6 dscp 10;
+ notify-source 10.53.0.6 dscp 11;
+ transfer-source 10.53.0.6 dscp 12;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ recursion no;
+ // minimal-responses yes;
+ querylog yes;
+ /*
+ * test that named loads with root-delegation-only that
+ * has a exclude list.
+ */
+ root-delegation-only exclude { "a"; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example.net" {
+ type master;
+ file "example.net.db.signed";
+ allow-update { any; };
+};
+
+zone "ds.example.net" {
+ type master;
+ file "ds.example.net.db.signed";
+ allow-update { any; };
+};
+
+zone "to-be-removed.tld" {
+ type master;
+ file "to-be-removed.tld.db";
+ allow-update { any; };
+};
+
+zone "broken" {
+ type master;
+ file "broken.db";
+ allow-update { any; };
+};
+
+zone "no-edns-version.tld" {
+ type master;
+ file "no-edns-version.tld.db";
+};
+
+zone "delegation-only" {
+ type master;
+ file "delegation-only.db";
+};
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..736c2e5
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/no-edns-version.tld.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/root.db b/bin/tests/system/resolver/ns6/root.db
new file mode 100644
index 0000000..09b23fc
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/root.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+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 consistancy 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
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..2a1c960
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3adcd1d
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/all-cnames.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..f94d84a
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/edns-version.tld.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.7
diff --git a/bin/tests/system/resolver/ns7/named.args b/bin/tests/system/resolver/ns7/named.args
new file mode 100644
index 0000000..fc8ffac
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/named.args
@@ -0,0 +1,2 @@
+# this server runs named with the "-T clienttest" option omitted
+-m record,size,mctx -c named.conf -d 99 -X named.lock -g
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..6828ad2
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/named1.conf.in
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ query-source address 10.53.0.7 dscp 13;
+ notify-source 10.53.0.7 dscp 14;
+ transfer-source 10.53.0.7 dscp 15;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion 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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "server" {
+ type master;
+ file "server.db";
+ allow-update { any; };
+};
+
+zone "edns-version.tld" {
+ type master;
+ file "edns-version.tld.db";
+};
+
+zone "all-cnames" {
+ type master;
+ file "all-cnames.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..ad8988f
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/named2.conf.in
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ query-source address 10.53.0.7 port @PORT@ dscp 13;
+ notify-source 10.53.0.7 dscp 14;
+ transfer-source 10.53.0.7 dscp 15;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion 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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "server" {
+ type master;
+ file "server.db";
+ allow-update { any; };
+};
+
+zone "edns-version.tld" {
+ type master;
+ file "edns-version.tld.db";
+};
+
+zone "all-cnames" {
+ type master;
+ file "all-cnames.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..a623df9
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..ab42f26
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/server.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/prereq.sh b/bin/tests/system/resolver/prereq.sh
new file mode 100644
index 0000000..264ab4c
--- /dev/null
+++ b/bin/tests/system/resolver/prereq.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION eq "0.76" || $Net::DNS::VERSION eq "0.77");' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS version 0.76 and 0.77 have a bug that causes this test to fail: please update." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires the Net::DNS library." >&2
+ exit 1
+fi
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/resolver/setup.sh b/bin/tests/system/resolver/setup.sh
new file mode 100644
index 0000000..c54fa71
--- /dev/null
+++ b/bin/tests/system/resolver/setup.sh
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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
+
+(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..12d2819
--- /dev/null
+++ b/bin/tests/system/resolver/tests.sh
@@ -0,0 +1,783 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+echo .
+
+DIGOPTS="-p ${PORT}"
+RESOLVOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "checking non-cachable NXDOMAIN response handling ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking non-cachable NXDOMAIN response handling using dns_client ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking that local bound address can be set (Can't query from a denied address) ($n)"
+ ret=0
+ ${RESOLVE} -b 10.53.0.8 $RESOLVOPTS -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=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking that local bound address can be set (Can query from an allowed address) ($n)"
+ ret=0
+ ${RESOLVE} -b 10.53.0.1 $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking non-cachable NODATA response handling ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking non-cachable NODATA response handling using dns_client ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking handling of bogus referrals ($n)"
+# If the server has the "INSIST(!external)" bug, this query will kill it.
+$DIG $DIGOPTS +tcp www.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=`expr $status + 1`; }
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking handling of bogus referrals using dns_client ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "check handling of cname + other data / 1 ($n)"
+$DIG $DIGOPTS +tcp cname1.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=`expr $status + 1`; }
+
+n=`expr $n + 1`
+echo_i "check handling of cname + other data / 2 ($n)"
+$DIG $DIGOPTS +tcp cname2.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=`expr $status + 1`; }
+
+n=`expr $n + 1`
+echo_i "check that server is still running ($n)"
+$DIG $DIGOPTS +tcp www.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=`expr $status + 1`; }
+
+n=`expr $n + 1`
+echo_i "checking answer IPv4 address filtering (deny) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking answer IPv6 address filtering (deny) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking answer IPv4 address filtering (accept) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking answer IPv4 address filtering using dns_client (accept) ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking answer IPv6 address filtering (accept) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking answer IPv6 address filtering using dns_client (accept) ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking CNAME target filtering (deny) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking CNAME target filtering (accept) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking CNAME target filtering using dns_client (accept) ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking CNAME target filtering (accept due to subdomain) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking CNAME target filtering using dns_client (accept due to subdomain) ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking DNAME target filtering (deny) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking DNAME target filtering (accept) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking DNAME target filtering using dns_client (accept) ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "checking DNAME target filtering (accept due to subdomain) ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+if [ -x ${RESOLVE} ] ; then
+ n=`expr $n + 1`
+ echo_i "checking DNAME target filtering using dns_client (accept due to subdomain) ($n)"
+ ret=0
+ $RESOLVE $RESOLVOPTS -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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "RT21594 regression test check setup ($n)"
+ret=0
+# Check that "aa" is not being set by the authoritative server.
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "RT21594 regression test positive answers ($n)"
+ret=0
+# Check that resolver accepts the non-authoritative positive answers.
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "RT21594 regression test NODATA answers ($n)"
+ret=0
+# Check that resolver accepts the non-authoritative nodata answers.
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "RT21594 regression test NXDOMAIN answers ($n)"
+ret=0
+# Check that resolver accepts the non-authoritative positive answers.
+$DIG $DIGOPTS +tcp noexistant @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=`expr $status + $ret`
+
+n=`expr $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 $DIGOPTS +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 $DIGOPTS +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 $DIGOPTS +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 $DIGOPTS +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=`expr $status + $ret`
+
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that update a nameservers address has immediate effects ($n)"
+ret=0
+$DIG $DIGOPTS +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 $DIGOPTS +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=`expr $n + 1`
+echo_i "checking that update a nameservers glue has immediate effects ($n)"
+ret=0
+$DIG $DIGOPTS +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 $DIGOPTS +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=`expr $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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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 $DIGOPTS @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=`expr $n + 1`
+echo_i "checking that removal of a delegation is honoured ($n)"
+ret=0
+$DIG $DIGOPTS @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
+($RNDCCMD 10.53.0.4 reload tld 2>&1 ) |
+sed -e '/reload queued/d' -e 's/^/ns4 /' | cat_i
+old=
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ foo=0
+ $DIG $DIGOPTS @10.53.0.5 ns$i.to-be-removed.tld A > /dev/null
+ $DIG $DIGOPTS @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=`expr $n + 1`
+echo_i "check for improved error message with SOA mismatch ($n)"
+ret=0
+$DIG $DIGOPTS @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=`expr $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=`expr $n + 1`
+echo_i "check resolution on the listening port ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check prefetch (${n})"
+ret=0
+$DIG $DIGOPTS @10.53.0.5 fetch.tld txt > dig.out.1.${n} || ret=1
+ttl1=`awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n}`
+# sleep so we are in prefetch range
+sleep ${ttl1:-0}
+# trigger prefetch
+$DIG $DIGOPTS @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 occured
+$DIG $DIGOPTS @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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check prefetch of validated DS's RRSIG TTL is updated (${n})"
+ret=0
+$DIG $DIGOPTS +dnssec @10.53.0.5 ds.example.net ds > dig.out.1.${n} || ret=1
+ttl1=`awk '$4 == "DS" && $7 == "1" { print $2 - 2 }' dig.out.1.${n}`
+# sleep so we are in prefetch range
+sleep ${ttl1:-0}
+# trigger prefetch
+$DIG $DIGOPTS @10.53.0.5 ds.example.net ds > dig.out.2.${n} || ret=1
+ttl1=`awk '$4 == "DS" && $7 == "1" { print $2 }' dig.out.2.${n}`
+sleep 1
+# check that prefetch occured
+$DIG $DIGOPTS @10.53.0.5 ds.example.net ds +dnssec > dig.out.3.${n} || ret=1
+dsttl=`awk '$4 == "DS" && $7 == "1" { print $2 }' dig.out.3.${n}`
+sigttl=`awk '$4 == "RRSIG" && $5 == "DS" { print $2 }' dig.out.3.${n}`
+test ${dsttl:-0} -gt ${ttl2:-1} || ret=1
+test ${sigttl:-0} -gt ${ttl2:-1} || ret=1
+test ${dsttl:-0} -eq ${sigttl:-1} || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check prefetch disabled (${n})"
+ret=0
+$DIG $DIGOPTS @10.53.0.7 fetch.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"
+for i in $zerotonine $zerotonine $zerotonine $zerotonine
+do
+ $DIG $DIGOPTS @10.53.0.7 fetch.example.net txt > dig.out.2.${n} || ret=1
+ ttl2=`awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}`
+ test ${ttl2:-2} -eq 1 && break
+ $PERL -e 'select(undef, undef, undef, 0.05);'
+done
+test ${ttl2:-2} -eq 1 || ret=1
+# delay so that any prefetched record will have a lower ttl than expected
+sleep 3
+# check that prefetch has not occured
+$DIG $DIGOPTS @10.53.0.7 fetch.example.net txt > dig.out.3.${n} || ret=1
+ttl=`awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.3.${n}`
+test ${ttl:-0} -eq ${ttl1:-1} || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check prefetch qtype * (${n})"
+ret=0
+$DIG $DIGOPTS @10.53.0.5 fetchall.tld any > dig.out.1.${n} || ret=1
+ttl1=`awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n}`
+# sleep so we are in prefetch range
+sleep ${ttl1:-0}
+# trigger prefetch
+$DIG $DIGOPTS @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 the nameserver is still alive
+$DIG $DIGOPTS @10.53.0.5 fetchall.tld any > dig.out.3.${n} || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that E was logged on EDNS queries in the query log (${n})"
+ret=0
+$DIG $DIGOPTS @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 $DIGOPTS @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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that '-t aaaa' in .digrc does not have unexpected side effects ($n)"
+ret=0
+echo "-t aaaa" > .digrc
+env HOME=`pwd` $DIG $DIGOPTS @10.53.0.4 . > dig.out.1.${n} || ret=1
+env HOME=`pwd` $DIG $DIGOPTS @10.53.0.4 . A > dig.out.2.${n} || ret=1
+env HOME=`pwd` $DIG $DIGOPTS @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=`expr $status + $ret`
+
+edns=`$FEATURETEST --edns-version`
+
+n=`expr $n + 1`
+echo_i "check that EDNS version is logged (${n})"
+ret=0
+$DIG $DIGOPTS @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 $DIGOPTS @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=`expr $status + $ret`
+
+if test ${edns:-0} != 0; then
+ n=`expr $n + 1`
+ echo_i "check that edns-version is honoured (${n})"
+ ret=0
+ $DIG $DIGOPTS @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 $DIGOPTS @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=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "check that CNAME nameserver is logged correctly (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that unexpected opcodes are handled correctly (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $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 $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that dig +subnet zeros address bits correctly (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that SOA query returns data for delegation-only apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+n=`expr $n + 1`
+
+n=`expr $n + 1`
+echo_i "check that NS query returns data for delegation-only apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that A query returns data for delegation-only A apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that CDS query returns data for delegation-only apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that AAAA query returns data for delegation-only AAAA apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "check that DNSKEY query returns data for delegation-only apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that CDNSKEY query returns data for delegation-only apex (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex A data (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex CDS data (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex AAAA data (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex CDNSKEY data (${n})"
+ret=0
+$DIG $DIGOPTS 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check zero ttl not returned for learnt non zero ttl records (${n})"
+ret=0
+# use prefetch disabled server
+$DIG $DIGOPTS @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 $DIGOPTS @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} || break
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check zero ttl is returned for learnt zero ttl records (${n})"
+ret=0
+$DIG $DIGOPTS @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=`expr $status + $ret`
+
+n=`expr $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 $DIGOPTS @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=`expr $status + $ret`
+
+n=`expr $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 $DIGOPTS @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=`expr $status + $ret`
+
+n=`expr $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 $DIGOPTS @10.53.0.5 truncated.no-questions. a > 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that the resolver rejects a reply with empty question section with TC=0 ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.5 not-truncated.no-questions. a > 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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rndc/Makefile.in b/bin/tests/system/rndc/Makefile.in
new file mode 100644
index 0000000..186464f
--- /dev/null
+++ b/bin/tests/system/rndc/Makefile.in
@@ -0,0 +1,50 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id$
+
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+DNSLIBS =
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+DNSDEPLIBS =
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS =
+
+LIBS = @LIBS@
+
+TARGETS = gencheck@EXEEXT@
+
+GENCHECKOBJS = gencheck.@O@
+
+SRCS = gencheck.c
+
+@BIND9_MAKE_RULES@
+
+all: gencheck@EXEEXT@
+
+gencheck@EXEEXT@: ${GENCHECKOBJS} ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${GENCHECKOBJS} ${ISCLIBS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/system/rndc/clean.sh b/bin/tests/system/rndc/clean.sh
new file mode 100644
index 0000000..634248d
--- /dev/null
+++ b/bin/tests/system/rndc/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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/key?.conf
+rm -f ns6/huge.zone.db
+rm -f ns*/named.conf
+rm -f nsupdate.out.*.test*
+rm -f python.out.*.test*
+rm -f rndc.out.*.test*
+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..9021b50
--- /dev/null
+++ b/bin/tests/system/rndc/gencheck.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <fcntl.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) {
+ fputs(USAGE, stderr);
+ 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..f40cac4
--- /dev/null
+++ b/bin/tests/system/rndc/ns2/incl.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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..e4dfe3f
--- /dev/null
+++ b/bin/tests/system/rndc/ns2/named.conf.in
@@ -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 http://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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ update-policy local;
+ file "nil.db";
+ ixfr-from-differences yes;
+};
+
+zone "other" {
+ type master;
+ update-policy local;
+ file "other.db";
+};
+
+zone "static" {
+ type master;
+ file "static.db";
+};
+
+zone "incl" {
+ type master;
+ 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..2563b69
--- /dev/null
+++ b/bin/tests/system/rndc/ns2/secondkey.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..dd35295
--- /dev/null
+++ b/bin/tests/system/rndc/ns3/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..2466e69
--- /dev/null
+++ b/bin/tests/system/rndc/ns4/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+};
+
+view normal {
+ match-clients { any; };
+};
+
+view "view with a space" {
+ match-clients { none; };
+};
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..889623e
--- /dev/null
+++ b/bin/tests/system/rndc/ns5/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..cb7f5ee
--- /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
+-X named.lock -m none -T clienttest -c named.conf -d 99 -g -U 4 \ No newline at end of file
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..5a57730
--- /dev/null
+++ b/bin/tests/system/rndc/ns6/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/rndc/setup.sh b/bin/tests/system/rndc/setup.sh
new file mode 100644
index 0000000..850c4d2
--- /dev/null
+++ b/bin/tests/system/rndc/setup.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+$SHELL ../genzone.sh 2 >ns2/nil.db
+$SHELL ../genzone.sh 2 >ns2/other.db
+$SHELL ../genzone.sh 2 >ns2/static.db
+
+$SHELL ../genzone.sh 2 >ns6/huge.zone.db
+awk 'END { for (i = 1; i <= 1000000; 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
+
+make_key () {
+ $RNDCCONFGEN -r $RANDFILE -k key$1 -A $3 -s 10.53.0.4 -p $2 \
+ > ns4/key${1}.conf 2> /dev/null
+ egrep -v '(^# Start|^# End|^# Use|^[^#])' ns4/key$1.conf | cut -c3- | \
+ sed 's/allow { 10.53.0.4/allow { any/' >> ns4/named.conf
+}
+
+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
diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh
new file mode 100644
index 0000000..647730e
--- /dev/null
+++ b/bin/tests/system/rndc/tests.sh
@@ -0,0 +1,660 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+DIGCMD="$DIG $DIGOPTS @10.53.0.2 -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf -s"
+
+status=0
+n=0
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "rndc freeze"
+$RNDCCMD 10.53.0.2 freeze | sed 's/^/ns2 /' | cat_i | cat_i
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 text2.nil. TXT > dig.out.1.test$n
+grep 'addition 2' dig.out.1.test$n >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "rndc thaw"
+$RNDCCMD 10.53.0.2 thaw | sed 's/^/ns2 /' | cat_i
+
+n=`expr $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 text3.nil. TXT > dig.out.1.test$n
+grep 'addition 3' dig.out.1.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "rndc sync"
+ret=0
+$RNDCCMD 10.53.0.2 sync nil | sed 's/^/ns2 /' | cat_i
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 text4.nil. TXT > dig.out.1.test$n
+grep 'addition 4' dig.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "rndc sync -clean"
+ret=0
+$RNDCCMD 10.53.0.2 sync -clean nil | sed 's/^/ns2 /' | cat_i
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 text4.nil. TXT > dig.out.1.test$n
+grep 'addition 4' dig.out.1.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "cleaning all zones ($n)"
+$RNDCCMD 10.53.0.2 sync -clean | sed 's/^/ns2 /' | cat_i
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+grep 'not dynamic' rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $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 text6.other. TXT > dig.out.1.test$n
+grep 'addition 6' dig.out.1.test$n >/dev/null || ret=1
+$DIGCMD text7.other. TXT > dig.out.2.test$n
+grep 'addition 7' dig.out.2.test$n >/dev/null || ret=1
+$DIGCMD frozen.other. TXT > dig.out.3.test$n
+grep 'frozen addition' dig.out.3.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $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 text6.nil. TXT > dig.out.1.test$n
+grep 'addition 6' dig.out.1.test$n > /dev/null || ret=1
+$DIGCMD text7.nil. TXT > dig.out.2.test$n
+grep 'addition 7' dig.out.2.test$n > /dev/null || ret=1
+$DIGCMD frozen.nil. TXT > dig.out.3.test$n
+grep 'frozen addition' dig.out.3.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# temp test
+echo_i "dumping stats ($n)"
+$RNDCCMD 10.53.0.2 stats
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "test 'rndc dumpdb' on a empty cache ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 dumpdb > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9
+do
+ tmp=0
+ grep "Dump complete" ns3/named_dump.db > /dev/null || tmp=1
+ [ $tmp -eq 0 ] && break
+ sleep 1
+done
+[ $tmp -eq 1 ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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: 200 (198 automatic)" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+$DIG @10.53.0.4 -p ${PORT} -c ch -t txt foo12345.bind > /dev/null || ret=1
+grep "query: foo12345.bind CH TXT" 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
+$DIG @10.53.0.4 -p ${PORT} -c ch -t txt foo9876.bind > /dev/null || ret=1
+grep "query: foo9876.bind CH TXT" ns4/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+RNDCCMD4="$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf"
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+for i in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288
+do
+ n=`expr $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`
+ if [ "$?" = "0" ]; then
+ expected_size=`expr $i + 1`
+ if [ $actual_size != $expected_size ]; then ret=1; fi
+ else
+ ret=1
+ fi
+
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+done
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "test 'rndc reconfig' with loading of a large zone ($n)"
+ret=0
+cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns6/named.run`
+cp ns6/named.conf ns6/named.conf.save
+echo "zone \"huge.zone\" { type master; 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=`expr $status + $ret`
+sleep 1
+n=`expr $n + 1`
+echo_i "check if zone load was scheduled ($n)"
+grep "scheduled loading new zones" ns6/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "wait for the zones to be loaded ($n)"
+ret=1
+try=0
+while test $try -lt 100
+do
+ sleep 1
+ sed -n "$cur,"'$p' < ns6/named.run | grep "any newly configured zones are now loaded" > /dev/null && {
+ ret=0
+ break
+ }
+ try=`expr $try + 1`
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $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=`expr $status + $ret`
+
+if [ -x "$PYTHON" ]; then
+ n=`expr $n + 1`
+ echo_i "test rndc python bindings ($n)"
+ ret=0
+ $PYTHON > python.out.1.test$n << EOF
+import sys
+sys.path.insert(0, '../../../../bin/python')
+from isc import *
+r = rndc(('10.53.0.5', ${CONTROLPORT}), 'hmac-sha256', '1234abcd8765')
+result = r.call('status')
+print(result['text'])
+EOF
+ grep 'server is up and running' python.out.1.test$n > /dev/null 2>&1 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rootkeysentinel/clean.sh b/bin/tests/system/rootkeysentinel/clean.sh
new file mode 100644
index 0000000..702002b
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
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..6312ca1
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns1/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..065bc6e
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns1/root.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..369f75e
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns1/sign.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+keyid=`expr ${keyname} : 'K.+008+\(.*\)'`
+
+(cd ../ns2 && $SHELL sign.sh ${keyid:-00000} )
+
+cp ../ns2/dsset-example$TP .
+
+cat $infile $keyname.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $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..77425b1
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns2/example.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2da0567
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns2/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "example" {
+ type master;
+ 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..861337b
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns2/sign.sh
@@ -0,0 +1,40 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+oldid=${1:-00000}
+newid=`expr \( ${oldid} + 1000 \) % 65536`
+newid=`expr "0000${newid}" : '.*\(.....\)$'`
+badid=`expr \( ${oldid} + 7777 \) % 65536`
+badid=`expr "0000${badid}" : '.*\(.....\)$'`
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -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 -r $RANDFILE -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..4a73637
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns3/hint.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..ea118ce
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns3/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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-enable 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..4a73637
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns4/hint.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..3a42b3f
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns4/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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-enable yes;
+ dnssec-validation yes;
+ root-key-sentinel no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rootkeysentinel/prereq.sh b/bin/tests/system/rootkeysentinel/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/rootkeysentinel/setup.sh b/bin/tests/system/rootkeysentinel/setup.sh
new file mode 100644
index 0000000..130287b
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 800 $RANDFILE
+
+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..a36ec57
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/tests.sh
@@ -0,0 +1,286 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+newtest() {
+ n=`expr $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`
+oldid=`expr "0000${oldid}" : '.*\(.....\)$'`
+newid=`expr \( ${oldid} + 1000 \) % 65536`
+newid=`expr "0000${newid}" : '.*\(.....\)$'`
+badid=`expr \( ${oldid} + 7777 \) % 65536`
+badid=`expr "0000${badid}" : '.*\(.....\)$'`
+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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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
+
+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=`expr $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=`expr $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-${bad}.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
+
+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=`expr $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
+
+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=`expr $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
+
+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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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
+
+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=`expr $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-${bad}.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
+
+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=`expr $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
+
+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=`expr $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
+
+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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rpz/clean.sh b/bin/tests/system/rpz/clean.sh
new file mode 100644
index 0000000..25ce2c9
--- /dev/null
+++ b/bin/tests/system/rpz/clean.sh
@@ -0,0 +1,21 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Clean up after rpz tests.
+
+rm -f proto.* dsset-* trusted.conf dig.out* nsupdate.tmp ns*/*tmp
+rm -f ns*/*.key ns*/*.private ns2/tld2s.db ns2/bl.tld2.db
+rm -f ns3/bl*.db ns*/*switch ns*/empty.db ns*/empty.db.jnl
+rm -f ns5/requests ns5/example.db ns5/bl.db ns5/*.perf
+rm -f */named.memstats */named.run */named.stats */session.key
+rm -f */*.jnl */*.core */*.pid
+rm -f */policy2.db
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f tmp
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..4605e46
--- /dev/null
+++ b/bin/tests/system/rpz/ns1/named.conf.in
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {type master; 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..0abc1a2
--- /dev/null
+++ b/bin/tests/system/rpz/ns1/root.db
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.
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..039b160
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/base-tld2s.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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
+
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..98b9e57
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/bl.tld2.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; master for slave 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..e30db4b
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/blv2.tld2.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; master for slave 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..8a3d547
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/blv3.tld2.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; master for slave 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..28e5850
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..5cdc60e
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+zone "." { type hint; file "hints"; };
+
+zone "tld2." {type master; file "tld2.db";};
+zone "sub1.tld2." {type master; file "tld2.db";};
+zone "subsub.sub1.tld2." {type master; file "tld2.db";};
+zone "sub2.tld2." {type master; file "tld2.db";};
+zone "subsub.sub2.tld2." {type master; file "tld2.db";};
+zone "sub3.tld2." {type master; file "tld2.db";};
+zone "subsub.sub3.tld2." {type master; file "tld2.db";};
+
+zone "tld2s." {type master; file "tld2s.db";};
+
+zone "bl.tld2." {type master; file "bl.tld2.db"; notify yes; notify-delay 1;};
diff --git a/bin/tests/system/rpz/ns2/tld2.db b/bin/tests/system/rpz/ns2/tld2.db
new file mode 100644
index 0000000..a16d196
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/tld2.db
@@ -0,0 +1,120 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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"
diff --git a/bin/tests/system/rpz/ns3/base.db b/bin/tests/system/rpz/ns3/base.db
new file mode 100644
index 0000000..fee7170
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/base.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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.
diff --git a/bin/tests/system/rpz/ns3/crash1 b/bin/tests/system/rpz/ns3/crash1
new file mode 100644
index 0000000..d0862ed
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/crash1
@@ -0,0 +1,21 @@
+; Copyright (C) 2011-2013 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.
+
+
+; 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..25f4fcf
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/crash2
@@ -0,0 +1,27 @@
+; Copyright (C) 2011-2013 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.
+
+
+; 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..28e5850
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
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..52a7482
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/named.conf.in
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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 no;
+
+ response-policy {
+ 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";
+ }
+ min-ns-dots 0
+ qname-wait-recurse yes
+ ;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." { type hint; file "hints"; };
+
+zone "bl." {type master; file "bl.db";
+ allow-update {any;};};
+zone "bl-2." {type master; file "bl-2.db";
+ allow-update {any;};};
+zone "bl-given." {type master; file "bl-given.db";
+ allow-update {any;};};
+zone "bl-passthru." {type master; file "bl-passthru.db";
+ allow-update {any;};};
+zone "bl-no-op." {type master; file "bl-no-op.db";
+ allow-update {any;};};
+zone "bl-disabled." {type master; file "bl-disabled.db";
+ allow-update {any;};};
+zone "bl-nodata." {type master; file "bl-nodata.db";
+ allow-update {any;};};
+zone "bl-nxdomain." {type master; file "bl-nxdomain.db";
+ allow-update {any;};};
+zone "bl-cname." {type master; file "bl-cname.db";
+ allow-update {any;};};
+zone "bl-wildcname." {type master; file "bl-wildcname.db";
+ allow-update {any;};};
+zone "bl-garden." {type master; file "bl-garden.db";
+ allow-update {any;};};
+zone "bl-drop." {type master; file "bl-drop.db";
+ allow-update {any;};};
+zone "bl-tcp-only." {type master; file "bl-tcp-only.db";
+ allow-update {any;};};
+
+zone "bl.tld2." {type slave; file "bl.tld2.db"; masters {10.53.0.2;};
+ request-ixfr no; masterfile-format text;};
+
+zone "crash1.tld2" {type master; file "crash1";};
+zone "crash2.tld3." {type master; file "crash2";};
diff --git a/bin/tests/system/rpz/ns4/hints b/bin/tests/system/rpz/ns4/hints
new file mode 100644
index 0000000..28e5850
--- /dev/null
+++ b/bin/tests/system/rpz/ns4/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..05a374b
--- /dev/null
+++ b/bin/tests/system/rpz/ns4/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+include "../trusted.conf";
+zone "." { type hint; file "hints"; };
+
+zone "tld4." {type master; file "tld4.db";};
+zone "sub1.tld4." {type master; file "tld4.db";};
+zone "subsub.sub1.tld4." {type master; file "tld4.db";};
+zone "sub2.tld4." {type master; file "tld4.db";};
+zone "subsub.sub2.tld4." {type master; 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..a164818
--- /dev/null
+++ b/bin/tests/system/rpz/ns4/tld4.db
@@ -0,0 +1,64 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; 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..7edcc17
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/empty.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 )
+ NS .
diff --git a/bin/tests/system/rpz/ns5/hints b/bin/tests/system/rpz/ns5/hints
new file mode 100644
index 0000000..28e5850
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..9b2a0bb
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/named.args
@@ -0,0 +1,3 @@
+# run the performace test close to real life
+
+-c named.conf -X named.lock -gd3
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..28b8906
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/named.conf.in
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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 1;
+ notify yes;
+
+ # turn rpz on or off
+ include "rpz-switch";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+zone "." {type hint; file "hints"; };
+
+zone "tld5." {type master; file "tld5.db"; };
+zone "example.tld5." {type master; file "example.db"; };
+
+zone "bl0." {type master; file "bl.db"; };
+zone "bl1." {type master; file "bl.db"; };
+zone "bl2." {type master; file "bl.db"; };
+zone "bl3." {type master; file "bl.db"; };
+zone "bl4." {type master; file "bl.db"; };
+zone "bl5." {type master; file "bl.db"; };
+zone "bl6." {type master; file "bl.db"; };
+zone "bl7." {type master; file "bl.db"; };
+zone "bl8." {type master; file "bl.db"; };
+zone "bl9." {type master; file "bl.db"; };
+zone "bl10." {type master; file "bl.db"; };
+zone "bl11." {type master; file "bl.db"; };
+zone "bl12." {type master; file "bl.db"; };
+zone "bl13." {type master; file "bl.db"; };
+zone "bl14." {type master; file "bl.db"; };
+zone "bl15." {type master; file "bl.db"; };
+zone "bl16." {type master; file "bl.db"; };
+zone "bl17." {type master; file "bl.db"; };
+zone "bl18." {type master; file "bl.db"; };
+zone "bl19." {type master; file "bl.db"; };
+
+zone "policy1" {
+ type master;
+ file "empty.db";
+ also-notify { 10.53.0.6; };
+ allow-update { any; };
+ allow-transfer { any; };
+};
+
+zone "policy2" {
+ type master;
+ file "policy2.db";
+ allow-update { any; };
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/rpz/ns5/tld5.db b/bin/tests/system/rpz/ns5/tld5.db
new file mode 100644
index 0000000..cfdab74
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/tld5.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; RPZ preformance 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
diff --git a/bin/tests/system/rpz/ns6/hints b/bin/tests/system/rpz/ns6/hints
new file mode 100644
index 0000000..28e5850
--- /dev/null
+++ b/bin/tests/system/rpz/ns6/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..f22f7b1
--- /dev/null
+++ b/bin/tests/system/rpz/ns6/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+
+ response-policy { zone "policy1"; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+
+zone "policy1" {
+ type slave;
+ masters { 10.53.0.5; };
+ file "empty.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/rpz/ns7/hints b/bin/tests/system/rpz/ns7/hints
new file mode 100644
index 0000000..28e5850
--- /dev/null
+++ b/bin/tests/system/rpz/ns7/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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..434e246
--- /dev/null
+++ b/bin/tests/system/rpz/ns7/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+
+ response-policy { zone "policy2"; } qname-wait-recurse no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+
+zone "policy2" {
+ type slave;
+ masters { 10.53.0.5; };
+ file "policy2.db";
+ allow-transfer { any; };
+ request-ixfr no; // force axfr on rndc reload
+};
diff --git a/bin/tests/system/rpz/prereq.sh b/bin/tests/system/rpz/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/rpz/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/rpz/qperf.sh b/bin/tests/system/rpz/qperf.sh
new file mode 100644
index 0000000..9c8b391
--- /dev/null
+++ b/bin/tests/system/rpz/qperf.sh
@@ -0,0 +1,20 @@
+#! /bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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..cb73f4a
--- /dev/null
+++ b/bin/tests/system/rpz/setup.sh
@@ -0,0 +1,123 @@
+#! /bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+QPERF=`$SHELL qperf.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 ns6/named.conf.in ns6/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
+
+# 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
+
+# sign the root and a zone in ns2
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+# $1=directory, $2=domain name, $3=input zone file, $4=output file
+signzone () {
+ KEYNAME=`$KEYGEN -q -r $RANDFILE -b 512 -K $1 $2`
+ cat $1/$3 $1/$KEYNAME.key > $1/tmp
+ $SIGNER -Pp -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,\}\) \(.*\)/trusted-keys {"\1" \2 "\3";};/p' $1/$KEYNAME.key >>trusted.conf
+ DSFILENAME=dsset-`echo $2 |sed -e "s/\.$//g"`$TP
+ 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
+ max-policy-ttl 90
+ break-dnssec yes
+ qname-wait-recurse no
+ ;
+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
diff --git a/bin/tests/system/rpz/test1 b/bin/tests/system/rpz/test1
new file mode 100644
index 0000000..f629253
--- /dev/null
+++ b/bin/tests/system/rpz/test1
@@ -0,0 +1,96 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..29f302c
--- /dev/null
+++ b/bin/tests/system/rpz/test2
@@ -0,0 +1,74 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..1a6f373
--- /dev/null
+++ b/bin/tests/system/rpz/test3
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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
+send
diff --git a/bin/tests/system/rpz/test4 b/bin/tests/system/rpz/test4
new file mode 100644
index 0000000..37aabb3
--- /dev/null
+++ b/bin/tests/system/rpz/test4
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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
+send
diff --git a/bin/tests/system/rpz/test4a b/bin/tests/system/rpz/test4a
new file mode 100644
index 0000000..fdc388e
--- /dev/null
+++ b/bin/tests/system/rpz/test4a
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..1a3747c
--- /dev/null
+++ b/bin/tests/system/rpz/test5
@@ -0,0 +1,58 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..ec04681
--- /dev/null
+++ b/bin/tests/system/rpz/test6
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..32eb0c6
--- /dev/null
+++ b/bin/tests/system/rpz/tests.sh
@@ -0,0 +1,646 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# test response policy zones (RPZ)
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/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
+
+HAVE_CORE=
+SAVE_RESULTS=
+
+
+USAGE="$0: [-x]"
+while getopts "x" c; do
+ case $c in
+ x) set -x;;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift `expr $OPTIND - 1 || true`
+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
+}
+
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+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 "+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
+}
+
+# set DIGNM=file name for dig output
+GROUP_NM=
+TEST_NUM=0
+make_dignm () {
+ TEST_NUM=`expr $TEST_NUM + 1`
+ DIGNM=dig.out$GROUP_NM-$TEST_NUM
+ while test -f $DIGNM; do
+ TEST_NUM="$TEST_NUM+"
+ DIGNM=dig.out$GROUP_NM-$TEST_NUM
+ done
+}
+
+setret () {
+ ret=1
+ status=`expr $status + 1`
+ echo_i "$*"
+}
+
+# (re)load the reponse 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 () {
+ # 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 test -f ns$1/base.db; then
+ for NM in ns$1/bl*.db; do
+ cp -f ns$1/base.db $NM
+ done
+ fi
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns$1
+ load_db
+}
+
+# $1=server and irrelevant args $2=error message
+ckalive () {
+ CKALIVE_NS=`expr "$1" : '.*@ns\([1-9]\).*'`
+ 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
+ return 1
+}
+
+ckstats () {
+ HOST=$1
+ LABEL="$2"
+ NSDIR="$3"
+ EXPECTED="$4"
+ $RNDCCMD $HOST stats
+ NEW_CNT=0`sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \
+ $NSDIR/named.stats | tail -1`
+ eval "OLD_CNT=0\$${NSDIR}_CNT"
+ GOT=`expr $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=0`sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \
+ $NSDIR/named.stats | tail -1`
+ eval "OLD_CNT=0\$${NSDIR}_CNT"
+ GOT=`expr $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=`expr $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
+ 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"
+ 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
+ if grep "flags:.* aa .*ad;" $DIGNM; then
+ setret "'dig $1' AA and AD set;"
+ elif grep "flags:.* aa .*ad;" $DIGNM; then
+ setret "'dig $1' AD set;"
+ fi
+ if $PERL $SYSTEMTESTTOP/digcomp.pl $DIGNM $2 >/dev/null; then
+ NEED_TCP=`echo "$1" | sed -n -e 's/[Tt][Cc][Pp].*/TCP/p'`
+ RESULT_TCP=`sed -n -e 's/.*Truncated, retrying in TCP.*/TCP/p' $DIGNM`
+ if test "$NEED_TCP" != "$RESULT_TCP"; then
+ setret "'dig $1' wrong; no or unexpected truncation in $DIGNM"
+ return 1
+ fi
+ clean_result ${DIGNM}*
+ return 0
+ fi
+ setret "'dig $1' wrong; diff $DIGNM $2"
+ return 1
+}
+
+# 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 1
+ fi
+ if test -n "$3" && test "$ADDR_TTL" -ne "$3"; then
+ setret "'dig $2' wrong; TTL=$ADDR_TTL instead of $3 in $DIGNM"
+ return 1
+ 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
+}
+
+# check against a 'here document'
+here () {
+ make_dignm
+ sed -e 's/^[ ]*//' >${DIGNM}_OK
+ digcmd $* >$DIGNM
+ ckresult "$*" ${DIGNM}_OK
+}
+
+# check dropped response
+DROPPED='^;; connection timed out; no servers could be reached'
+drop () {
+ make_dignm
+ digcmd $* >$DIGNM
+ if grep "$DROPPED" $DIGNM >/dev/null; then
+ clean_result ${DIGNM}*
+ return 0
+ fi
+ setret "'dig $1' wrong; response in $DIGNM"
+ return 1
+}
+
+
+# make prototype files to check against rewritten results
+digcmd nonexistent @$ns2 >proto.nxdomain
+digcmd txt-only.tld2 @$ns2 >proto.nodata
+
+
+status=0
+
+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 28
+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 slave policy zone (RT34450)
+cp ns2/blv2.tld2.db.in ns2/bl.tld2.db
+$RNDCCMD 10.53.0.2 reload bl.tld2
+goodsoa="rpz.tld2. hostmaster.ns.tld2. 2 3600 1200 604800 60"
+for i in 0 1 2 3 4 5 6 7 8 9 10
+do
+ soa=`$DIG -p ${PORT} +short soa bl.tld2 @10.53.0.3 -b10.53.0.3`
+ test "$soa" = "$goodsoa" && break
+ sleep 1
+done
+nochange a7-1.tld2 # 19 PASSTHRU
+sleep 1 # ensure that a clock tick has occured so that the reload takes effect
+cp ns2/blv3.tld2.db.in ns2/bl.tld2.db
+goodsoa="rpz.tld2. hostmaster.ns.tld2. 3 3600 1200 604800 60"
+$RNDCCMD 10.53.0.2 reload bl.tld2
+for i in 0 1 2 3 4 5 6 7 8 9 10
+do
+ soa=`$DIG -p ${PORT} +short soa bl.tld2 @10.53.0.3 -b10.53.0.3`
+ test "$soa" = "$goodsoa" && break
+ sleep 1
+done
+nxdomain a7-1.tld2 # 20 slave 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
+
+if $FEATURETEST --rpz-nsdname; then
+ # these tests assume "min-ns-dots 0"
+ start_group "NSDNAME rewrites" test3
+ 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
+ nxdomain a3-1.subsub.sub1.tld2 -tany
+ 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
+ nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash
+ end_group
+ ckstats $ns3 test3 ns3 7
+else
+ echo_i "NSDNAME not checked; named configured with --disable-rpz-nsdname"
+fi
+
+if $FEATURETEST --rpz-nsip; then
+ # these tests assume "min-ns-dots 0"
+ start_group "NSIP rewrites" test4
+ 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
+ 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
+ ckstats $ns3 test4 ns3 4
+else
+ echo_i "NSIP not checked; named configured with --disable-rpz-nsip"
+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'
+ ;; 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"
+ $QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p ${PORT} >/dev/null
+ comment "before real test $1"
+ PFILE="ns5/$2.perf"
+ $RNDCCMD $ns5 notrace
+ $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=`expr \( "$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
+
+
+# restart the main test RPZ server to see if that creates a core file
+if test -z "$HAVE_CORE"; then
+ $PERL $SYSTEMTESTTOP/stop.pl . ns3
+ restart 3
+ 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
+EMSGS=`egrep -l 'invalid rpz|rpz.*failed' ns*/named.run`
+if test -n "$EMSGS"; then
+ setret "error messages in $EMSGS starting with:"
+ egrep 'invalid rpz|rpz.*failed' ns*/named.run | sed -e '10,$d' | cat_i
+fi
+
+echo_i "checking that ttl values are not zeroed when qtype is '*'"
+$DIG +noall +answer -p ${PORT} @$ns3 any a3-2.tld2 > dig.out.any
+ttl=`awk '/a3-2 tld2 text/ {print $2}' dig.out.any`
+if test ${ttl:=0} -eq 0; then setret "failed"; fi
+
+echo_i "checking rpz updates/transfers with parent nodes added after children"
+# regression test for RT #36272: the success condition
+# is the slave server not crashing.
+nsd() {
+ $NSUPDATE -p ${PORT} << EOF
+server $1
+ttl 300
+update $2 $3 IN CNAME .
+update $2 $4 IN CNAME .
+send
+EOF
+ sleep 2
+}
+
+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
+
+echo_i "checking that going from a empty policy zone works"
+nsd $ns5 add '*.x.servfail.policy2.' x.servfail.policy2.
+sleep 1
+$RNDCCMD $ns7 reload policy2
+$DIG z.x.servfail -p ${PORT} @$ns7 > dig.out.ns7
+grep NXDOMAIN dig.out.ns7 > /dev/null || setret I:failed;
+
+echo_i "checking rpz with delegation fails correctly"
+$DIG -p ${PORT} @$ns3 ns example.com > dig.out.delegation
+grep "status: SERVFAIL" dig.out.delegation > /dev/null || setret "I:failed"
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rpzrecurse/README b/bin/tests/system/rpzrecurse/README
new file mode 100644
index 0000000..67546bb
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/README
@@ -0,0 +1,117 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..9723ff5
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ans5/ans.pl
@@ -0,0 +1,79 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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..de97959
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/clean.sh
@@ -0,0 +1,29 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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/named2.conf
+
+rm -f ans*/*.run
+
+rm -f ns*/session.key
diff --git a/bin/tests/system/rpzrecurse/ns1/db.l0 b/bin/tests/system/rpzrecurse/ns1/db.l0
new file mode 100644
index 0000000..af0d9e8
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/db.l0
@@ -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 http://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..36ed1e5
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/db.l1.l0
@@ -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 http://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.db b/bin/tests/system/rpzrecurse/ns1/example.db
new file mode 100644
index 0000000..fd3e887
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/example.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..e8105a2
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/named.conf.in
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ querylog yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "test.example.org" {
+ type master;
+ file "example.db";
+};
+
+zone "l0" {
+ type master;
+ file "db.l0";
+};
+
+zone "l1.l0" {
+ type master;
+ file "db.l1.l0";
+};
+
+zone "l2.l1.l0" {
+ type master;
+ file "does-not-exist";
+};
+
+zone "test1.example.net" {
+ type master;
+ file "test1.example.net.db";
+};
+
+zone "test2.example.net" {
+ type master;
+ file "test2.example.net.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..1b1de3f
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4d07a41
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/test1.example.net.db
@@ -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 http://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..bfe46aa
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/test2.example.net.db
@@ -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 http://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..9b99e45
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.clientip1
@@ -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 http://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..49ab881
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.clientip2
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..770269c
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.clientip21
@@ -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 http://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.log1 b/bin/tests/system/rpzrecurse/ns2/db.log1
new file mode 100644
index 0000000..f18cfe1
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.log1
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..88722ff
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.log2
@@ -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 http://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..b432802
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.log3
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.wildcard1 b/bin/tests/system/rpzrecurse/ns2/db.wildcard1
new file mode 100644
index 0000000..8d6e8ad
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard1
@@ -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 http://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..8d6e8ad
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard2a
@@ -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 http://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..c362314
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard2b
@@ -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 http://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..b60bdd1
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard3
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..94bea9e
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.clientip.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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;
+
+ # policy zones to be tested
+ zone "clientip1" { type master; file "db.clientip1"; };
+ zone "clientip2" { type master; file "db.clientip2"; };
+};
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..5ddc68b
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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;
+
+ # policy zones to be tested
+ zone "clientip21" { type master; file "db.clientip21"; };
+};
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..cd64d3d
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.conf.header.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ querylog yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..f690495
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.default.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+};
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..a172a27
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.log.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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;
+
+ # policy zones to be tested
+ zone "log1" { type master; file "db.log1"; };
+ zone "log2" { type master; file "db.log2"; };
+ zone "log3" { type master; file "db.log3"; };
+};
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..ae861bb
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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;
+ };
+
+ # policy zones to be tested
+ zone "wildcard1" { type master; file "db.wildcard1"; };
+};
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..edcae05
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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;
+ };
+
+ # policy zones to be tested
+ zone "wildcard2a" { type master; file "db.wildcard2a"; };
+ zone "wildcard2b" { type master; file "db.wildcard2b"; };
+};
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..2d0f1b4
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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;
+ };
+
+ # policy zones to be tested
+ zone "wildcard3" { type master; file "db.wildcard3"; };
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/root.hint b/bin/tests/system/rpzrecurse/ns2/root.hint
new file mode 100644
index 0000000..f627479
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..3fb4a24
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/example.db
@@ -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 http://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..fa5ee30
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/named1.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ response-policy { zone "policy"; };
+};
+
+zone "policy" { type master; file "policy.db"; };
+
+zone "example.tld" { type master; file "example.db"; };
+
+zone "." { type master; 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..a50a9cd
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/named2.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ response-policy { zone "policy"; } nsip-wait-recurse no;
+};
+
+zone "policy" { type master; file "policy.db"; };
+
+zone "example.tld" { type master; file "example.db"; };
+
+zone "." { type master; 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..c2437d2
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/policy.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..b12a184
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/root.db
@@ -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 http://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..66cd956
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns4/child.example.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..24e5115
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns4/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+zone "child.example.tld" { type master; file "child.example.db"; };
diff --git a/bin/tests/system/rpzrecurse/prereq.sh b/bin/tests/system/rpzrecurse/prereq.sh
new file mode 100644
index 0000000..6f0487e
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/prereq.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+ret=0
+$FEATURETEST --rpz-nsdname || ret=1
+$FEATURETEST --rpz-nsip || ret=1
+
+if [ $ret != 0 ]; then
+ echo "I:This test requires NSIP AND NSDNAME support in RPZ." >&2
+ exit 1
+fi
+
+$SHELL ../testcrypto.sh || exit 255
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/rpzrecurse/setup.sh b/bin/tests/system/rpzrecurse/setup.sh
new file mode 100644
index 0000000..4680655
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/setup.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+USAGE="$0: [-xD]"
+DEBUG=
+while getopts "xD" c; do
+ case $c in
+ x) set -x; DEBUG=-x;;
+ N) NOCLEAN=set;;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift `expr $OPTIND - 1 || true`
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+OPTIND=1
+
+[ ${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 ns3/named2.conf.in ns3/named2.conf
+
+copy_setports ns4/named.conf.in ns4/named.conf
diff --git a/bin/tests/system/rpzrecurse/testgen.pl b/bin/tests/system/rpzrecurse/testgen.pl
new file mode 100755
index 0000000..af43bbd
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/testgen.pl
@@ -0,0 +1,341 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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';
+ };
+
+ # policy zones to be tested
+EOB
+
+my $qname_wait_recurse = <<'EOB';
+ } 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 master; 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..172a806
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/tests.sh
@@ -0,0 +1,389 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+t=0
+
+# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists)
+run_server() {
+ TESTNAME=$1
+
+ echo_i "stopping resolver"
+ $PERL $SYSTEMTESTTOP/stop.pl . ns2
+
+ sleep 1
+
+ echo_i "starting resolver using named.$TESTNAME.conf"
+ cp -f ns2/named.$TESTNAME.conf ns2/named.conf
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns2
+}
+
+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=`expr $t + 1`
+ echo_i "testing $NAME doesn't recurse (${t})"
+ 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=`expr $t + 1`
+ echo_i "testing $NAME recurses (${t})"
+ run_query $TESTNAME $LINE && {
+ echo_i "test ${t} failed"
+ status=1
+ }
+}
+
+t=`expr $t + 1`
+echo_i "testing that l1.l0 exists without RPZ (${t})"
+$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=`expr $t + 1`
+echo_i "testing that l2.l1.l0 returns SERVFAIL without RPZ (${t})"
+$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=`expr $t + 1`
+ echo_i "testing that ${ni} of 33 queries skip recursion (${t})"
+ 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=`expr $c + $?`
+ done
+ skipped=`expr 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=`expr $t + 1`
+echo_i "running dig to cache CNAME record (${t})"
+$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME > dig.out.${t}
+sleep 1
+echo_i "suspending authority server"
+if [ "$CYGWIN" ]; then
+ WINPID=`cat ns1/named.pid`
+ PID=`ps | sed 's/^..//' | awk '$4 == '$WINPID | awk '{print $1}'`
+else
+ PID=`cat ns1/named.pid`
+fi
+kill -TSTP $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/^/I:ns2 /'
+sleep 1
+t=`expr $t + 1`
+echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})"
+$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A > 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/^/I:ns2 /'
+sleep 1
+echo_i "resuming authority server"
+if [ "$CYGWIN" ]; then
+ WINPID=`cat ns1/named.pid`
+ PID=`ps | sed 's/^..//' | awk '$4 == '$WINPID | awk '{print $1}'`
+else
+ PID=`cat ns1/named.pid`
+fi
+kill -CONT $PID
+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=`expr $t + 1`
+echo_i "running dig to cache CNAME record (${t})"
+$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME > dig.out.${t}
+sleep 1
+echo_i "suspending authority server"
+if [ "$CYGWIN" ]; then
+ WINPID=`cat ns1/named.pid`
+ PID=`ps | sed 's/^..//' | awk '$4 == '$WINPID | awk '{print $1}'`
+else
+ PID=`cat ns1/named.pid`
+fi
+kill -TSTP $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/^/I:ns2 /'
+sleep 1
+t=`expr $t + 1`
+echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})"
+$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A > dig.out.${t} &
+sleep 1
+echo_i "removing the policy zone"
+cp ns2/named.default.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reconfig 2>&1 | sed 's/^/I:ns2 /'
+sleep 1
+echo_i "resuming authority server"
+if [ "$CYGWIN" ]; then
+ WINPID=`cat ns1/named.pid`
+ PID=`ps | sed 's/^..//' | awk '$4 == '$WINPID | awk '{print $1}'`
+else
+ PID=`cat ns1/named.pid`
+fi
+kill -CONT $PID
+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 CLIENT-IP behavior
+t=`expr $t + 1`
+echo_i "testing CLIENT-IP behavior (${t})"
+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=`expr $t + 1`
+echo_i "testing CLIENT-IP behavior #2 (${t})"
+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=`expr $t + 1`
+echo_i "testing RPZ log clause (${t})"
+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 via 32.4.0.53.10.rpz-client-ip.log1" > /dev/null && {
+ echo_i " 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 via 32.3.0.53.10.rpz-client-ip.log2" > /dev/null || {
+ echo_i " 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 via 32.2.0.53.10.rpz-client-ip.log3" > /dev/null || {
+ echo_i " failed: expected rewrite message for policy zone log3 was not logged"
+ status=1
+}
+
+# Check wildcard behavior
+
+t=`expr $t + 1`
+echo_i "testing wildcard behavior with 1 RPZ zone (${t})"
+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=`expr $t + 1`
+echo_i "testing wildcard behavior with 2 RPZ zones (${t})"
+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=`expr $t + 1`
+echo_i "testing wildcard behavior with 1 RPZ zone and no non-wildcard triggers (${t})"
+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=`expr $t + 1`
+echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)"
+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=`expr $t2 - $t1`
+echo_i "elasped time $p1 seconds"
+
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
+cp -f ns3/named2.conf ns3/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null
+
+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=`expr $t4 - $t3`
+echo_i "elasped time $p2 seconds"
+
+if test $p1 -le $p2; then ret=1; fi
+if test $ret != 0; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/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..11e7d2d
--- /dev/null
+++ b/bin/tests/system/rrchecker/clean.sh
@@ -0,0 +1,11 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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..2944016
--- /dev/null
+++ b/bin/tests/system/rrchecker/tests.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "class list ($n)"
+$RRCHECKER -C > classlist.out
+$DIFF classlist.out classlist.good || { echo_i "failed"; status=`expr $status + 1`; }
+
+n=`expr $n + 1`
+echo_i "type list ($n)"
+$RRCHECKER -T > typelist.out
+$DIFF typelist.out typelist.good || { echo_i "failed"; status=`expr $status + 1`; }
+
+n=`expr $n + 1`
+echo_i "private type list ($n)"
+$RRCHECKER -P > privatelist.out
+$DIFF privatelist.out privatelist.good || { echo_i "failed"; status=`expr $status + 1`; }
+
+myecho() {
+cat << EOF
+$*
+EOF
+}
+
+n=`expr $n + 1`
+echo_i "check conversions to canonical format ($n)"
+ret=0
+$SHELL ../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=`expr $status + 1`; }
+
+n=`expr $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=`expr $status + 1`; }
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rrchecker/typelist.good b/bin/tests/system/rrchecker/typelist.good
new file mode 100644
index 0000000..8938994
--- /dev/null
+++ b/bin/tests/system/rrchecker/typelist.good
@@ -0,0 +1,77 @@
+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
+SPF
+UINFO
+UID
+GID
+UNSPEC
+NID
+L32
+L64
+LP
+EUI48
+EUI64
+URI
+CAA
+AVC
+DOA
+TA
+DLV
diff --git a/bin/tests/system/rrl/broken.conf b/bin/tests/system/rrl/broken.conf
new file mode 100644
index 0000000..75df4fc
--- /dev/null
+++ b/bin/tests/system/rrl/broken.conf
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port 5300;
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ notify 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;
+ };
+
+ additional-from-cache no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+controls {
+ inet 10.53.0.5 port 9953 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..55a1c12
--- /dev/null
+++ b/bin/tests/system/rrl/clean.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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.out
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..4605e46
--- /dev/null
+++ b/bin/tests/system/rrl/ns1/named.conf.in
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "." {type master; 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..c628370
--- /dev/null
+++ b/bin/tests/system/rrl/ns1/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..cb67a8b
--- /dev/null
+++ b/bin/tests/system/rrl/ns2/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+. 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..73e3296
--- /dev/null
+++ b/bin/tests/system/rrl/ns2/named.conf.in
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ 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;
+
+ 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;
+ };
+
+ additional-from-cache no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+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 master; 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..4a4b97a
--- /dev/null
+++ b/bin/tests/system/rrl/ns2/tld2.db
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..cb67a8b
--- /dev/null
+++ b/bin/tests/system/rrl/ns3/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+. 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..5be45fa
--- /dev/null
+++ b/bin/tests/system/rrl/ns3/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+
+ // 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 master; 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..26e9f33
--- /dev/null
+++ b/bin/tests/system/rrl/ns3/tld3.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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..cb67a8b
--- /dev/null
+++ b/bin/tests/system/rrl/ns4/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+. 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..a35e353
--- /dev/null
+++ b/bin/tests/system/rrl/ns4/named.conf.in
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+
+ 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;
+ };
+
+ additional-from-cache no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+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 master; 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..5b746a0
--- /dev/null
+++ b/bin/tests/system/rrl/ns4/tld4.db
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; 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
diff --git a/bin/tests/system/rrl/setup.sh b/bin/tests/system/rrl/setup.sh
new file mode 100644
index 0000000..4563f04
--- /dev/null
+++ b/bin/tests/system/rrl/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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/rrl/tests.sh b/bin/tests/system/rrl/tests.sh
new file mode 100644
index 0000000..4742751
--- /dev/null
+++ b/bin/tests/system/rrl/tests.sh
@@ -0,0 +1,282 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# test response rate limiting
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/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 `expr $OPTIND - 1 || true`
+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="+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=`expr $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() {
+ BAD=no
+ ADDRS=`egrep "^$2$" mdig.out-$1 2>/dev/null | wc -l`
+ # count simple truncated and truncated NXDOMAIN as TC
+ TC=`egrep "^TC|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l`
+ DROP=`egrep "^drop$" mdig.out-$1 2>/dev/null | wc -l`
+ # count NXDOMAIN and truncated NXDOMAIN as NXDOMAIN
+ NXDOMAIN=`egrep "^NXDOMAIN|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l`
+ SERVFAIL=`egrep "^SERVFAIL$" mdig.out-$1 2>/dev/null | wc -l`
+ NOERROR=`egrep "^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=`sed -n -e "s/[ ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" \
+ ns2/named.stats | tail -1`
+ C=`expr 0$C + 0`
+
+ 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
+# or with "additional-from-cache no"
+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 'x$CNT.a2.tld2'
+# These should be counted and limited but are not. See RT33138.
+burst 10 '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 wild card answers.
+# The parent name of the 30 requests is counted.
+ck_result 'x*.a2.tld2' 192.0.2.2 2 10 18 0 0 12
+
+# These should be limited but are not. See RT33138.
+ck_result 'y.x*.a2.tld2' 192.0.2.2 10 0 0 0 0 10
+
+#########
+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
+
+grep "would limit" ns4/named.run >/dev/null 2>&1 ||
+setret "\"would limit\" not found in log file."
+
+$NAMED -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/rrsetorder/clean.sh b/bin/tests/system/rrsetorder/clean.sh
new file mode 100644
index 0000000..b88c8d1
--- /dev/null
+++ b/bin/tests/system/rrsetorder/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.test*
+rm -f dig.out.cyclic dig.out.fixed dig.out.random
+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
diff --git a/bin/tests/system/rrsetorder/dig.out.fixed.good b/bin/tests/system/rrsetorder/dig.out.fixed.good
new file mode 100644
index 0000000..eaf9c63
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good1 b/bin/tests/system/rrsetorder/dig.out.random.good1
new file mode 100644
index 0000000..c272c75
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good10 b/bin/tests/system/rrsetorder/dig.out.random.good10
new file mode 100644
index 0000000..6a39e3f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good11 b/bin/tests/system/rrsetorder/dig.out.random.good11
new file mode 100644
index 0000000..efbc792
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good12 b/bin/tests/system/rrsetorder/dig.out.random.good12
new file mode 100644
index 0000000..c859a2e
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good13 b/bin/tests/system/rrsetorder/dig.out.random.good13
new file mode 100644
index 0000000..49bf54b
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good14 b/bin/tests/system/rrsetorder/dig.out.random.good14
new file mode 100644
index 0000000..974aa89
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good15 b/bin/tests/system/rrsetorder/dig.out.random.good15
new file mode 100644
index 0000000..e8deb67
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good16 b/bin/tests/system/rrsetorder/dig.out.random.good16
new file mode 100644
index 0000000..f467087
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good17 b/bin/tests/system/rrsetorder/dig.out.random.good17
new file mode 100644
index 0000000..6082a25
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good18 b/bin/tests/system/rrsetorder/dig.out.random.good18
new file mode 100644
index 0000000..07eefa0
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good19 b/bin/tests/system/rrsetorder/dig.out.random.good19
new file mode 100644
index 0000000..a5530c6
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good2 b/bin/tests/system/rrsetorder/dig.out.random.good2
new file mode 100644
index 0000000..00da93a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good20 b/bin/tests/system/rrsetorder/dig.out.random.good20
new file mode 100644
index 0000000..6dcf6da
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good21 b/bin/tests/system/rrsetorder/dig.out.random.good21
new file mode 100644
index 0000000..9dcc63f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good22 b/bin/tests/system/rrsetorder/dig.out.random.good22
new file mode 100644
index 0000000..4c51aa6
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good23 b/bin/tests/system/rrsetorder/dig.out.random.good23
new file mode 100644
index 0000000..eaf9c63
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good24 b/bin/tests/system/rrsetorder/dig.out.random.good24
new file mode 100644
index 0000000..c25c756
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good3 b/bin/tests/system/rrsetorder/dig.out.random.good3
new file mode 100644
index 0000000..4d50059
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good4 b/bin/tests/system/rrsetorder/dig.out.random.good4
new file mode 100644
index 0000000..0b34afa
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good5 b/bin/tests/system/rrsetorder/dig.out.random.good5
new file mode 100644
index 0000000..efe0e25
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good6 b/bin/tests/system/rrsetorder/dig.out.random.good6
new file mode 100644
index 0000000..d2ca6fc
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good7 b/bin/tests/system/rrsetorder/dig.out.random.good7
new file mode 100644
index 0000000..0d8312a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good8 b/bin/tests/system/rrsetorder/dig.out.random.good8
new file mode 100644
index 0000000..3b27693
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/dig.out.random.good9 b/bin/tests/system/rrsetorder/dig.out.random.good9
new file mode 100644
index 0000000..61192af
--- /dev/null
+++ b/bin/tests/system/rrsetorder/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/ns1/named.conf.in b/bin/tests/system/rrsetorder/ns1/named.conf.in
new file mode 100644
index 0000000..e3430f7
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type master;
+ 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..3229825
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns1/root.db
@@ -0,0 +1,39 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
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..ae7eb95
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns2/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ // flush-zones-on-shutdown yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type slave;
+ masters { 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..9597bb7
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns3/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ notify yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ 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..fea31e1
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns4/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ acache-enable 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/setup.sh b/bin/tests/system/rrsetorder/setup.sh
new file mode 100644
index 0000000..3a14fe9
--- /dev/null
+++ b/bin/tests/system/rrsetorder/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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/rrsetorder/tests.sh b/bin/tests/system/rrsetorder/tests.sh
new file mode 100644
index 0000000..4cc21cd
--- /dev/null
+++ b/bin/tests/system/rrsetorder/tests.sh
@@ -0,0 +1,472 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short +nocookie"
+DIGCMD="$DIG $DIGOPTS -p ${PORT}"
+
+status=0
+
+if grep "^#define DNS_RDATASET_FIXED" $TOP/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 (master)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ $DIGCMD @10.53.0.1 fixed.example > dig.out.fixed || ret=1
+ $DIFF dig.out.fixed dig.out.fixed.good >/dev/null || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+else
+ echo_i "Checking order fixed behaves as cyclic when disabled (master)"
+ 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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (master + 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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+#
+#
+#
+echo_i "Checking order cyclic (master)"
+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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+echo_i "Checking order random (master)"
+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
+ 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
+ $DIGCMD @10.53.0.1 random.example > dig.out.random || ret=1
+ match=0
+ for j 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
+ eval "$DIFF dig.out.random dig.out.random.good$j >/dev/null && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=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
+ eval "match=\`expr \$match + \$match$i\`"
+done
+echo_i "Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+#
+#
+#
+if $test_fixed; then
+ echo_i "Checking order fixed (slave)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ $DIGCMD @10.53.0.2 fixed.example > dig.out.fixed || ret=1
+ $DIFF dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (slave + 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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+#
+#
+#
+echo_i "Checking order cyclic (slave)"
+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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+echo_i "Checking order random (slave)"
+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
+ 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
+ $DIGCMD @10.53.0.2 random.example > dig.out.random || ret=1
+ match=0
+ for j 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
+ eval "$DIFF dig.out.random dig.out.random.good$j >/dev/null && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=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
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo_i "Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "Shutting down slave"
+
+(cd ..; $SHELL stop.sh rrsetorder ns2 )
+
+echo_i "Checking for slave's on disk copy of zone"
+
+if [ ! -f ns2/root.bk ]
+then
+ echo_i "failed";
+ status=`expr $status + 1`
+fi
+
+echo_i "Re-starting slave"
+
+(cd ..; $PERL start.pl --noclean --port ${PORT} rrsetorder ns2 )
+
+#
+#
+#
+if $test_fixed; then
+ echo_i "Checking order fixed (slave 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
+ $DIGCMD @10.53.0.2 fixed.example > dig.out.fixed || ret=1
+ $DIFF dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (slave + 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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+#
+#
+#
+echo_i "Checking order cyclic (slave 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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+echo_i "Checking order random (slave loaded from disk)"
+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
+ 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
+ $DIGCMD @10.53.0.2 random.example > dig.out.random || ret=1
+ match=0
+ for j 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
+ eval "$DIFF dig.out.random dig.out.random.good$j >/dev/null && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=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
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo_i "Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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
+ $DIGCMD @10.53.0.3 fixed.example > dig.out.fixed || ret=1
+ $DIFF dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (cache + additional)"
+ret=0
+# prime acache
+$DIGCMD @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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+#
+#
+#
+echo_i "Checking order cyclic (cache)"
+ret=0
+# prime acache
+$DIGCMD @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=`expr $i % 4`
+ $DIGCMD @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=`expr $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=`expr $status + $ret`
+
+echo_i "Checking order random (cache)"
+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
+ 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
+ $DIGCMD @10.53.0.3 random.example > dig.out.random || ret=1
+ match=0
+ for j 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
+ eval "$DIFF dig.out.random dig.out.random.good$j >/dev/null && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=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
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo_i "Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+echo_i "Checking default order no match in rrset-order (random)"
+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
+ 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
+ $DIGCMD @10.53.0.4 random.example > dig.out.random|| ret=1
+ match=0
+ for j 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
+ eval "$DIFF dig.out.random dig.out.random.good$j >/dev/null && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=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
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo_i "Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rsabigexponent/Makefile.in b/bin/tests/system/rsabigexponent/Makefile.in
new file mode 100644
index 0000000..af2b0f1
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/Makefile.in
@@ -0,0 +1,50 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id$
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@
+CWARNINGS =
+
+DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+DNSDEPLIBS = ../../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = bigkey@EXEEXT@
+
+OBJS = bigkey.@O@
+
+SRCS = bigkey.c
+
+@BIND9_MAKE_RULES@
+
+all: bigkey@EXEEXT@
+
+bigkey@EXEEXT@: ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/tests/system/rsabigexponent/bigkey.c b/bin/tests/system/rsabigexponent/bigkey.c
new file mode 100644
index 0000000..4462f2e
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/bigkey.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#if defined(OPENSSL) || defined(PKCS11CRYPTO)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.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 <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/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+#ifdef OPENSSL
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER <= 0x00908000L
+#define USE_FIX_KEY_FILES
+#endif
+#else
+#define USE_FIX_KEY_FILES
+#endif
+
+#ifdef USE_FIX_KEY_FILES
+
+/*
+ * Use a fixed key file pair if OpenSSL doesn't support > 32 bit exponents.
+ */
+
+int
+main(int argc, char **argv) {
+ FILE *fp;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ fp = fopen("Kexample.+005+10264.private", "w");
+ if (fp == NULL) {
+ perror("fopen(Kexample.+005+10264.private)");
+ exit(1);
+ }
+
+ fputs("Private-key-format: v1.3\n", fp);
+ fputs("Algorithm: 5 (RSASHA1)\n", fp);
+ fputs("Modulus: yhNbLRPA7VpLCXcgMvBwsfe7taVaTvLPY3AI+YolKwqD6"
+ "/3nLlCcz4kBOTOkQBf9bmO98WnKuOWoxuEOgudoDvQOzXNl9RJtt61"
+ "IRMscAlsVtTIfAjPLhcGy32l2s5VYWWVXx/qkcf+i/JC38YXIuVdiA"
+ "MtbgQV40ffM4lAbZ7M=\n", fp);
+ fputs("PublicExponent: AQAAAAAAAQ==\n", fp);
+ fputs("PrivateExponent: gfXvioazoFIJp3/H2kJncrRZaqjIf9+21CL1i"
+ "XecBOof03er8ym5AKopZQM8ie+qxvhDkIJ8YDrB7UbDxmFpPceHWYM"
+ "X0vDWQCIiEiKzRfCsBOjgJu6HS15G/oZDqDwKat+yegtzxhg48BCPq"
+ "zfHLXXUvBTA/HK/u8L1LwggqHk=\n", fp);
+ fputs("Prime1: 7xAPHsNnS0w7CoEnIQiu+SrmHsy86HKJOEm9FiQybRVCwf"
+ "h4ZRQl+Z9mUbb9skjPvkM6ZeuzXTFkOjdck2y1NQ==\n", fp);
+ fputs("Prime2: 2GRzzqyRR2gfITPug8Rddxt647/2DrAuKricX/AXyGcuHM"
+ "vTZ+v+mfgJn6TFqSn4SBF2zHJ876lWbQ+12aNORw==\n", fp);
+ fputs("Exponent1: PnGTwxiT59N/Rq/FSAwcwoAudiF/X3iK0X09j9Dl8cY"
+ "DYAJ0bhB9es1LIaSsgLSER2b1kHbCp+FQXGVHJeZ07Q==\n", fp);
+ fputs("Exponent2: Ui+zxA/zbnUSYnz+wdbrfBD2aTeKytZG4ASI3oPDZag"
+ "V9YC0eZRPjI82KQcFXoj1b/fV/HzT9/9rhU4mvCGjLw==\n", fp);
+ fputs("Coefficient: sdCL6AdOaCr9c+RO8NCA492MOT9w7K9d/HauC+fif"
+ "2iWN36dA+BCKaeldS/+6ZTnV2ZVyVFQTeLJM8hplxDBwQ==\n", fp);
+
+ if (fclose(fp) != 0) {
+ perror("fclose(Kexample.+005+10264.private)");
+ exit(1);
+ }
+
+ fp = fopen("Kexample.+005+10264.key", "w");
+ if (fp == NULL) {
+ perror("fopen(Kexample.+005+10264.key)");
+ exit(1);
+ }
+
+ fputs("; This is a zone-signing key, keyid 10264, for example.\n", fp);
+ fputs("example. IN DNSKEY 256 3 5 BwEAAAAAAAHKE1stE8DtWksJdyA"
+ "y8HCx97u1pVpO8s9jcAj5iiUrCoPr /ecuUJzPiQE5M6RAF/1uY73x"
+ "acq45ajG4Q6C52gO9A7Nc2X1Em23rUhE yxwCWxW1Mh8CM8uFwbLfaX"
+ "azlVhZZVfH+qRx/6L8kLfxhci5V2IAy1uB BXjR98ziUBtnsw==\n", fp);
+
+ if (fclose(fp) != 0) {
+ perror("close(Kexample.+005+10264.key)");
+ exit(1);
+ }
+
+ return(0);
+}
+#else
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+
+dst_key_t *key;
+dns_fixedname_t fname;
+dns_name_t *name;
+unsigned int bits = 1024U;
+isc_entropy_t *ectx;
+isc_entropysource_t *source;
+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__); \
+ 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");
+ 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__);
+ exit(1);
+ }
+
+ dns_result_register();
+
+ CHECK(isc_mem_create(0, 0, &mctx), "isc_mem_create()");
+ CHECK(isc_entropy_create(mctx, &ectx), "isc_entropy_create()");
+ CHECK(isc_entropy_usebestsource(ectx, &source,
+ "../random.data",
+ ISC_ENTROPY_KEYBOARDNO),
+ "isc_entropy_usebestsource(\"../random.data\")");
+ CHECK(dst_lib_init2(mctx, ectx, NULL, 0), "dst_lib_init2()");
+ CHECK(isc_log_create(mctx, &log_, &logconfig), "isc_log_create()");
+ isc_log_setcontext(log_);
+ dns_log_init(log_);
+ dns_log_setcontext(log_);
+ CHECK(isc_log_settag(logconfig, "bigkey"), "isc_log_settag()");
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ CHECK(isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC,
+ level,
+ &destination,
+ ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL),
+ "isc_log_createchannel()");
+ 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_RSASHA1,
+ 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);
+ if (source != NULL)
+ isc_entropy_destroysource(&source);
+ isc_entropy_detach(&ectx);
+ dst_lib_destroy();
+ dns_name_destroy();
+ isc_mem_destroy(&mctx);
+ return (0);
+}
+#endif
+
+#else /* OPENSSL || PKCS11CRYPTO */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/util.h>
+
+int
+main(int argc, char **argv) {
+ UNUSED(argc);
+ UNUSED(argv);
+ fprintf(stderr, "Compiled without Crypto\n");
+ exit(1);
+}
+
+#endif /* OPENSSL || PKCS11CRYPTO */
+/*! \file */
diff --git a/bin/tests/system/rsabigexponent/clean.sh b/bin/tests/system/rsabigexponent/clean.sh
new file mode 100644
index 0000000..bba0f11
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
diff --git a/bin/tests/system/rsabigexponent/conf/bad01.conf b/bin/tests/system/rsabigexponent/conf/bad01.conf
new file mode 100644
index 0000000..1c56cc3
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/bad01.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..671199d
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/bad02.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..d7edae6
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/bad03.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..bfa7a45
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/good01.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..d87fb7f
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/good02.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..0a70e29
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/good03.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ 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..a43c02b
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns1/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..d205fc8
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns1/root.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..8570855
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns1/sign.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+cp ../ns2/dsset-example.in dsset-example$TP
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+
+cat $infile $keyname.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $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.+005+05896.key b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.key
new file mode 100644
index 0000000..1030c21
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.key
@@ -0,0 +1,2 @@
+; This is a key-signing key, keyid 5896, for example.
+example. IN DNSKEY 257 3 5 AwEAAaLNbgMfH/XUwZC9DBVG4OpYVUVyCyZEBqhk3k6WziIAY+2f7MN3 L9CoZR9GqfqM+/c6g8gfkIaZZ2YP/YUUaN73xH/nxtHYkrP5Rqe/dw7q ONnsVwvf3HJ8HvURG3wjaOrPoe207+HpNTNhe/sT2usKhokSU8yKB0DK lnrKQvp9vScsIB/RsIxOXWmYgOMkSXtpI3lQ07l1i2Tv6UnecD9s8ruk fl/gPbRBketLYACrqpb2j/1f7ciQv+rz1GnN9ma8XK1Yw8173/hrVL1S /ZqTGczwdeA3AVyiHThOZ15EPhSuL7jaJusHOi43Aa8ZfCMCeimT73F5 epktGomAxFU=
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.private b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.private
new file mode 100644
index 0000000..dbac306
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+05896.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.3
+Algorithm: 5 (RSASHA1)
+Modulus: os1uAx8f9dTBkL0MFUbg6lhVRXILJkQGqGTeTpbOIgBj7Z/sw3cv0KhlH0ap+oz79zqDyB+QhplnZg/9hRRo3vfEf+fG0diSs/lGp793Duo42exXC9/ccnwe9REbfCNo6s+h7bTv4ek1M2F7+xPa6wqGiRJTzIoHQMqWespC+n29JywgH9GwjE5daZiA4yRJe2kjeVDTuXWLZO/pSd5wP2zyu6R+X+A9tEGR60tgAKuqlvaP/V/tyJC/6vPUac32ZrxcrVjDzXvf+GtUvVL9mpMZzPB14DcBXKIdOE5nXkQ+FK4vuNom6wc6LjcBrxl8IwJ6KZPvcXl6mS0aiYDEVQ==
+PublicExponent: AQAB
+PrivateExponent: K9juX1LbtccmlwgDoBtl6lf+J2UO0bCSpnn8UehV/lxijZZ8Gy0XqLgh/Cl5EG02U6Dj61ts/oOEkL2Px272y86pktVm/A+7e1ORDw8HTvIQe8kmrKEPa5o4cEK6R1X2JP/lGfOYhBzeYkdIMBhp5tH/6B0Sis1GJNIrc0jUf0g+JvOH/j1SpLoKoDpHUwOWnAt92AZsYhyJgeDXgw+xTBcOVvRfmh3Zmoi6x58lmQsU3loloqQ2V2V3xw1qEhTwBtFiguqeUV/FZl+RerT+lld7v2KkuxchyxlCCavgq6bZSUpn3TxcmnK6pj42oTy11hG9PHvIS8VNpGLr0p6mpQ==
+Prime1: 2KZlb2BXJHEJJv2iuJoddNuDlDStG77cA7FR84Dsarbc5rHj1BjwOPDec235LQOzNAAVMTh3B8/8kcAkx/U0F2FPfgAS/ZK2dOBKcJFU4bmUQDsLMXJn67Pf7d1HeDYfVPSFp1Ib/G91dXuo11+nRZJRfKUW19aFYXybSLVmifM=
+Prime2: wF9HHnv17f1L3VLBJ+qndiPcp/l24fVk5xWrbZlivK+WFrZkHFbmN+WRIkjKbe1mBf4z2fMp1JZKt8wViJVG9Bkk2wSCQA74MrejPFlD9AEMC/TrV7F/l89DryG9YeLAk6td38opGiAmRHzSdrjstUF+iv7IAW+fghPQ3O4ogpc=
+Exponent1: Nmtlo1phyUeTcvXW/+PGbmoNXRb2PLfucAcEfNPvjsasKk6Y2dgBz2vBlOEU7Be31eIHcLusOowl9z56fre7A/xviUjffE50AluslyYKWkDRWmj6YMtKC0y9fPROVYXSzPY29FaNrRUaPg531NG0JKeiTFrzp/e8vUYdg1/9h70=
+Exponent2: r5+MNwlmaQJBG2psivuQLKvqy7NU1E8K8mj3G1TYLniCpnOXC8RN4yQDDvCzVg5QgRIk1kpHmxwmVIvN8OaPY1P9MLJ6Eu9Xqj26meLIxd+a1uOfY2zZloeTPDSqR84Sj/338tIGGiLVrNrj7Z1ABO4pD84wXBdC4SckHD6U3zs=
+Coefficient: c1jE021ke1G/1+C/mqhVtXF9/+ivfw9Ae6na3PofQREs3wiBJH7kpbLmTqc1ovXrHA3BbD1CfWUBhrFK/n5MvsU59VGmz5mD+HGsHC1eoaS4JCG5EWFUP8MStiv+JJGyfuK8MUGsEXQorfQmzGXhe5N2S+4dEYDfksSVd9Wg9d0=
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.key b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.key
new file mode 100644
index 0000000..5343267
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.key
@@ -0,0 +1,2 @@
+; This is a zone-signing key, keyid 51829, for example.
+example. IN DNSKEY 256 3 5 BwEAAAAAAAGfDKVFak/2o446xOsi39QnfZmRidaRyg3LaCxDBM6kVqCH QKI3a2lEf4FWVSbp+dYjGavsqWJ/Z7poMRy9JJol2bMLhtsZhESK5EYR aR/2dLw5H10SR+wb/qRVVYovWlk67sql7XYc3x5cjc4XaMVziBBrQMiW qkQS2oGQLwKCLw==
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.private b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.private
new file mode 100644
index 0000000..35acd10
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+005+51829.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.3
+Algorithm: 5 (RSASHA1)
+Modulus: nwylRWpP9qOOOsTrIt/UJ32ZkYnWkcoNy2gsQwTOpFagh0CiN2tpRH+BVlUm6fnWIxmr7Klif2e6aDEcvSSaJdmzC4bbGYREiuRGEWkf9nS8OR9dEkfsG/6kVVWKL1pZOu7Kpe12HN8eXI3OF2jFc4gQa0DIlqpEEtqBkC8Cgi8=
+PublicExponent: AQAAAAAAAQ==
+PrivateExponent: Aidz1Ah0WnUxdjZQ5J2bkXXOvP7ZhxtrmNvaQkQpEOjc5EW0mh+8f6rmp19CZHVwjk1nRfTgSnPk/y+xsyfroBRf5RH+6bjvB3mk+uSor6+xibdTy+HlEyd5YPdGzHmqFUe7pcL25kO0QSqdEVjvBP9SCgscDBhrTHURYsPxudE=
+Prime1: 0nuP62sq8a1OyjGqmsqhf6XrpwRXSKYVjdJEdRzogi/fnU/AWDZdc2W8JOC1nxdbfVC68b8G+Vc+5GOsuUw56Q==
+Prime2: wXG1f8INIsNLGtEhAuqw320onFrqBEgs+EkEZeUxHP5hUkchoUSnqTZrfRUA+UuOD2sI0NtA3OYCXaihgWu0Vw==
+Exponent1: QooxjUxTEcn9N5ehnpK0VD3gKwoW3C2NIv/2GeKVpL+ZcsD6iMzmHou/WVOAt0oz+RdWDLxpEzakwUhslPN6+Q==
+Exponent2: PP9JlJFaGEs3ckmvj53NXKz0fkbjtIOJvWwnkT7WrVpTgaUISjuSxLOfUDrrFC9JGAIAmoWDrI76QrTanbLiyw==
+Coefficient: u4jEvCVMxzmDBCjw8MLuTZtuBqs0ScAT7NkceBrjhdpCV1DtzVGJgbwI2GEHqEcSlcVAQCM92vPz76lL4Q94zw==
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..06bc89a
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/dsset-example.in
@@ -0,0 +1,2 @@
+example. IN DS 5896 5 1 07766192DA7BDE32F6DC719B9F5A3476686F8758
+example. IN DS 5896 5 2 CFBFD9C06EA15B0A984566573A18ACEC234FDC9C09103C0C53E75989 088A8FB4
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..1d0d4b5
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/example.db.bad
@@ -0,0 +1,110 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+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 5 1 300 (
+ 20361231235959 20000101000000 51829 example.
+ HW8O/KHJEObWSYtQD14+3MRtD6rasy/AeIAo
+ 1HmtELxeUoMvVcQzm7z1RoeV6S7+r/SrUjAz
+ PwtlE4TpyTEj9sfTr4mJhU0DwrNW6dN6qHCw
+ vB3nuURVOKzU8V26PdFcjJB+/HnJT2LyLUqr
+ KAzHwU1tAXkgx0FOwfyOs2rxooo= )
+ 300 NS ns2.example.
+ 300 RRSIG NS 5 1 300 (
+ 20361231235959 20000101000000 51829 example.
+ EO8/KzfhppvhD2b0hGCdEN8/WTNexK6zkC1Z
+ oW3vu0cFVvac+wrV9Vox90lHI0jTce/R+bvT
+ T9RbpZiZcBKLVyBuHIdFPOdc3ogHMPwaPNkD
+ pvVvLfV6auHCvINiVw+jWinBpTjqoROH/yTC
+ 03BQ41vewKsz3fYZ03XUr2xga5Q= )
+ 3600 NSEC a.example. NS SOA RRSIG NSEC DNSKEY
+ 3600 RRSIG NSEC 5 1 3600 (
+ 20361231235959 20000101000000 51829 example.
+ FiUyrwO7MV9Lhg6yu0XN/hLZPOiDg/NqIIUc
+ HfA9Yix90Z9G/yzn8NBC92Yp5EPiI4HiE24T
+ t1p4YwHe6n/IJA4KZUIpCxEY5xhQL/mVMeuj
+ dlFA2LaiDwbOh//42zdocaeGPrcV+u6OmXoU
+ xkQIuWeJ1QCaD5FXJdN6zELZsnw= )
+ 300 DNSKEY 256 3 5 (
+ BwEAAAAAAAGfDKVFak/2o446xOsi39QnfZmR
+ idaRyg3LaCxDBM6kVqCHQKI3a2lEf4FWVSbp
+ +dYjGavsqWJ/Z7poMRy9JJol2bMLhtsZhESK
+ 5EYRaR/2dLw5H10SR+wb/qRVVYovWlk67sql
+ 7XYc3x5cjc4XaMVziBBrQMiWqkQS2oGQLwKC
+ Lw==
+ ) ; ZSK; alg = RSASHA1; key id = 51829
+ 300 DNSKEY 257 3 5 (
+ AwEAAaLNbgMfH/XUwZC9DBVG4OpYVUVyCyZE
+ Bqhk3k6WziIAY+2f7MN3L9CoZR9GqfqM+/c6
+ g8gfkIaZZ2YP/YUUaN73xH/nxtHYkrP5Rqe/
+ dw7qONnsVwvf3HJ8HvURG3wjaOrPoe207+Hp
+ NTNhe/sT2usKhokSU8yKB0DKlnrKQvp9vScs
+ IB/RsIxOXWmYgOMkSXtpI3lQ07l1i2Tv6Une
+ cD9s8rukfl/gPbRBketLYACrqpb2j/1f7ciQ
+ v+rz1GnN9ma8XK1Yw8173/hrVL1S/ZqTGczw
+ deA3AVyiHThOZ15EPhSuL7jaJusHOi43Aa8Z
+ fCMCeimT73F5epktGomAxFU=
+ ) ; KSK; alg = RSASHA1; key id = 5896
+ 300 RRSIG DNSKEY 5 1 300 (
+ 20361231235959 20000101000000 5896 example.
+ b07impYEH+uW8iPCVE0QXqYSs6Yyu7Nb8q1f
+ rXv+NgE5wbsIvdo4PDdSfScP41WgVKdLPipH
+ gaTyk4CKAuGSvIBMzlc3yib03zdvzBDgn3Yi
+ lONpl2yH47vhvn5iXYcVV4kbuYE9+SFVoVO8
+ m6xvihm1D17m8emivnG6DuJSpJJM09v0toSd
+ 3yGI3bgUtki85ehOPU0ZkvA20InVgP5kKUgw
+ /M4vP4VkcwenNO7koMZOorI02KFOH3vvZSI4
+ hzuwJVaQZ35IBBVmSSMAD+0LTBk6sMPSpcmP
+ Pff75NLhU+4+UflWie6mzWIvm3ovcG3fveq0
+ W4G3TCriTIKSjY3Jqg== )
+ 300 RRSIG DNSKEY 5 1 300 (
+ 20361231235959 20000101000000 51829 example.
+ a7WU2WcHEpDfM5NBUzN7t4WXEwldn1EM/HkH
+ XEo9NnZhFV16414qbuwWMlUsc5MTii+T4OFZ
+ p2+XHj9M8glM1d98o+EDSYT7LdrrE7AqdtSO
+ gcXdeY6WRI9R5wkLP3cP6kADp5WIOcQ78IPb
+ pRJ4jhxqMPFV3cqCWH/Lp8JPghY= )
+a.example. 300 IN A 10.0.0.1
+ 300 RRSIG A 5 2 300 (
+ 20361231235959 20000101000000 51829 example.
+ h4WyY0hUkZobUbt2xWC4lJLEbGvzxGczH/mN
+ WHZBpgg+1tuoTAdVbt6a2TfQcJV/iPQGAHte
+ Vu/U6tD8KzP08krlqrcefwvR5LDAQygWRdjt
+ Rx105w9F0GiL6kpDH6S9T8xCw3aF5Rl1lu/u
+ 8eiUzDIMIBTijhXmM96Nde18RdA= )
+ 3600 NSEC ns2.example. A RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 (
+ 20361231235959 20000101000000 51829 example.
+ LbzeWbk9r119I95TVCebEPfnCCk9zBRq4nAR
+ swliQVQ84bCjwVJfakvlD4mgilSPtypxpyXC
+ DQaiOQWOz9LFzro5u71VuSS5fY7U4elp/lq6
+ 5BJB6o/dmk5xASAHHbOO6e5dcoQ5vRxcnJaE
+ 0vE1jGppo2FiQzkVi7Zbrghoolg= )
+ns2.example. 300 IN A 10.53.0.2
+ 300 RRSIG A 5 2 300 (
+ 20361231235959 20000101000000 51829 example.
+ Jfp3xzrym5GksbZ+a2rjOXzV/Ct+eX2DCo8a
+ lSbriEhuK9OR3WUnXoDqp1X/d7adNL2lI9c+
+ B3UVL+EOCyvNxt9kECcN8KgQdXKExZEQUwnN
+ UB51QESM9pW6akavhXJu98sjnhtpdTwrtKbg
+ nMJkfYe5Mw3e/8RFY+wpEq/8cHw= )
+ 3600 NSEC example. A RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 (
+ 20361231235959 20000101000000 51829 example.
+ Wxkz4nY5rty6O90QhFZguyqbaz9njnJKUs7m
+ qYF9u7dDk8vUf3yS97fw3e0N13X5zGZa7hTr
+ +65U4NKEOqYDBbvWaXSVFxrzVfSVXqY6l4jX
+ kWjA6q4q5TTgcjOUJ0MfvcjtgxcaKUiPGmPJ
+ RWdOV7t9YMWnf7QAbPI55QN9sfY= )
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..3a958b5
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2e8eb7a
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ 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..da479b2
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/sign.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.
+infile=example.db.in
+outfile=example.db.bad
+
+for i in Xexample.+005+51829.key Xexample.+005+51829.private \
+ Xexample.+005+05896.key Xexample.+005+05896.private
+do
+ cp $i `echo $i | sed s/X/K/`
+done
+
+$SIGNER -r $RANDFILE -g -s 20000101000000 -e 20361231235959 -o $zone \
+ $infile Kexample.+005+51829 Kexample.+005+51829 \
+ > /dev/null 2> signer.err
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..99d2a0d
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns3/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-enable 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/prereq.sh b/bin/tests/system/rsabigexponent/prereq.sh
new file mode 100644
index 0000000..e27f193
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/prereq.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+if $BIGKEY > /dev/null 2>&1
+then
+ rm -f Kexample.*
+else
+ echo_i "This test requires cryptography" >&2
+ echo_i "configure with --with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
+ exit 255
+fi
diff --git a/bin/tests/system/rsabigexponent/setup.sh b/bin/tests/system/rsabigexponent/setup.sh
new file mode 100644
index 0000000..ad46921
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..b530528
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/tests.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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=`expr $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=`expr $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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/run.sh b/bin/tests/system/run.sh
new file mode 100644
index 0000000..0e7632f
--- /dev/null
+++ b/bin/tests/system/run.sh
@@ -0,0 +1,207 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run a system test.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+stopservers=true
+baseport=5300
+
+if [ ${SYSTEMTEST_NO_CLEAN:-0} -eq 1 ]; then
+ clean=false
+else
+ clean=true
+fi
+
+while getopts "knp:r-:" flag; do
+ case "$flag" in
+ -) case "${OPTARG}" in
+ keep) stopservers=false ;;
+ noclean) clean=false ;;
+ esac
+ ;;
+ k) stopservers=false ;;
+ n) clean=false ;;
+ p) baseport=$OPTARG ;;
+ r) runall="-r" ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+if [ $# -eq 0 ]; then
+ echofail "Usage: $0 [-k] [-n] [-p <PORT>] [-r] test-directory [test-options]" >&2;
+ exit 1
+fi
+
+systest=$1
+shift
+
+if [ ! -d $systest ]; then
+ echofail "$0: $systest: no such test" >&2
+ exit 1
+fi
+
+# Define the number of ports allocated for each test, and the lowest and
+# highest valid values for the "-p" option.
+#
+# The lowest valid value is one more than the highest privileged port number
+# (1024).
+#
+# The highest valid value is calculated by noting that the value passed on the
+# command line is the lowest port number in a block of "numports" consecutive
+# ports and that the highest valid port number is 65,535.
+numport=100
+minvalid=`expr 1024 + 1`
+maxvalid=`expr 65535 - $numport + 1`
+
+test "$baseport" -eq "$baseport" > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echofail "$0: $systest: must specify a numeric value for the port" >&2
+ exit 1
+elif [ $baseport -lt $minvalid -o $baseport -gt $maxvalid ]; then
+ echofail "$0: $systest: the specified port must be in the range $minvalid to $maxvalid" >&2
+ exit 1
+fi
+
+# Name the first 10 ports in the set (it is assumed that each test has access
+# to ten or more ports): the query port, the control port and eight extra
+# ports. Since the lowest numbered port (specified in the command line)
+# will usually be a multiple of 10, the names are chosen so that if this is
+# true, the last digit of EXTRAPORTn is "n".
+PORT=$baseport
+EXTRAPORT1=`expr $baseport + 1`
+EXTRAPORT2=`expr $baseport + 2`
+EXTRAPORT3=`expr $baseport + 3`
+EXTRAPORT4=`expr $baseport + 4`
+EXTRAPORT5=`expr $baseport + 5`
+EXTRAPORT6=`expr $baseport + 6`
+EXTRAPORT7=`expr $baseport + 7`
+EXTRAPORT8=`expr $baseport + 8`
+CONTROLPORT=`expr $baseport + 9`
+
+LOWPORT=$baseport
+HIGHPORT=`expr $baseport + $numport - 1`
+
+export PORT
+export EXTRAPORT1
+export EXTRAPORT2
+export EXTRAPORT3
+export EXTRAPORT4
+export EXTRAPORT5
+export EXTRAPORT6
+export EXTRAPORT7
+export EXTRAPORT8
+export CONTROLPORT
+
+export LOWPORT
+export HIGHPORT
+
+echostart "S:$systest:`date`"
+echoinfo "T:$systest:1:A"
+echoinfo "A:$systest:System test $systest"
+echoinfo "I:$systest:PORTRANGE:${LOWPORT} - ${HIGHPORT}"
+
+if [ x${PERL:+set} = x ]
+then
+ echowarn "I:$systest:Perl not available. Skipping test."
+ echowarn "R:$systest:UNTESTED"
+ echoend "E:$systest:`date $dateargs`"
+ exit 0;
+fi
+
+$PERL testsock.pl -p $PORT || {
+ echowarn "I:$systest:Network interface aliases not set up. Skipping test."
+ echowarn "R:$systest:UNTESTED"
+ echoend "E:$systest:`date $dateargs`"
+ exit 0;
+}
+
+# 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."
+ [ $result -eq 255 ] && echowarn "R:$systest:SKIPPED" || echowarn "R:$systest:UNTESTED"
+ echoend "E:$systest:`date $dateargs`"
+ exit 0
+fi
+
+# Check for PKCS#11 support
+if
+ test ! -f $systest/usepkcs11 || $SHELL cleanpkcs11.sh
+then
+ : pkcs11 ok
+else
+ echowarn "I:$systest:Need PKCS#11, skipping test."
+ echowarn "R:$systest:PKCS11ONLY"
+ echoend "E:$systest:`date $dateargs`"
+ exit 0
+fi
+
+# Set up any dynamically generated test data
+if test -f $systest/setup.sh
+then
+ ( cd $systest && $SHELL setup.sh "$@" )
+fi
+
+# Start name servers running
+$PERL start.pl --port $PORT $systest
+if [ $? -ne 0 ]; then
+ echofail "R:$systest:FAIL"
+ echoend "E:$systest:`date $dateargs`"
+ exit 1
+fi
+
+# Run the tests
+( cd $systest ; $SHELL tests.sh "$@" )
+status=$?
+
+if $stopservers
+then
+ :
+else
+ exit $status
+fi
+
+# Shutdown
+$PERL stop.pl $systest
+
+status=`expr $status + $?`
+
+if [ $status != 0 ]; then
+ echofail "R:$systest:FAIL"
+ # Do not clean up - we need the evidence.
+ find . -name core -exec chmod 0644 '{}' \;
+else
+ echopass "R:$systest:PASS"
+ if $clean
+ then
+ $SHELL clean.sh $runall $systest "$@"
+ if test -d ../../../.git
+ then
+ git status -su --ignored $systest 2>/dev/null | \
+ sed -n -e 's|^?? \(.*\)|I:file \1 not removed|p' \
+ -e 's|^!! \(.*/named.run\)$|I:file \1 not removed|p' \
+ -e 's|^!! \(.*/named.memstats\)$|I:file \1 not removed|p'
+ fi
+ fi
+fi
+
+echoend "E:$systest:`date $dateargs`"
+
+exit $status
diff --git a/bin/tests/system/runall.sh b/bin/tests/system/runall.sh
new file mode 100644
index 0000000..76f20a4
--- /dev/null
+++ b/bin/tests/system/runall.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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.
+# (This is ignored when running on Windows as the tests are always
+# run sequentially on that platform.)
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/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 ;;
+ esac
+done
+export NOCLEAN
+shift `expr $OPTIND - 1`
+
+# Obtain number of processes to use.
+
+if [ $# -eq 0 ]; then
+ numproc=1
+elif [ $# -eq 1 ]; then
+ test "$1" -eq "$1" > /dev/null 2>&1
+ if [ $? -ne 0 ]; 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 [ "$CYGWIN" = "" ]; then
+ # Running on Unix, use "make" to run tests in parallel.
+ make -j $numproc check
+ status=$?
+else
+ # Running on Windows: no "make" available, so ensure test interfaces are up
+ # and then run the tests sequentially. (This is simpler than working out
+ # where "nmake" is likely to be found. Besides, "nmake" does not support
+ # parallel execution so if "nmake" is used, the tests would be run
+ # sequentially anyway.)
+ $PERL testsock.pl || {
+ cat <<-EOF
+ I:NOTE: System tests were skipped because they require that the
+ I: IP addresses 10.53.0.1 through 10.53.0.8 be configured
+ I: as alias addresses on the loopback interface. Please run
+ I: "bin/tests/system/ifconfig.sh up" as root to configure them.
+ EOF
+ exit 1
+ }
+ {
+ for testdir in $SUBDIRS; do
+ $SHELL run.sh $testdir || status=1
+ done
+ } 2>&1 | tee "systests.output"
+fi
+exit $status
diff --git a/bin/tests/system/runsequential.sh b/bin/tests/system/runsequential.sh
new file mode 100644
index 0000000..5e352e9
--- /dev/null
+++ b/bin/tests/system/runsequential.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+for d in $SEQUENTIALDIRS
+do
+ $SHELL run.sh "${@}" $d 2>&1 | tee $d/test.output
+done
diff --git a/bin/tests/system/runtime/README b/bin/tests/system/runtime/README
new file mode 100644
index 0000000..11429a2
--- /dev/null
+++ b/bin/tests/system/runtime/README
@@ -0,0 +1,6 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..e98d0f3
--- /dev/null
+++ b/bin/tests/system/runtime/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns2/named.conf ns2/named-alt*.conf
+rm -f */named.memstats
+rm -f */named*.run
+rm -f ns*/named.lock ns*/named*.pid ns*/other.lock
+rm -f *.pid
+rm -f rndc.out*
+[ -d ns2/nope ] && chmod 755 ns2/nope
+rm -rf ns2/nope
+rm -f ns2/dir ns2/nopedir ns2/mkd ns2/nopemkd
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..87ff94c
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt1.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named2.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-enable no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
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..9191e42
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt2.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named3.pid";
+ listen-on { 10.53.0.2; 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-enable no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
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..ce3eab4
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt3.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named4.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-enable no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
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..a0b79c3
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt4.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ include "dir";
+ include "nopemkd";
+ port @PORT@;
+ pid-file "../named4.pid";
+ listen-on { 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation auto;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
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..82e95b1
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt5.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ include "nopedir";
+ port @PORT@;
+ pid-file "../named5.pid";
+ listen-on { 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation auto;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
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..548f3c2
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt6.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ include "../nopedir";
+ include "../mkd";
+ port @PORT@;
+ pid-file "../named6.pid";
+ listen-on { 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation auto;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
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..7eb7f6c
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named1.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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..04cb026
--- /dev/null
+++ b/bin/tests/system/runtime/setup.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports 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
+
+mkdir ns2/nope
+
+if [ 1 = "${CYGWIN:-0}" ]
+then
+ setfacl -s user::r-x,group::r-x,other::r-x ns2/nope
+else
+ chmod 555 ns2/nope
+fi
+
+echo "directory \"`pwd`/ns2\";" > ns2/dir
+echo "directory \"`pwd`/ns2/nope\";" > ns2/nopedir
+echo "managed-keys-directory \"`pwd`/ns2\";" > ns2/mkd
+echo "managed-keys-directory \"`pwd`/ns2/nope\";" > ns2/nopemkd
diff --git a/bin/tests/system/runtime/tests.sh b/bin/tests/system/runtime/tests.sh
new file mode 100644
index 0000000..abb603c
--- /dev/null
+++ b/bin/tests/system/runtime/tests.sh
@@ -0,0 +1,153 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+n=`expr $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 != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ ! "$CYGWIN" ]; then
+ n=`expr $n + 1`
+ echo_i "verifying that named checks for conflicting listeners ($n)"
+ ret=0
+ (cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X other.lock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
+ for i in 1 2 3 4 5 6 7 8 9
+ do
+ grep "unable to listen on any configured interface" ns2/named2.run > /dev/null && break
+ sleep 1
+ done
+ grep "unable to listen on any configured interface" ns2/named2.run > /dev/null || ret=1
+ for i in 1 2 3 4 5 6 7 8 9
+ do
+ grep "exiting (due to fatal error)" ns2/named2.run > /dev/null && break
+ sleep 1
+ done
+ pid=`cat ns2/named2.pid 2>/dev/null`
+ test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+fi
+
+n=`expr $n + 1`
+echo_i "verifying that named checks for conflicting named processes ($n)"
+ret=0
+(cd ns2; $NAMED -c named-alt2.conf -D ns2-extra-2 -X named.lock -m record,size,mctx -d 99 -g -U 4 >> named3.run 2>&1 & )
+sleep 2
+grep "another named process" ns2/named3.run > /dev/null || ret=1
+pid=`cat ns2/named3.pid 2>/dev/null`
+test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "verifying that 'lock-file none' disables process check ($n)"
+ret=0
+(cd ns2; $NAMED -c named-alt3.conf -D ns2-extra-3 -m record,size,mctx -d 99 -g -U 4 >> named4.run 2>&1 & )
+sleep 2
+grep "another named process" ns2/named4.run > /dev/null && ret=1
+pid=`cat ns2/named4.pid 2>/dev/null`
+test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if $SHELL ../testcrypto.sh -q
+then
+ n=`expr $n + 1`
+ echo_i "checking that named refuses to reconfigure if managed-keys-directory is set and 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
+ grep "failed:" rndc.out.$n > /dev/null 2>&1 || ret=1
+ sleep 1
+ grep "managed-keys-directory '.*' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking that named refuses to reconfigure if managed-keys-directory is unset and working 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
+ grep "failed:" rndc.out.$n > /dev/null 2>&1 || ret=1
+ sleep 1
+ grep "working directory '.*' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ n=`expr $n + 1`
+ echo_i "checking that named reconfigures if working directory is not writable but managed-keys-directory is ($n)"
+ ret=0
+ copy_setports ns2/named-alt6.conf.in ns2/named.conf
+ $RNDCCMD 10.53.0.2 reconfig > rndc.out.$n 2>&1
+ grep "failed:" rndc.out.$n > /dev/null 2>&1 && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+
+ echo_i "shutting down existing named"
+ pid=`cat named4.pid 2>/dev/null`
+ test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+ pid=`cat named5.pid 2>/dev/null`
+ test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+ pid=`cat named6.pid 2>/dev/null`
+ test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+fi
+
+n=`expr $n + 1`
+echo_i "checking that named refuses to start if managed-keys-directory is set and not writable ($n)"
+ret=0
+cd ns2
+$NAMED -c named-alt4.conf -d 99 -g > named4.run 2>&1 &
+sleep 2
+grep "exiting (due to fatal error)" named4.run > /dev/null || ret=1
+pid=`cat named4.pid 2>/dev/null`
+test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+cd ..
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named refuses to start if managed-keys-directory is unset and working directory is not writable ($n)"
+ret=0
+cd ns2
+$NAMED -c named-alt5.conf -d 99 -g > named5.run 2>&1 &
+sleep 2
+grep "exiting (due to fatal error)" named5.run > /dev/null || ret=1
+pid=`cat named5.pid 2>/dev/null`
+test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+cd ..
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that named starts if managed-keys-directory is writable and working directory is not writable ($n)"
+ret=0
+cd ns2
+$NAMED -c named-alt6.conf -d 99 -g > named6.run 2>&1 &
+sleep 2
+grep "exiting (due to fatal error)" named6.run > /dev/null || ret=1
+pid=`cat named6.pid 2>/dev/null`
+test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
+cd ..
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/send.pl b/bin/tests/system/send.pl
new file mode 100644
index 0000000..01368b1
--- /dev/null
+++ b/bin/tests/system/send.pl
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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/setup.sh b/bin/tests/system/setup.sh
new file mode 100644
index 0000000..ff8c1bd
--- /dev/null
+++ b/bin/tests/system/setup.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run a system test.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/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..14c3b91
--- /dev/null
+++ b/bin/tests/system/sfcache/README
@@ -0,0 +1,12 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+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..f24d016
--- /dev/null
+++ b/bin/tests/system/sfcache/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K*.key */K*.private */*.signed */*.db */dsset-*
+rm -f */managed.conf */trusted.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f dig.*
+rm -f sfcache.*
+rm -f ns*/named.lock
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..a43c02b
--- /dev/null
+++ b/bin/tests/system/sfcache/ns1/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ 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..dab5cea
--- /dev/null
+++ b/bin/tests/system/sfcache/ns1/root.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/sfcache/ns1/sign.sh b/bin/tests/system/sfcache/ns1/sign.sh
new file mode 100644
index 0000000..769978b
--- /dev/null
+++ b/bin/tests/system/sfcache/ns1/sign.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh )
+
+cp ../ns2/dsset-example$TP .
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key > $zonefile
+
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $keyname > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+
+# ...or with a managed key.
+keyfile_to_managed_keys $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..594a549
--- /dev/null
+++ b/bin/tests/system/sfcache/ns2/example.db.in
@@ -0,0 +1,101 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..693ee05
--- /dev/null
+++ b/bin/tests/system/sfcache/ns2/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ 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..73e55e7
--- /dev/null
+++ b/bin/tests/system/sfcache/ns2/sign.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -g -r $RANDFILE -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..31c497c
--- /dev/null
+++ b/bin/tests/system/sfcache/ns5/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ servfail-ttl 30;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/sfcache/ns5/trusted.conf.bad b/bin/tests/system/sfcache/ns5/trusted.conf.bad
new file mode 100644
index 0000000..ed30460
--- /dev/null
+++ b/bin/tests/system/sfcache/ns5/trusted.conf.bad
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trusted-keys {
+ "." 256 3 1 "AQO6Cl+slAf+iuieDim9L3kujFHQD7s/IOj03ClMOpKYcTXtK4mRpuULVfvWxDi9Ew/gj0xLnnX7z9OJHIxLI+DSrAHd8Dm0XfBEAtVtJSn70GaPZgnLMw1rk5ap2DsEoWk=";
+};
diff --git a/bin/tests/system/sfcache/prereq.sh b/bin/tests/system/sfcache/prereq.sh
new file mode 100644
index 0000000..338197b
--- /dev/null
+++ b/bin/tests/system/sfcache/prereq.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r $RANDFILE foo > /dev/null 2>&1
+then
+ rm -f Kfoo*
+else
+ echo "I:This test requires that --with-openssl was used." >&2
+ exit 255
+fi
diff --git a/bin/tests/system/sfcache/setup.sh b/bin/tests/system/sfcache/setup.sh
new file mode 100644
index 0000000..7e6d604
--- /dev/null
+++ b/bin/tests/system/sfcache/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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 ../ns5 && cp -f trusted.conf.bad trusted.conf
+
diff --git a/bin/tests/system/sfcache/tests.sh b/bin/tests/system/sfcache/tests.sh
new file mode 100644
index 0000000..6e45830
--- /dev/null
+++ b/bin/tests/system/sfcache/tests.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+echo_i "checking DNSSEC SERVFAIL is cached ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec foo.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+$RNDCCMD 10.53.0.5 dumpdb -all 2>&1 | sed 's/^/I:ns5 /'
+for i in 1 2 3 4 5 6 7 8 9 10; do
+ awk '/Zone/{out=0} { if (out) print } /SERVFAIL/{out=1}' ns5/named_dump.db > sfcache.$n
+ [ -s "sfcache.$n" ] && break
+ sleep 1
+done
+grep "^; foo.example/A" sfcache.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking SERVFAIL is returned from cache ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking that +cd bypasses cache check ($n)"
+ret=0
+$DIG $DIGOPTS +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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "disabling server to force non-dnssec SERVFAIL"
+$RNDCCMD 10.53.0.2 stop 2>&1 | sed 's/^/I:ns2 /'
+
+awk '/SERVFAIL/ { next; out=1 } /Zone/ { out=0 } { if (out) print }' ns5/named_dump.db
+echo_i "checking SERVFAIL is cached ($n)"
+ret=0
+$DIG $DIGOPTS bar.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+$RNDCCMD 10.53.0.5 dumpdb -all 2>&1 | sed 's/^/I:ns5 /'
+for i in 1 2 3 4 5 6 7 8 9 10; do
+ awk '/Zone/{out=0} { if (out) print } /SERVFAIL/{out=1}' ns5/named_dump.db > sfcache.$n
+ [ -s "sfcache.$n" ] && break
+ sleep 1
+done
+grep "^; bar.example/A" sfcache.$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking SERVFAIL is returned from cache ($n)"
+ret=0
+$DIG $DIGOPTS bar.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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking with +cd query ($n)"
+ret=0
+$DIG $DIGOPTS +cd bar.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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking with +dnssec query ($n)"
+ret=0
+$DIG $DIGOPTS +cd bar.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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/smartsign/child.db b/bin/tests/system/smartsign/child.db
new file mode 100644
index 0000000..11af1a5
--- /dev/null
+++ b/bin/tests/system/smartsign/child.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..0f23bf9
--- /dev/null
+++ b/bin/tests/system/smartsign/clean.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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..6c6567f
--- /dev/null
+++ b/bin/tests/system/smartsign/parent.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/smartsign/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/smartsign/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/smartsign/setup.sh b/bin/tests/system/smartsign/setup.sh
new file mode 100644
index 0000000..ccdec61
--- /dev/null
+++ b/bin/tests/system/smartsign/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
diff --git a/bin/tests/system/smartsign/tests.sh b/bin/tests/system/smartsign/tests.sh
new file mode 100644
index 0000000..547f2bf
--- /dev/null
+++ b/bin/tests/system/smartsign/tests.sh
@@ -0,0 +1,342 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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 -r $RANDFILE -L 30 $czone`
+
+# not yet published or active
+czsk2=`$KEYGEN -q -r $RANDFILE -P none -A none $czone`
+
+# published but not active
+czsk3=`$KEYGEN -q -r $RANDFILE -A none $czone`
+
+# inactive
+czsk4=`$KEYGEN -q -r $RANDFILE -P now-24h -A now-24h -I now $czone`
+
+# active in 12 hours, inactive 12 hours after that...
+czsk5=`$KEYGEN -q -r $RANDFILE -P now+12h -A now+12h -I now+24h $czone`
+
+# explicit successor to czk5
+# (suppressing warning about lack of removal date)
+czsk6=`$KEYGEN -q -r $RANDFILE -S $czsk5 -i 6h 2>/dev/null`
+
+# active ksk
+cksk1=`$KEYGEN -q -r $RANDFILE -fk -L 30 $czone`
+
+# published but not YET active; will be active in 20 seconds
+cksk2=`$KEYGEN -q -r $RANDFILE -fk $czone`
+# $SETTIME moved after other $KEYGENs
+
+echo_i "revoking key"
+# revoking key changes its ID
+cksk3=`$KEYGEN -q -r $RANDFILE -fk $czone`
+cksk4=`$REVOKE $cksk3`
+
+echo_i "generating parent keys"
+pzsk=`$KEYGEN -q -r $RANDFILE $pzone`
+pksk=`$KEYGEN -q -r $RANDFILE -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 -r $RANDFILE -o $czone $cfile 2>&1`
+
+echo_i "signing parent zone"
+pzoneout=`$SIGNER -Sg -r $RANDFILE -o $pzone $pfile 2>&1`
+
+czactive=`echo $czsk1 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+czgenerated=`echo $czsk2 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+czpublished=`echo $czsk3 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+czinactive=`echo $czsk4 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+czpredecessor=`echo $czsk5 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+czsuccessor=`echo $czsk6 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+ckactive=`echo $cksk1 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+ckpublished=`echo $cksk2 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+ckprerevoke=`echo $cksk3 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+ckrevoked=`echo $cksk4 | sed 's/.*+005+0*\([0-9]*\)$/\1/'`
+
+pzid=`echo $pzsk | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+pkid=`echo $pksk | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
+
+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=`expr $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 -r $RANDFILE -o $pzone -f ${pfile}2.signed $pfile 2>&1`
+czoneout=`$SIGNER -Sxg -e now+1d -X now+2d -r $RANDFILE -o $czone -f ${cfile}2.signed $cfile 2>&1`
+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=`expr $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=`expr $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=`expr $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 unexpect 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=`expr $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=`expr $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=`expr $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 -r $RANDFILE -o $czone $cfile 2>&1`
+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=`expr $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" { 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=`expr $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=`expr $status + $ret`
+
+echo_i "waiting 30 seconds for key activation"
+sleep 30
+echo_i "re-signing child zone"
+czoneout2=`$SIGNER -Sg -r $RANDFILE -o $czone -f $cfile.new $cfile.signed 2>&1`
+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=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/sortlist/clean.sh b/bin/tests/system/sortlist/clean.sh
new file mode 100644
index 0000000..e910291
--- /dev/null
+++ b/bin/tests/system/sortlist/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f *.dig *.good *.out
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f ns*/named.lock
diff --git a/bin/tests/system/sortlist/ns1/example.db b/bin/tests/system/sortlist/ns1/example.db
new file mode 100644
index 0000000..94ebc73
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/example.db
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..9015681
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+
+ 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 master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ 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..dab5cea
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..7e60631
--- /dev/null
+++ b/bin/tests/system/sortlist/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..2fc44b0
--- /dev/null
+++ b/bin/tests/system/sortlist/tests.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+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 | \
+ egrep '10.53.0.(2|3)$' > test2.out &&
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.3 | sed 1q | \
+ egrep '10.53.0.(2|3)$' >> test2.out &&
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.4 | sed 1q | \
+ egrep '10.53.0.4$' >> test2.out &&
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.5 | sed 1q | \
+ egrep '10.53.0.5$' >> test2.out || status=1
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/spf/clean.sh b/bin/tests/system/spf/clean.sh
new file mode 100644
index 0000000..df9a329
--- /dev/null
+++ b/bin/tests/system/spf/clean.sh
@@ -0,0 +1,13 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/named.run
+rm -f ns1/named.memstats
+rm -f ns*/named.lock
+rm -f ns*/named.conf
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..255da60
--- /dev/null
+++ b/bin/tests/system/spf/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+zone "spf" {
+ type master;
+ file "spf.db";
+};
+
+zone "warn" {
+ type master;
+ file "spf.db";
+ check-spf warn;
+};
+
+zone "nowarn" {
+ type master;
+ 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..6c0e7e5
--- /dev/null
+++ b/bin/tests/system/spf/ns1/spf.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..7e60631
--- /dev/null
+++ b/bin/tests/system/spf/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..f46f643
--- /dev/null
+++ b/bin/tests/system/spf/tests.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+n=1
+status=0
+
+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=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/start.pl b/bin/tests/system/start.pl
new file mode 100755
index 0000000..3ef49a9
--- /dev/null
+++ b/bin/tests/system/start.pl
@@ -0,0 +1,345 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 Cwd;
+use Cwd 'abs_path';
+use Getopt::Long;
+
+# Usage:
+# perl start.pl [--noclean] [--restart] [--port port] 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.)
+#
+# 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>] test-directory [server-directory [server-options]]";
+my $noclean = '';
+my $restart = '';
+my $queryport = 5300;
+
+GetOptions('noclean' => \$noclean, 'restart' => \$restart, 'port=i' => \$queryport) or die "$usage\n";
+
+my $test = $ARGV[0];
+my $server = $ARGV[1];
+my $options = $ARGV[2];
+
+if (!$test) {
+ die "$usage\n";
+}
+if (!-d $test) {
+ die "No test directory: \"$test\"\n";
+}
+if ($server && !-d "$test/$server") {
+ die "No server directory: \"$test/$server\"\n";
+}
+
+# Global variables
+my $topdir = abs_path("$test/..");
+my $testdir = abs_path("$test");
+my $NAMED = $ENV{'NAMED'};
+my $LWRESD = $ENV{'LWRESD'};
+my $DIG = $ENV{'DIG'};
+my $PERL = $ENV{'PERL'};
+my $PYTHON = $ENV{'PYTHON'};
+
+# Start the server(s)
+
+if ($server) {
+ if ($server =~ /^ns/) {
+ &check_ports($server);
+ }
+ &start_server($server, $options);
+ if ($server =~ /^ns/) {
+ &verify_server($server);
+ }
+} else {
+ # Determine which servers need to be started for this test.
+ opendir DIR, $testdir;
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ my @ns = grep /^ns[0-9]*$/, @files;
+ my @lwresd = grep /^lwresd[0-9]*$/, @files;
+ my @ans = grep /^ans[0-9]*$/, @files;
+ my $name;
+
+ # Start the servers we found.
+ &check_ports();
+ foreach $name(@ns, @lwresd, @ans) {
+ &start_server($name);
+ &verify_server($name) if ($name =~ /^ns/);
+ }
+}
+
+# Subroutines
+
+sub check_ports {
+ my $server = shift;
+ my $options = "";
+ my $port = $queryport;
+ my $file = "";
+
+ $file = $testdir . "/" . $server . "/named.port" if ($server);
+
+ if ($server && $server =~ /(\d+)$/) {
+ $options = "-i $1";
+ }
+
+ if ($file ne "" && -e $file) {
+ open(FH, "<", $file);
+ while(my $line=<FH>) {
+ chomp $line;
+ $port = $line;
+ last;
+ }
+ close FH;
+ }
+
+ my $tries = 0;
+ while (1) {
+ my $return = system("$PERL $topdir/testsock.pl -p $port $options");
+ last if ($return == 0);
+ if (++$tries > 4) {
+ print "$0: could not bind to server addresses, still running?\n";
+ print "I:server sockets not available\n";
+ print "I:failed\n";
+ system("$PERL $topdir/stop.pl $testdir"); # Is this the correct behavior?
+ exit 1;
+ }
+ print "I:Couldn't bind to socket (yet)\n";
+ sleep 2;
+ }
+}
+
+sub start_server {
+ my $server = shift;
+ my $options = shift;
+
+ my $cleanup_files;
+ my $command;
+ my $pid_file;
+ my $cwd = getcwd();
+ my $args_file = $cwd . "/" . $test . "/" . $server . "/" . "named.args";
+
+ if ($server =~ /^ns/) {
+ $cleanup_files = "{*.jnl,*.bk,*.st,named.run}";
+ 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 -M external ";
+ } else {
+ $command = "$NAMED ";
+ }
+ if ($options) {
+ $command .= "$options";
+ } elsif (-e $args_file) {
+ open(FH, "<", $args_file);
+ while(my $line=<FH>)
+ {
+ #$line =~ s/\R//g;
+ chomp $line;
+ next if ($line =~ /^\s*$/); #discard blank lines
+ next if ($line =~ /^\s*#/); #discard comment lines
+ $line =~ s/#.*$//g;
+ $options = $line;
+ last;
+ }
+ close FH;
+ $command .= "$options";
+ } else {
+ $command .= "-D $test-$server ";
+ $command .= "-X named.lock ";
+ $command .= "-m record,size,mctx ";
+ $command .= "-T clienttest ";
+ $command .= "-T nosoa "
+ if (-e "$testdir/$server/named.nosoa");
+ $command .= "-T noaa "
+ if (-e "$testdir/$server/named.noaa");
+ $command .= "-T noedns "
+ if (-e "$testdir/$server/named.noedns");
+ $command .= "-T dropedns "
+ if (-e "$testdir/$server/named.dropedns");
+ $command .= "-T maxudp512 "
+ if (-e "$testdir/$server/named.maxudp512");
+ $command .= "-T maxudp1460 "
+ if (-e "$testdir/$server/named.maxudp1460");
+ $command .= "-c named.conf -d 99 -g -U 4";
+ }
+ $command .= " -T notcp"
+ if (-e "$testdir/$server/named.notcp");
+ if ($restart) {
+ $command .= " >>named.run 2>&1 &";
+ } else {
+ $command .= " >named.run 2>&1 &";
+ }
+ $pid_file = "named.pid";
+ } elsif ($server =~ /^lwresd/) {
+ $cleanup_files = "{lwresd.run}";
+ if ($ENV{'USE_VALGRIND'}) {
+ $command = "valgrind -q --gen-suppressions=all --num-callers=48 --fullpath-after= --log-file=lwresd-valgrind-%p.log ";
+ if ($ENV{'USE_VALGRIND'} eq 'helgrind') {
+ $command .= "--tool=helgrind ";
+ } else {
+ $command .= "--tool=memcheck --track-origins=yes --leak-check=full ";
+ }
+ $command .= "$LWRESD -m none -M external ";
+ } else {
+ $command = "$LWRESD ";
+ }
+ if ($options) {
+ $command .= "$options";
+ } else {
+ $command .= "-X lwresd.lock ";
+ $command .= "-m record,size,mctx ";
+ $command .= "-T clienttest ";
+ $command .= "-C resolv.conf -d 99 -g -U 4 ";
+ $command .= "-i lwresd.pid -P 9210 -p 5300";
+ }
+ if ($restart) {
+ $command .= " >>lwresd.run 2>&1 &";
+ } else {
+ $command .= " >lwresd.run 2>&1 &";
+ }
+ $pid_file = "lwresd.pid";
+ } elsif ($server =~ /^ans/) {
+ $cleanup_files = "{ans.run}";
+ if (-e "$testdir/$server/ans.py") {
+ $command = "$PYTHON -u ans.py 10.53.0.$' $queryport";
+ } elsif (-e "$testdir/$server/ans.pl") {
+ $command = "$PERL ans.pl";
+ } else {
+ $command = "$PERL $topdir/ans.pl 10.53.0.$'";
+ }
+ if ($options) {
+ $command .= "$options";
+ } else {
+ $command .= "";
+ }
+ if ($restart) {
+ $command .= " >>ans.run 2>&1 &";
+ } else {
+ $command .= " >ans.run 2>&1 &";
+ }
+ $pid_file = "ans.pid";
+ } else {
+ print "I:Unknown server type $server\n";
+ print "I:failed\n";
+ system "$PERL $topdir/stop.pl $testdir";
+ exit 1;
+ }
+
+ # print "I:starting server %s\n",$server;
+
+ chdir "$testdir/$server";
+
+ unless ($noclean) {
+ unlink glob $cleanup_files;
+ }
+
+ # get the shell to report the pid of the server ($!)
+ $command .= "echo \$!";
+
+ # start the server
+ my $child = `$command`;
+ $child =~ s/\s+$//g;
+
+ # wait up to 14 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 > 140) {
+ print "I:Couldn't start server $server (pid=$child)\n";
+ print "I:failed\n";
+ system "kill -9 $child" if ("$child" ne "");
+ system "$PERL $topdir/stop.pl $testdir";
+ exit 1;
+ }
+ # sleep for 0.1 seconds
+ select undef,undef,undef,0.1;
+ }
+
+ # go back to the top level directory
+ chdir $cwd;
+}
+
+sub verify_server {
+ my $server = shift;
+ my $n = $server;
+ my $port = $queryport;
+ my $tcp = "+tcp";
+
+ $n =~ s/^ns//;
+
+ if (-e "$testdir/$server/named.port") {
+ open(FH, "<", "$testdir/$server/named.port");
+ while(my $line=<FH>) {
+ chomp $line;
+ $port = $line;
+ last;
+ }
+ close FH;
+ }
+
+ $tcp = "" if (-e "$testdir/$server/named.notcp");
+
+ my $tries = 0;
+ while (1) {
+ my $return = system("$DIG $tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noedns -p $port version.bind. chaos txt \@10.53.0.$n > dig.out");
+ last if ($return == 0);
+ if (++$tries >= 30) {
+ print "I:no response from $server\n";
+ print "I:failed\n";
+ system("$PERL $topdir/stop.pl $testdir");
+ exit 1;
+ }
+ sleep 2;
+ }
+ unlink "dig.out";
+}
diff --git a/bin/tests/system/start.sh b/bin/tests/system/start.sh
new file mode 100644
index 0000000..78fb044
--- /dev/null
+++ b/bin/tests/system/start.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ./conf.sh
+$PERL start.pl "$@"
diff --git a/bin/tests/system/staticstub/clean.sh b/bin/tests/system/staticstub/clean.sh
new file mode 100755
index 0000000..52c25cd
--- /dev/null
+++ b/bin/tests/system/staticstub/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
diff --git a/bin/tests/system/staticstub/conf/bad01.conf b/bin/tests/system/staticstub/conf/bad01.conf
new file mode 100644
index 0000000..6f9bf55
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad01.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..dd23d73
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad02.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..e8e9231
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad03.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..54b5d28
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad04.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..7a3ba55
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad05.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..8c2ad58
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad06.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..c347102
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad07.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..83f1f27
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad08.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..349b252
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad09.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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.
+
+# "masters" isn't allowed for a static-stub zone (unlike a stub zone).
+zone "example.com" {
+ type static-stub;
+ masters { 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..f3ec708
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad10.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..afe78a9
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad11.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..8f3558e
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good01.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..1bbb5c1
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good02.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..af6fc8e
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good03.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..02009c5
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good04.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..59054ee
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good05.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 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..4f31755
--- /dev/null
+++ b/bin/tests/system/staticstub/ns1/named.conf.in
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+zone "." { type master; 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..c1b821d
--- /dev/null
+++ b/bin/tests/system/staticstub/ns1/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.utld hostmaster.ns.utld ( 46 3600 1200 604800 60 )
+@ NS ns.utld
+ns.utld 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..245c7c2
--- /dev/null
+++ b/bin/tests/system/staticstub/ns2/named.conf.in
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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;
+ 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..85fc1d8
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/example.db.in
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..becf883
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/example.org.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..b582196
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 no;
+};
+
+EXAMPLE_ZONE_PLACEHOLDER
+
+zone "example.org" {
+ type master;
+ file "example.org.db";
+};
+
+zone "undelegated" {
+ type master;
+ 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..32af7d0
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/sign.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+(cd ../ns4 && $SHELL -e sign.sh )
+
+cp ../ns4/dsset-sub.example$TP .
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -f KSK -n zone $zone`
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+# Configure the resolving server with a trusted key.
+keyfile_to_trusted_keys $keyname2 > trusted.conf
+
+zone=undelegated
+infile=undelegated.db.in
+zonefile=undelegated.db
+keyname1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -f KSK -n zone $zone`
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+keyfile_to_trusted_keys $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..c85337d
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/undelegated.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..feda956
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/example.com.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..42a0860
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/example.info.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..13b3a61
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/example.org.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..b3a82c9
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify no;
+};
+
+zone "example.com" {
+ type master;
+ file "example.com.db";
+};
+
+zone "example.org" {
+ type master;
+ file "example.org.db";
+};
+
+zone "sub.example" {
+ type master;
+ file "sub.example.db.signed";
+};
+
+zone "example.info" {
+ type master;
+ 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..26ca671
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/sign.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=sub.example
+infile=${zone}.db.in
+zonefile=${zone}.db
+
+keyname1=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+keyname2=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -f KSK -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
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..9d346eb
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/sub.example.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/staticstub/prereq.sh
new file mode 100755
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/staticstub/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/staticstub/setup.sh b/bin/tests/system/staticstub/setup.sh
new file mode 100755
index 0000000..5cd1a5f
--- /dev/null
+++ b/bin/tests/system/staticstub/setup.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+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 master; file "example.db.signed"; };/' tmp > ns3/named.conf
+
+rm -f tmp
+
+copy_setports ns4/named.conf.in ns4/named.conf
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..95cad16
--- /dev/null
+++ b/bin/tests/system/staticstub/tests.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+for conf in conf/good*.conf
+do
+ n=`expr $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=`expr $status + $ret`
+done
+
+for conf in conf/bad*.conf
+do
+ n=`expr $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=`expr $status + $ret`
+done
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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
+$RNDCCMD 10.53.0.3 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+# 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 master; file "example.db.signed"; };/' tmp > ns3/named.conf
+$RNDCCMD 10.53.0.3 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $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.
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+# 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=`expr $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=`expr $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=`expr $status + $ret`
+
+# check server-names
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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 ../testsock6.pl ::1 2> /dev/null
+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=`expr $status + $ret`
+else
+ echo_i "SKIPPED: checking IPv6 static-stub address ($n)"
+fi
+
+n=`expr $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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+# reload with a different name server: exisitng zone shouldn't be reused.
+n=`expr $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
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+$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=`expr $status + $ret`
+
+n=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/statistics/ans4/ans.pl b/bin/tests/system/statistics/ans4/ans.pl
new file mode 100644
index 0000000..f8feafc
--- /dev/null
+++ b/bin/tests/system/statistics/ans4/ans.pl
@@ -0,0 +1,116 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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..830c835
--- /dev/null
+++ b/bin/tests/system/statistics/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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 dig.out*
+rm -f curl.out.*
+rm -f ns*/named.lock
+rm -f stats*out
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..762b0fd
--- /dev/null
+++ b/bin/tests/system/statistics/ns1/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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-channels {
+ inet 10.53.0.1 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example.info." {
+ type master;
+ file "example-info.db";
+};
+
+zone "32/1.0.0.127-in-addr.example." {
+ type master;
+ 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..dab5cea
--- /dev/null
+++ b/bin/tests/system/statistics/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..868fffc
--- /dev/null
+++ b/bin/tests/system/statistics/ns1/zone.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..4a3f33f
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..38a6b0d
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/internal.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..c046fe9
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+statistics-channels {
+ inet 10.53.0.2 port @EXTRAPORT1@ allow { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/statistics/ns3/internal.db b/bin/tests/system/statistics/ns3/internal.db
new file mode 100644
index 0000000..cdf2648
--- /dev/null
+++ b/bin/tests/system/statistics/ns3/internal.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..fe07cea
--- /dev/null
+++ b/bin/tests/system/statistics/ns3/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+statistics-channels {
+ inet 10.53.0.3 port @EXTRAPORT1@ allow { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "example" {
+ type master;
+ allow-update { any; };
+ file "internal.db";
+};
diff --git a/bin/tests/system/statistics/ns3/root.hint b/bin/tests/system/statistics/ns3/root.hint
new file mode 100644
index 0000000..1acfd14
--- /dev/null
+++ b/bin/tests/system/statistics/ns3/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/prereq.sh b/bin/tests/system/statistics/prereq.sh
new file mode 100644
index 0000000..ec3fefe
--- /dev/null
+++ b/bin/tests/system/statistics/prereq.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION >= 0.76 && $Net::DNS::VERSION <= 0.77);' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS version 0.76 and 0.77 have a bug that causes this test to fail: please update." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/statistics/setup.sh b/bin/tests/system/statistics/setup.sh
new file mode 100644
index 0000000..c9f645b
--- /dev/null
+++ b/bin/tests/system/statistics/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/statistics/tests.sh b/bin/tests/system/statistics/tests.sh
new file mode 100644
index 0000000..c6e6785
--- /dev/null
+++ b/bin/tests/system/statistics/tests.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+DIGCMD="$DIG $DIGOPTS -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+status=0
+
+ret=0
+n=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=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "dumping initial stats for ns2 ($n)"
+$RNDCCMD -s 10.53.0.2 stats > /dev/null 2>&1
+[ -f ns2/named.stats ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "checking for 1 entry in adb hash table in named.stats ($n)"
+grep "1 Addresses in hash table" ns2/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "verifying cache statistics in named.stats ($n)"
+grep "Cache Statistics" ns2/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $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
+$RNDCCMD -s 10.53.0.2 stats > /dev/null 2>&1
+grep "2 Addresses in hash table" ns2/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "dumping initial stats for ns3 ($n)"
+rm -f ns3/named.stats
+$RNDCCMD -s 10.53.0.3 stats > /dev/null 2>&1
+[ -f ns3/named.stats ] || ret=1
+[ "$CYGWIN" ] || \
+nsock0nstat=`grep "UDP/IPv4 sockets active" ns3/named.stats | awk '{print $1}'`
+[ 0 -ne ${nsock0nstat:-0} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $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
+
+ret=0
+echo_i "dumping updated stats for ns3 ($n)"
+rm -f ns3/named.stats
+$RNDCCMD -s 10.53.0.3 stats > /dev/null 2>&1
+[ -f ns3/named.stats ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "verifying recursing clients output in named.stats ($n)"
+grep "2 recursing clients" ns3/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "verifying active fetches output in named.stats ($n)"
+grep "1 active fetches" ns3/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+if [ ! "$CYGWIN" ]; then
+ ret=0
+ echo_i "verifying active sockets output in named.stats ($n)"
+ nsock1nstat=`grep "UDP/IPv4 sockets active" ns3/named.stats | awk '{print $1}'`
+ [ `expr $nsock1nstat - $nsock0nstat` -eq 1 ] || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=`expr $status + $ret`
+ n=`expr $n + 1`
+fi
+
+# 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" ns3/named.stats > /dev/null || ret=1
+grep "TCP queries in progress" ns3/named.stats > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "verifying bucket size output ($n)"
+grep "bucket size" ns3/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $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=`expr $status + $ret`
+n=`expr $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.${t} 2>/dev/null || ret=1
+ grep '<zone name="32/1.0.0.127-in-addr.example" rdataclass="IN"><type>master</type>' curl.out.${t} > /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=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "checking priming queries are counted ($n)"
+grep "1 priming queries" ns3/named.stats
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/statschannel/clean.sh b/bin/tests/system/statschannel/clean.sh
new file mode 100644
index 0000000..477f209
--- /dev/null
+++ b/bin/tests/system/statschannel/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f traffic traffic.out.*
+rm -f dig.out*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/named.stats
+rm -f xml.*stats json.*stats
+rm -f compressed.headers regular.headers compressed.out regular.out
diff --git a/bin/tests/system/statschannel/fetch.pl b/bin/tests/system/statschannel/fetch.pl
new file mode 100644
index 0000000..e589c45
--- /dev/null
+++ b/bin/tests/system/statschannel/fetch.pl
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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{a} if defined $options{a};
+
+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/ns2/example.db b/bin/tests/system/statschannel/ns2/example.db
new file mode 100644
index 0000000..b65651a
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/example.db
@@ -0,0 +1,47 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/named.conf.in b/bin/tests/system/statschannel/ns2/named.conf.in
new file mode 100644
index 0000000..bababf6
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ 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 hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/statschannel/prereq.sh b/bin/tests/system/statschannel/prereq.sh
new file mode 100644
index 0000000..f3d4fd1
--- /dev/null
+++ b/bin/tests/system/statschannel/prereq.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+fail=0
+
+if $PERL -e 'use File::Fetch;' 2>/dev/null
+then
+ :
+else
+ echo_i "This test requires the File::Fetch library." >&2
+ fail=1
+fi
+
+exit $fail
diff --git a/bin/tests/system/statschannel/server-json.pl b/bin/tests/system/statschannel/server-json.pl
new file mode 100644
index 0000000..cb1f463
--- /dev/null
+++ b/bin/tests/system/statschannel/server-json.pl
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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..2003024
--- /dev/null
+++ b/bin/tests/system/statschannel/server-xml.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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..e7ad741
--- /dev/null
+++ b/bin/tests/system/statschannel/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/statschannel/tests.sh b/bin/tests/system/statschannel/tests.sh
new file mode 100644
index 0000000..780f857
--- /dev/null
+++ b/bin/tests/system/statschannel/tests.sh
@@ -0,0 +1,215 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGCMD="$DIG @10.53.0.2 -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+if [ ! "$HAVEJSONSTATS" ]
+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 [ ! "$HAVEXMLSTATS" ]
+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" -a ! "$PERL_XML" ]; then
+ echo_i "skipping all tests"
+ exit 0
+fi
+
+
+gettraffic() {
+ echo_i "... using $1"
+ case $1 in
+ xml) path='xml/v3/traffic' ;;
+ json) path='json/v1/traffic' ;;
+ *) return 1 ;;
+ esac
+ file=`$PERL fetch.pl -p ${EXTRAPORT1} $path`
+ $PERL traffic-${1}.pl $file 2>/dev/null | sort > traffic.out.$2
+ result=$?
+ rm -f $file
+ return $result
+}
+
+status=0
+n=1
+ret=0
+echo_i "fetching traffic size data ($n)"
+if [ $PERL_XML ]; then
+ gettraffic xml x$n || ret=1
+ cmp traffic.out.x$n traffic.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ gettraffic json j$n || ret=1
+ cmp traffic.out.j$n traffic.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "fetching traffic size data after small UDP query ($n)"
+$DIGCMD short.example txt > dig.out.$n || ret=1
+if [ $PERL_XML ]; then
+ gettraffic xml x$n || ret=1
+ cmp traffic.out.x$n traffic.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ gettraffic json j$n || ret=1
+ cmp traffic.out.j$n traffic.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+n=`expr $n + 1`
+echo_i "fetching traffic size data after large UDP query ($n)"
+$DIGCMD long.example txt > dig.out.$n || ret=1
+if [ $PERL_XML ]; then
+ gettraffic xml x$n || ret=1
+ cmp traffic.out.x$n traffic.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ gettraffic json j$n || ret=1
+ cmp traffic.out.j$n traffic.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "fetching traffic size data after small TCP query ($n)"
+$DIGCMD +tcp short.example txt > dig.out.$n || ret=1
+if [ $PERL_XML ]; then
+ gettraffic xml x$n || ret=1
+ cmp traffic.out.x$n traffic.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ gettraffic json j$n || ret=1
+ cmp traffic.out.j$n traffic.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "fetching traffic size data after large TCP query ($n)"
+$DIGCMD +tcp long.example txt > dig.out.$n || ret=1
+if [ $PERL_XML ]; then
+ gettraffic xml x$n || ret=1
+ cmp traffic.out.x$n traffic.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ gettraffic json j$n || ret=1
+ cmp traffic.out.j$n traffic.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "checking consistency between named.stats and xml/json ($n)"
+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=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "checking consistency between regular and compressed output ($n)"
+if [ "$HAVEXMLSTATS" ];
+then
+ URL=http://10.53.0.2:${EXTRAPORT1}/xml/v3/server
+else
+ URL=http://10.53.0.2:${EXTRAPORT1}/json/v1/server
+fi
+$CURL -D regular.headers $URL 2>/dev/null | \
+ sed -e "s#<current-time>.*</current-time>##g" > regular.out
+$CURL -D compressed.headers --compressed $URL 2>/dev/null | \
+ sed -e "s#<current-time>.*</current-time>##g" > compressed.out
+diff regular.out compressed.out >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+ret=0
+echo_i "checking if compressed output is really compressed ($n)"
+if [ "$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 [ ! `expr $REGSIZE / $COMPSIZE` -gt 2 ]; then
+ ret=1
+ fi
+else
+ echo_i "skipped"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/statschannel/traffic-json.pl b/bin/tests/system/statschannel/traffic-json.pl
new file mode 100644
index 0000000..67b53c4
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic-json.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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..a866c64
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic-xml.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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/stop.pl b/bin/tests/system/stop.pl
new file mode 100644
index 0000000..2593d4d
--- /dev/null
+++ b/bin/tests/system/stop.pl
@@ -0,0 +1,193 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 Cwd 'abs_path';
+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 $port = 9953;
+GetOptions('use-rndc' => \$use_rndc, 'halt' => \$halt, 'port=i' => \$port) or die "$usage\n";
+
+my $errors = 0;
+
+my $test = $ARGV[0];
+my $server = $ARGV[1];
+die "$usage\n" unless defined($test);
+die "No test directory: \"$test\"\n" unless (-d $test);
+die "No server directory: \"$server\"\n" if (defined($server) && !-d "$test/$server");
+
+# Global variables
+my $testdir = abs_path($test);
+my @servers;
+
+
+# Determine which servers need to be stopped.
+if (defined $server) {
+ @servers = ($server);
+} else {
+ local *DIR;
+ opendir DIR, $testdir or die "$testdir: $!\n";
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ my @ns = grep /^ns[0-9]*$/, @files;
+ my @lwresd = grep /^lwresd[0-9]*$/, @files;
+ my @ans = grep /^ans[0-9]*$/, @files;
+
+ push @servers, @ns, @lwresd, @ans;
+}
+
+
+# Stop the server(s), pass 1: rndc.
+if ($use_rndc) {
+ foreach my $server (grep /^ns/, @servers) {
+ stop_rndc($server);
+ }
+
+ wait_for_servers(30, grep /^ns/, @servers);
+}
+
+
+# Pass 2: SIGTERM
+foreach my $server (@servers) {
+ stop_signal($server, "TERM");
+}
+
+wait_for_servers(60, @servers);
+
+# Pass 3: SIGABRT
+foreach my $server (@servers) {
+ stop_signal($server, "ABRT");
+}
+
+exit($errors ? 1 : 0);
+
+# Subroutines
+
+# Return the full path to a given server's PID file.
+sub server_pid_file {
+ my($server) = @_;
+
+ my $pid_file;
+ if ($server =~ /^ns/) {
+ $pid_file = "named.pid";
+ } elsif ($server =~ /^lwresd/) {
+ $pid_file = "lwresd.pid";
+ } elsif ($server =~ /^ans/) {
+ $pid_file = "ans.pid";
+ } else {
+ print "I:Unknown server type $server\n";
+ exit 1;
+ }
+ $pid_file = "$testdir/$server/$pid_file";
+}
+
+# Read a PID.
+sub read_pid {
+ my($pid_file) = @_;
+
+ local *FH;
+ my $result = open FH, "< $pid_file";
+ if (!$result) {
+ print "I:$pid_file: $!\n";
+ unlink $pid_file;
+ return;
+ }
+
+ my $pid = <FH>;
+ chomp($pid);
+ return $pid;
+}
+
+# Stop a named process with rndc.
+sub stop_rndc {
+ my($server) = @_;
+
+ return unless ($server =~ /^ns(\d+)$/);
+ my $ip = "10.53.0.$1";
+ my $how = $halt ? "halt" : "stop";
+
+ # Ugly, but should work.
+ system("$ENV{RNDC} -c ../common/rndc.conf -s $ip -p $port $how | sed 's/^/I:$server /'");
+ return;
+}
+
+# Stop a server by sending a signal to it.
+sub stop_signal {
+ my($server, $sig) = @_;
+
+ my $pid_file = server_pid_file($server);
+ return unless -f $pid_file;
+
+ my $pid = read_pid($pid_file);
+ return unless defined($pid);
+
+ if ($sig eq 'ABRT') {
+ print "I:$server didn't die when sent a SIGTERM\n";
+ $errors++;
+ }
+
+ my $result;
+ if ($^O eq 'cygwin') {
+ $result = system("/bin/kill -f -$sig $pid");
+ unlink $pid_file;
+ if ($result != 0) {
+ print "I:$server died before a SIG$sig was sent\n";
+ $errors++;
+ }
+ } else {
+ $result = kill $sig, $pid;
+ if (!$result) {
+ print "I:$server died before a SIG$sig was sent\n";
+ unlink $pid_file;
+ $errors++;
+ }
+ }
+
+ return;
+}
+
+sub wait_for_servers {
+ my($timeout, @servers) = @_;
+
+ my @pid_files = grep { defined($_) }
+ map { server_pid_file($_) } @servers;
+
+ while ($timeout > 0 && @pid_files > 0) {
+ @pid_files = grep { -f $_ } @pid_files;
+ sleep 1 if (@pid_files > 0);
+ $timeout--;
+ }
+
+ return;
+}
diff --git a/bin/tests/system/stop.sh b/bin/tests/system/stop.sh
new file mode 100644
index 0000000..a2ae614
--- /dev/null
+++ b/bin/tests/system/stop.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ./conf.sh
+$PERL ./stop.pl "$@"
+
diff --git a/bin/tests/system/stopall.sh b/bin/tests/system/stopall.sh
new file mode 100644
index 0000000..d9b57e0
--- /dev/null
+++ b/bin/tests/system/stopall.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Stop all hanging processes from any system tests.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/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..3d13acd
--- /dev/null
+++ b/bin/tests/system/stress/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f reload.pid
+
+rm -f ns?/zones.conf
+rm -f ns?/zone*.bk
+
+rm -f ns1/delegations.db
+
+rm -f ns2/zone0*.db
+rm -f ns2/zone0*.jnl
+rm -f */named.memstats
+rm -f ns*/named.lock
diff --git a/bin/tests/system/stress/ns1/named.conf b/bin/tests/system/stress/ns1/named.conf
new file mode 100644
index 0000000..59690e7
--- /dev/null
+++ b/bin/tests/system/stress/ns1/named.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/stress/ns2/named.conf b/bin/tests/system/stress/ns2/named.conf
new file mode 100644
index 0000000..c0fb05f
--- /dev/null
+++ b/bin/tests/system/stress/ns2/named.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/stress/ns3/named.conf b/bin/tests/system/stress/ns3/named.conf
new file mode 100644
index 0000000..9b905a9
--- /dev/null
+++ b/bin/tests/system/stress/ns3/named.conf
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+server 10.53.0.4 {
+ provide-ixfr no;
+};
+server 10.53.0.2 {
+ request-ixfr no;
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/stress/ns4/named.conf b/bin/tests/system/stress/ns4/named.conf
new file mode 100644
index 0000000..405f618
--- /dev/null
+++ b/bin/tests/system/stress/ns4/named.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "zones.conf";
+
diff --git a/bin/tests/system/stress/prereq.sh b/bin/tests/system/stress/prereq.sh
new file mode 100644
index 0000000..de147a4
--- /dev/null
+++ b/bin/tests/system/stress/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/stress/setup.pl b/bin/tests/system/stress/setup.pl
new file mode 100644
index 0000000..40e3cea
--- /dev/null
+++ b/bin/tests/system/stress/setup.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up test data for zone transfer quota tests.
+#
+use FileHandle;
+
+my $n_zones = 5;
+my $n_names = 1000;
+
+make_zones(2, undef);
+make_zones(3, "10.53.0.2");
+make_zones(4, "10.53.0.3");
+
+my $rootdelegations =
+ new FileHandle("ns1/root.db", "w") or die;
+
+print $rootdelegations <<END;
+\$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
+END
+
+for ($z = 0; $z < $n_zones; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ foreach $ns (qw(2 3 4)) {
+ print $rootdelegations "$zn. NS ns$ns.$zn.\n";
+ print $rootdelegations "ns$ns.$zn. A 10.53.0.$ns\n";
+ }
+}
+close $rootdelegations;
+
+sub make_zones {
+ my ($nsno, $slaved_from) = @_;
+ my $namedconf = new FileHandle("ns$nsno/zones.conf", "w") or die;
+ for ($z = 0; $z < $n_zones; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ if (defined($slaved_from)) {
+ print $namedconf "zone \"$zn\" { type slave; " .
+ "file \"$zn.bk\"; masters { $slaved_from; }; };\n";
+ } else {
+ print $namedconf "zone \"$zn\" { " .
+ "type master; " .
+ "allow-update { any; }; " .
+ "file \"$zn.db\"; };\n";
+
+ my $fn = "ns$nsno/$zn.db";
+ my $f = new FileHandle($fn, "w") or die "open: $fn: $!";
+ print $f "\$TTL 300
+\@ IN SOA ns2.$zn. hostmaster 1 300 120 3600 86400
+@ NS ns2.$zn.
+ns2.$zn. A 10.53.0.2
+@ NS ns3.$zn.
+ns3.$zn. A 10.53.0.3
+@ NS ns4.$zn.
+ns4.$zn. A 10.53.0.4
+ MX 10 mail1.isp.example.
+ MX 20 mail2.isp.example.
+";
+ for ($i = 0; $i < $n_names; $i++) {
+ print $f sprintf("name%06d", $i) .
+ " A 10.0.0.1\n";
+ }
+ $f->close;
+ }
+ }
+}
diff --git a/bin/tests/system/stress/setup.sh b/bin/tests/system/stress/setup.sh
new file mode 100644
index 0000000..b1798a4
--- /dev/null
+++ b/bin/tests/system/stress/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up test data for zone transfer quota tests.
+#
+
+$PERL setup.pl
diff --git a/bin/tests/system/stress/tests.sh b/bin/tests/system/stress/tests.sh
new file mode 100644
index 0000000..53c3d20
--- /dev/null
+++ b/bin/tests/system/stress/tests.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+(
+$SHELL -c "while true
+ do $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reload 2>&1 |
+ sed 's/^/I:ns3 /';
+ sleep 1
+ done" & echo $! >reload.pid
+) &
+
+for i in 0 1 2 3 4
+do
+ $PERL update.pl -s 10.53.0.2 -p 5300 zone00000$i.example. &
+done
+
+echo "I:waiting for background processes to finish"
+wait
+
+echo "I:killing reload loop"
+kill `cat reload.pid`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/stress/update.pl b/bin/tests/system/stress/update.pl
new file mode 100644
index 0000000..6bb8afc
--- /dev/null
+++ b/bin/tests/system/stress/update.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
+# 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 "I: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 "I:Update failed: ", $res->errorstring, "\n";
+ }
+}
+
+sub section {
+ my ($msg) = @_;
+ print "I:$msg\n";
+}
+
+for ($i = 0; $i < 1000; $i++) {
+ test("NOERROR", ["update", rr_add("dynamic-$i.$zone 300 TXT txt-$i" )]);
+}
+
+if ($failures) {
+ print "I:$failures tests failed.\n";
+} else {
+ print "I:Update of $opt_s zone $zone successful.\n";
+}
+exit $failures;
diff --git a/bin/tests/system/stub/clean.sh b/bin/tests/system/stub/clean.sh
new file mode 100644
index 0000000..d5698ef
--- /dev/null
+++ b/bin/tests/system/stub/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after stub tests.
+#
+rm -f dig.out.ns3 ns3/child.example.st
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
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..b4a2fa8
--- /dev/null
+++ b/bin/tests/system/stub/ns1/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/stub/ns1/root.db b/bin/tests/system/stub/ns1/root.db
new file mode 100644
index 0000000..5d14899
--- /dev/null
+++ b/bin/tests/system/stub/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..12acc8a
--- /dev/null
+++ b/bin/tests/system/stub/ns2/child.example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4810cde
--- /dev/null
+++ b/bin/tests/system/stub/ns2/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "child.example" {
+ type master;
+ 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..cbf1392
--- /dev/null
+++ b/bin/tests/system/stub/ns3/example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..ce9497d
--- /dev/null
+++ b/bin/tests/system/stub/ns3/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "child.example" {
+ type stub;
+ file "child.example.st";
+ masters { 10.53.0.2; };
+};
diff --git a/bin/tests/system/stub/setup.sh b/bin/tests/system/stub/setup.sh
new file mode 100644
index 0000000..9b9aa02
--- /dev/null
+++ b/bin/tests/system/stub/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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
diff --git a/bin/tests/system/stub/tests.sh b/bin/tests/system/stub/tests.sh
new file mode 100644
index 0000000..3c51aec
--- /dev/null
+++ b/bin/tests/system/stub/tests.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+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"
+ $PERL $SYSTEMTESTTOP/stop.pl . ns3
+
+ echo_i "re-starting stub server"
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns3
+}
+done
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tcp/clean.sh b/bin/tests/system/tcp/clean.sh
new file mode 100644
index 0000000..5fb4f9b
--- /dev/null
+++ b/bin/tests/system/tcp/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f */named.stats
+rm -f dig.out*
+rm -f ns*/named.lock
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..b188783
--- /dev/null
+++ b/bin/tests/system/tcp/ns1/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ 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..dab5cea
--- /dev/null
+++ b/bin/tests/system/tcp/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4a3f33f
--- /dev/null
+++ b/bin/tests/system/tcp/ns2/example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..684b881
--- /dev/null
+++ b/bin/tests/system/tcp/ns2/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ statistics-file "named.stats";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ 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..282bb2c
--- /dev/null
+++ b/bin/tests/system/tcp/ns3/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+server 10.53.0.1 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/tcp/ns4/named.conf.in b/bin/tests/system/tcp/ns4/named.conf.in
new file mode 100644
index 0000000..e6c7c22
--- /dev/null
+++ b/bin/tests/system/tcp/ns4/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ forwarders { 10.53.0.2; };
+ forward only;
+};
+
+server 10.53.0.2 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/tcp/setup.sh b/bin/tests/system/tcp/setup.sh
new file mode 100644
index 0000000..4563f04
--- /dev/null
+++ b/bin/tests/system/tcp/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL 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/tcp/tests.sh b/bin/tests/system/tcp/tests.sh
new file mode 100644
index 0000000..89916d7
--- /dev/null
+++ b/bin/tests/system/tcp/tests.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+status=0
+
+echo_i "initialize counters"
+$RNDCCMD -s 10.53.0.1 stats > /dev/null 2>&1
+$RNDCCMD -s 10.53.0.2 stats > /dev/null 2>&1
+ntcp10=`grep "TCP requests received" ns1/named.stats | tail -1 | awk '{print $1}'`
+ntcp20=`grep "TCP requests received" ns2/named.stats | tail -1 | awk '{print $1}'`
+#echo ntcp10 ':' "$ntcp10"
+#echo ntcp20 ':' "$ntcp20"
+
+echo_i "check TCP transport"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 txt.example. > dig.out.3
+$RNDCCMD -s 10.53.0.1 stats > /dev/null 2>&1
+$RNDCCMD -s 10.53.0.2 stats > /dev/null 2>&1
+ntcp11=`grep "TCP requests received" ns1/named.stats | tail -1 | awk '{print $1}'`
+ntcp21=`grep "TCP requests received" ns2/named.stats | tail -1 | awk '{print $1}'`
+#echo ntcp11 ':' "$ntcp11"
+#echo ntcp21 ':' "$ntcp21"
+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=`expr $status + $ret`
+
+echo_i "check TCP forwarder"
+ret=0
+$DIG $DIGOPTS @10.53.0.4 txt.example. > dig.out.4
+$RNDCCMD -s 10.53.0.1 stats > /dev/null 2>&1
+$RNDCCMD -s 10.53.0.2 stats > /dev/null 2>&1
+ntcp12=`grep "TCP requests received" ns1/named.stats | tail -1 | awk '{print $1}'`
+ntcp22=`grep "TCP requests received" ns2/named.stats | tail -1 | awk '{print $1}'`
+#echo ntcp12 ':' "$ntcp12"
+#echo ntcp22 ':' "$ntcp22"
+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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/testcrypto.sh b/bin/tests/system/testcrypto.sh
new file mode 100644
index 0000000..92d3d09
--- /dev/null
+++ b/bin/tests/system/testcrypto.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=${SYSTEMTESTTOP:=..}
+. $SYSTEMTESTTOP/conf.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+prog=$0
+
+args="-r $RANDFILE"
+alg="-a RSAMD5 -b 512"
+quiet=0
+
+msg1="cryptography"
+msg2="--with-openssl, or --enable-native-pkcs11 --with-pkcs11"
+while test "$#" -gt 0; do
+ case $1 in
+ -q)
+ args="$args -q"
+ quiet=1
+ ;;
+ rsa|RSA)
+ alg=""
+ msg1="RSA cryptography"
+ ;;
+ gost|GOST)
+ alg="-a eccgost"
+ msg1="GOST cryptography"
+ msg2="--with-gost"
+ ;;
+ ecdsa|ECDSA)
+ alg="-a ecdsap256sha256"
+ msg1="ECDSA cryptography"
+ msg2="--with-ecdsa"
+ ;;
+ eddsa|EDDSA)
+ alg="-a ED25519"
+ msg1="EDDSA cryptography"
+ msg2="--with-eddsa"
+ ;;
+ *)
+ echo "${prog}: unknown argument"
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+
+if $KEYGEN $args $alg foo > /dev/null 2>&1
+then
+ rm -f Kfoo*
+else
+ if test $quiet -eq 0; then
+ echo "I:This test requires support for $msg1" >&2
+ echo "I:configure with $msg2" >&2
+ fi
+ exit 255
+fi
diff --git a/bin/tests/system/testsock.pl b/bin/tests/system/testsock.pl
new file mode 100644
index 0000000..35d9f93
--- /dev/null
+++ b/bin/tests/system/testsock.pl
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Test whether the interfaces on 10.53.0.* are up.
+
+require 5.001;
+
+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 {
+ @ids = (1..8);
+}
+
+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..ff49b67
--- /dev/null
+++ b/bin/tests/system/testsock6.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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..06c3566
--- /dev/null
+++ b/bin/tests/system/testsummary.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+keepfile=0
+
+while getopts "n" flag; do
+ case $flag in
+ n) keepfile=1 ;;
+ esac
+done
+
+if [ `ls */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
+
+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
+
+exit $status
diff --git a/bin/tests/system/tkey/Makefile.in b/bin/tests/system/tkey/Makefile.in
new file mode 100644
index 0000000..252b6c0
--- /dev/null
+++ b/bin/tests/system/tkey/Makefile.in
@@ -0,0 +1,54 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: Makefile.in,v 1.14 2009/12/05 23:31:40 each Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@
+CWARNINGS =
+
+DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@
+
+DNSDEPLIBS = ../../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = keycreate@EXEEXT@ keydelete@EXEEXT@
+
+CREATEOBJS = keycreate.@O@
+DELETEOBJS = keydelete.@O@
+
+SRCS = keycreate.c keydelete.c
+
+@BIND9_MAKE_RULES@
+
+all: keycreate@EXEEXT@ keydelete@EXEEXT@
+
+keycreate@EXEEXT@: ${CREATEOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${CREATEOBJS} ${LIBS}
+
+keydelete@EXEEXT@: ${DELETEOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${DELETEOBJS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/tests/system/tkey/clean.sh b/bin/tests/system/tkey/clean.sh
new file mode 100644
index 0000000..a8ea8cf
--- /dev/null
+++ b/bin/tests/system/tkey/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.* rndc.out.* ns1/named.conf
+rm -f K* ns1/K*
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns1/_default.tsigkeys
+rm -f ns*/named.lock
diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c
new file mode 100644
index 0000000..5a00f86
--- /dev/null
+++ b/bin/tests/system/tkey/keycreate.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <pk11/site.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>
+
+#include <dst/result.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 dst_key_t *ourkey;
+static isc_mem_t *mctx;
+static dns_tsigkey_t *tsigkey, *initialkey;
+static dns_tsig_keyring_t *ring;
+static unsigned char noncedata[16];
+static isc_buffer_t nonce;
+static dns_requestmgr_t *requestmgr;
+static const char *ownername_str = ".";
+
+#ifndef PK11_MD5_DISABLE
+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, *response;
+ 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;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + 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_destroy(&query);
+ dns_message_destroy(&response);
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+ isc_app_shutdown();
+ return;
+}
+#endif
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event) {
+#ifndef PK11_MD5_DISABLE
+ 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;
+ dns_request_t *request;
+ static char keystr[] = "0123456789ab";
+
+ isc_event_free(&event);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, "10.53.0.1", &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);
+
+ initialkey = NULL;
+ 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);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ result = dns_tkey_builddhquery(query, ourkey,
+ dns_fixedname_name(&ownername),
+ DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
+ CHECK("dns_tkey_builddhquery", result);
+
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address,
+ DNS_REQUESTOPT_TCP, initialkey,
+ TIMEOUT, task, recvquery, query,
+ &request);
+ CHECK("dns_request_create", result);
+#else
+ UNUSED(task);
+
+ isc_event_free(&event);
+ CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+int
+main(int argc, char *argv[]) {
+ char *ourkeyname;
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ dns_tkeyctx_t *tctx;
+ isc_log_t *log;
+ isc_logconfig_t *logconfig;
+ isc_task_t *task;
+ isc_result_t result;
+ int type;
+
+ RUNCHECK(isc_app_start());
+
+ if (argc < 2) {
+ fprintf(stderr, "I:no DH key provided\n");
+ exit(-1);
+ }
+ ourkeyname = argv[1];
+
+ if (argc >= 3)
+ ownername_str = argv[2];
+
+ dns_result_register();
+
+ mctx = NULL;
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "../random.data"));
+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+
+ log = NULL;
+ logconfig = NULL;
+ RUNCHECK(isc_log_create(mctx, &log, &logconfig));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+ tctx = NULL;
+ RUNCHECK(dns_tkeyctx_create(mctx, ectx, &tctx));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+ dns_tsigkeyring_detach(&ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
+
+ ourkey = 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));
+ result = isc_entropy_getdata(ectx, noncedata, sizeof(noncedata),
+ NULL, ISC_ENTROPY_BLOCKING);
+ CHECK("isc_entropy_getdata", result);
+ isc_buffer_add(&nonce, sizeof(noncedata));
+
+ (void)isc_app_run();
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ 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_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ 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..bde66a4
--- /dev/null
+++ b/bin/tests/system/tkey/keydelete.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <pk11/site.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>
+
+#include <dst/result.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;
+static dns_tsigkey_t *tsigkey;
+static dns_tsig_keyring_t *ring;
+static dns_requestmgr_t *requestmgr;
+
+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, *response;
+
+ 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;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + 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_destroy(&query);
+ dns_message_destroy(&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;
+ dns_request_t *request;
+
+ isc_event_free(&event);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1)
+ CHECK("inet_pton", result);
+ isc_sockaddr_fromin(&address, &inaddr, PORT);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ result = dns_tkey_builddeletequery(query, tsigkey);
+ CHECK("dns_tkey_builddeletequery", result);
+
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address,
+ DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT,
+ task, recvquery, query, &request);
+ CHECK("dns_request_create", result);
+}
+
+int
+main(int argc, char **argv) {
+ char *keyname;
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ dns_tkeyctx_t *tctx;
+ dst_key_t *dstkey;
+ isc_log_t *log;
+ isc_logconfig_t *logconfig;
+ isc_task_t *task;
+ isc_result_t result;
+ int type;
+
+ RUNCHECK(isc_app_start());
+
+ if (argc < 2) {
+ fprintf(stderr, "I:no key to delete\n");
+ exit(-1);
+ }
+ keyname = argv[1];
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "../random.data"));
+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+
+ log = NULL;
+ logconfig = NULL;
+ RUNCHECK(isc_log_create(mctx, &log, &logconfig));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+ tctx = NULL;
+ RUNCHECK(dns_tkeyctx_create(mctx, ectx, &tctx));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
+
+ dstkey = 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);
+#ifndef PK11_MD5_DISABLE
+ 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);
+#else
+ dst_key_free(&dstkey);
+ CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED);
+#endif
+
+ (void)isc_app_run();
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ dns_tsigkeyring_detach(&ring);
+
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_tkeyctx_destroy(&tctx);
+
+ dns_view_detach(&view);
+
+ isc_log_destroy(&log);
+
+ dst_lib_destroy();
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ 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..7771d28
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/example.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..9300397
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: named.conf.in,v 1.10 2011/11/03 23:46:26 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ tkey-domain "server";
+ tkey-dhkey "server" KEYID;
+ allow-query-cache { any; };
+ random-device "RANDFILE";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+key "tkeytest." {
+ algorithm hmac-md5;
+ secret "0123456789ab";
+};
+
+zone example {
+ type master;
+ 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..c1e2ff3
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+keyname=`$KEYGEN -T KEY -a DH -b 768 -n host -r $RANDFILE server`
+keyid=`echo $keyname | $PERL -p -e 's/^.*\+0*//;'`
+rm -f named.conf
+sed -e "s;KEYID;$keyid;" -e "s;RANDFILE;$RANDFILE;" < named.conf.in > named.conf
diff --git a/bin/tests/system/tkey/prereq.sh b/bin/tests/system/tkey/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/tkey/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/tkey/setup.sh b/bin/tests/system/tkey/setup.sh
new file mode 100644
index 0000000..299ae5d
--- /dev/null
+++ b/bin/tests/system/tkey/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..9f90dd7
--- /dev/null
+++ b/bin/tests/system/tkey/tests.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# $Id: tests.sh,v 1.11 2011/11/03 23:46:26 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="@10.53.0.1 -p 5300"
+
+status=0
+
+echo "I:generating new DH key"
+ret=0
+dhkeyname=`$KEYGEN -T KEY -a DH -b 768 -n host -r $RANDFILE client` || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+ status=`expr $status + $ret`
+ echo "I:exit status: $status"
+ exit $status
+fi
+status=`expr $status + $ret`
+
+for owner in . foo.example.
+do
+ echo "I:creating new key using owner name \"$owner\""
+ ret=0
+ keyname=`$KEYCREATE $dhkeyname $owner` || ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ status=`expr $status + $ret`
+ echo "I:exit status: $status"
+ exit $status
+ fi
+ status=`expr $status + $ret`
+
+ echo "I:checking the new key"
+ ret=0
+ $DIG $DIGOPTS . ns -k $keyname > dig.out.1 || ret=1
+ grep "status: NOERROR" dig.out.1 > /dev/null || ret=1
+ grep "TSIG.*hmac-md5.*NOERROR" dig.out.1 > /dev/null || ret=1
+ grep "Some TSIG could not be validated" dig.out.1 > /dev/null && ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ fi
+ status=`expr $status + $ret`
+
+ echo "I:deleting new key"
+ ret=0
+ $KEYDELETE $keyname || ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ fi
+ status=`expr $status + $ret`
+
+ echo "I:checking that new key has been deleted"
+ ret=0
+ $DIG $DIGOPTS . ns -k $keyname > dig.out.2 || ret=1
+ grep "status: NOERROR" dig.out.2 > /dev/null && ret=1
+ grep "TSIG.*hmac-md5.*NOERROR" dig.out.2 > /dev/null && ret=1
+ grep "Some TSIG could not be validated" dig.out.2 > /dev/null || ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:creating new key using owner name bar.example."
+ret=0
+keyname=`$KEYCREATE $dhkeyname bar.example.` || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+ status=`expr $status + $ret`
+ echo "I:exit status: $status"
+ exit $status
+fi
+status=`expr $status + $ret`
+
+echo "I:checking the key with 'rndc tsig-list'"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 tsig-list > rndc.out.1
+grep "key \"bar.example.server" rndc.out.1 > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:using key in a request"
+ret=0
+$DIG $DIGOPTS -k $keyname txt.example txt > dig.out.3 || ret=1
+grep "status: NOERROR" dig.out.3 > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:deleting the key with 'rndc tsig-delete'"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 tsig-delete bar.example.server > /dev/null || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 tsig-list > rndc.out.2
+grep "key \"bar.example.server" rndc.out.2 > /dev/null && ret=1
+$DIG $DIGOPTS -k $keyname txt.example txt > dig.out.4 || ret=1
+grep "TSIG could not be validated" dig.out.4 > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:recreating the bar.example. key"
+ret=0
+keyname=`$KEYCREATE $dhkeyname bar.example.` || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+ status=`expr $status + $ret`
+ echo "I:exit status: $status"
+ exit $status
+fi
+status=`expr $status + $ret`
+
+echo "I:checking the new key with 'rndc tsig-list'"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 tsig-list > rndc.out.3
+grep "key \"bar.example.server" rndc.out.3 > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:using the new key in a request"
+ret=0
+$DIG $DIGOPTS -k $keyname txt.example txt > dig.out.5 || ret=1
+grep "status: NOERROR" dig.out.5 > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh
new file mode 100644
index 0000000..576ec70
--- /dev/null
+++ b/bin/tests/system/tsig/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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.+163+*
+rm -f keygen.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..05d8dd8
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/example.db
@@ -0,0 +1,161 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/named.conf.in b/bin/tests/system/tsig/ns1/named.conf.in
new file mode 100644
index 0000000..fbf30c6
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/named.conf.in
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key "md5" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5;
+};
+
+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;
+};
+
+key "md5-trunc" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5-80;
+};
+
+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 master;
+ file "example.db";
+};
diff --git a/bin/tests/system/tsig/setup.sh b/bin/tests/system/tsig/setup.sh
new file mode 100644
index 0000000..656e9bb
--- /dev/null
+++ b/bin/tests/system/tsig/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh
new file mode 100644
index 0000000..f731fa6
--- /dev/null
+++ b/bin/tests/system/tsig/tests.sh
@@ -0,0 +1,222 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+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
+
+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
+
+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
+#
+#
+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
+
+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.
+#
+#
+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
+
+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 multiple dnssec-keygen calls don't emit dns_dnssec_findmatchingkeys warning"
+ret=0
+$KEYGEN -r $RANDFILE -a hmac-sha256 -b 128 -n host example.net > keygen.out1 2>&1 || ret=1
+grep dns_dnssec_findmatchingkeys keygen.out1 > /dev/null && ret=1
+$KEYGEN -r $RANDFILE -a hmac-sha256 -b 128 -n host example.net > keygen.out2 2>&1 || ret=1
+grep dns_dnssec_findmatchingkeys keygen.out2 > /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/tsiggss/authsock.pl b/bin/tests/system/tsiggss/authsock.pl
new file mode 100644
index 0000000..57a72b2
--- /dev/null
+++ b/bin/tests/system/tsiggss/authsock.pl
@@ -0,0 +1,89 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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..c97ade7
--- /dev/null
+++ b/bin/tests/system/tsiggss/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
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..001bb29
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/example.nil.db.in
@@ -0,0 +1,51 @@
+; -*- 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..583cb37
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example.nil." IN {
+ type master;
+ 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..8fbe016
--- /dev/null
+++ b/bin/tests/system/tsiggss/prereq.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+# enable the tsiggss test only if gssapi was enabled
+$FEATURETEST --gssapi || {
+ echo_i "gssapi and krb5 not supported - skipping tsiggss test"
+ exit 255
+}
+
+# ... and crypto
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/tsiggss/setup.sh b/bin/tests/system/tsiggss/setup.sh
new file mode 100644
index 0000000..5da33cf
--- /dev/null
+++ b/bin/tests/system/tsiggss/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+key=`$KEYGEN -Cq -K ns1 -a DSA -b 512 -r $RANDFILE -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..b489d7b
--- /dev/null
+++ b/bin/tests/system/tsiggss/tests.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# tests for TSIG-GSS updates
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+DIGOPTS="@10.53.0.1 -p ${PORT}"
+
+test_update() {
+ host="$1"
+ type="$2"
+ cmd="$3"
+ digout="$4"
+
+ cat <<EOF > ns1/update.txt
+server 10.53.0.1 ${PORT}
+update add $host $cmd
+send
+EOF
+ echo "I:testing update for $host $type $cmd"
+ $NSUPDATE -g -d ns1/update.txt > nsupdate.out 2>&1 || {
+ echo "I:update failed for $host $type $cmd"
+ sed "s/^/I:/" nsupdate.out
+ return 1
+ }
+
+ out=`$DIG $DIGOPTS -t $type -q $host | egrep "^${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
+}
+
+echo "I:testing updates as administrator"
+KRB5CCNAME="FILE:"`pwd`/ns1/administrator.ccache
+export KRB5CCNAME
+
+test_update testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || status=1
+test_update testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || status=1
+test_update denied.example.nil. TXT "86400 TXT helloworld" "helloworld" > /dev/null && status=1
+
+echo "I:testing updates as a user"
+KRB5CCNAME="FILE:"`pwd`/ns1/testdenied.ccache
+export KRB5CCNAME
+
+test_update testdenied.example.nil. A "86400 A 10.53.0.12" "10.53.0.12" > /dev/null && status=1
+test_update testdenied.example.nil. TXT "86400 TXT helloworld" "helloworld" || status=1
+
+echo "I:testing external update policy"
+test_update testcname.example.nil. TXT "86400 CNAME testdenied.example.nil" "testdenied" > /dev/null && status=1
+$PERL ./authsock.pl --type=CNAME --path=ns1/auth.sock --pidfile=authsock.pid --timeout=120 > /dev/null 2>&1 &
+sleep 1
+test_update testcname.example.nil. TXT "86400 CNAME testdenied.example.nil" "testdenied" || status=1
+test_update testcname.example.nil. TXT "86400 A 10.53.0.13" "10.53.0.13" > /dev/null && status=1
+
+echo "I:testing external policy with SIG(0) key"
+ret=0
+$NSUPDATE -R $RANDFILE -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"
+status=`expr $status + $ret`
+
+echo "I:ensure too long realm name is fatal in non-interactive mode"
+ret=0
+$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
+ realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
+END
+grep "realm is too long" nsupdate.out > /dev/null || ret=1
+grep "syntax error" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo I:failed; status=1; }
+
+echo "I:ensure too long realm name is not fatal in interactive mode"
+ret=0
+$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
+ realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
+END
+grep "realm is too long" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo I:failed; status=1; }
+
+[ $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/unknown/clean.sh b/bin/tests/system/unknown/clean.sh
new file mode 100644
index 0000000..8d734fa
--- /dev/null
+++ b/bin/tests/system/unknown/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f 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
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..0c5a4a5
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken1.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..a3c84ff
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken2.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..17dde88
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken3.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..a404256
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken4.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..c31e279
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken5.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..440b36f
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/class10.hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..a8e1d4d
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/example-class10.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..d29f8da
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/example-in.db
@@ -0,0 +1,54 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..2c826d7
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/large.db
@@ -0,0 +1,3009 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+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..e92b9c4
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/named.conf.in
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+view "in" {
+ zone "example." {
+ type master;
+ file "example-in.db";
+ };
+
+ zone "broken1." {
+ type master;
+ file "broken1.db";
+ };
+
+ zone "broken2." {
+ type master;
+ file "broken2.db";
+ };
+
+ zone "broken3." {
+ type master;
+ file "broken3.db";
+ };
+
+ zone "broken4." {
+ type master;
+ file "broken4.db";
+ };
+
+ zone "broken5." {
+ type master;
+ file "broken5.db";
+ };
+};
+
+view "class10" class10 {
+ zone "." class10 {
+ type hint;
+ file "class10.hints";
+ };
+
+ zone "example." class10 {
+ type master;
+ 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..2571626
--- /dev/null
+++ b/bin/tests/system/unknown/ns2/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+view "in" {
+ zone "example." {
+ type slave;
+ masters { 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..2ccb074
--- /dev/null
+++ b/bin/tests/system/unknown/ns3/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+};
+
+view "in" {
+ zone "example." {
+ type slave;
+ masters { 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..475c42e
--- /dev/null
+++ b/bin/tests/system/unknown/ns3/sign.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=example
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone`
diff --git a/bin/tests/system/unknown/prereq.sh b/bin/tests/system/unknown/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/unknown/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/unknown/setup.sh b/bin/tests/system/unknown/setup.sh
new file mode 100644
index 0000000..a328376
--- /dev/null
+++ b/bin/tests/system/unknown/setup.sh
@@ -0,0 +1,21 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..7fbec3f
--- /dev/null
+++ b/bin/tests/system/unknown/tests.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+DIGOPTS="-p ${PORT}"
+
+echo_i "querying for various representations of an IN A record"
+for i in 1 2 3 4 5 6 7 8 9 10 11 12
+do
+ ret=0
+ $DIG +short $DIGOPTS @10.53.0.1 a$i.example a in > dig.out || ret=1
+ echo 10.0.0.1 | $DIFF - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "querying for various representations of an IN TXT record"
+for i in 1 2 3 4 5 6 7
+do
+ ret=0
+ $DIG +short $DIGOPTS @10.53.0.1 txt$i.example txt in > dig.out || ret=1
+ echo '"hello"' | $DIFF - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "querying for various representations of an IN TYPE123 record"
+for i in 1 2 3
+do
+ ret=0
+ $DIG +short $DIGOPTS @10.53.0.1 unk$i.example type123 in > dig.out || ret=1
+ echo '\# 1 00' | $DIFF - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "querying for NULL record"
+ret=0
+$DIG +short $DIGOPTS @10.53.0.1 null.example null in > dig.out || ret=1
+echo '\# 1 00' | $DIFF - dig.out || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "querying for empty NULL record"
+ret=0
+$DIG +short $DIGOPTS @10.53.0.1 empty.example null in > dig.out || ret=1
+echo '\# 0' | $DIFF - dig.out || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "querying for various representations of a CLASS10 TYPE1 record"
+for i in 1 2
+do
+ ret=0
+ $DIG +short $DIGOPTS @10.53.0.1 a$i.example a class10 > dig.out || ret=1
+ echo '\# 4 0A000001' | $DIFF - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "querying for various representations of a CLASS10 TXT record"
+for i in 1 2 3 4
+do
+ ret=0
+ $DIG +short $DIGOPTS @10.53.0.1 txt$i.example txt class10 > dig.out || ret=1
+ echo '"hello"' | $DIFF - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "querying for various representations of a CLASS10 TYPE123 record"
+for i in 1 2
+do
+ ret=0
+ $DIG +short $DIGOPTS @10.53.0.1 unk$i.example type123 class10 > dig.out || ret=1
+ echo '\# 1 00' | $DIFF - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "querying for SOAs of zone that should have failed to load"
+for i in 1 2 3 4
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.1 broken$i. soa in > dig.out || ret=1
+ grep "SERVFAIL" dig.out > /dev/null || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo_i "checking large unknown record loading on master"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 +tcp +short large.example TYPE45234 > dig.out || { ret=1 ; echo_i "dig failed" ; }
+$DIFF -s large.out dig.out > /dev/null || { ret=1 ; echo_i "$DIFF failed"; }
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking large unknown record loading on slave"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 +tcp +short large.example TYPE45234 > dig.out || { ret=1 ; echo_i "dig failed" ; }
+$DIFF -s large.out dig.out > /dev/null || { ret=1 ; echo_i "$DIFF failed"; }
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "stop and restart slave"
+$PERL $SYSTEMTESTTOP/stop.pl . ns2
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns2
+
+echo_i "checking large unknown record loading on slave"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 +tcp +short large.example TYPE45234 > dig.out || { ret=1 ; echo_i "dig failed" ; }
+$DIFF -s large.out dig.out > /dev/null || { ret=1 ; echo_i "$DIFF failed"; }
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "checking large unknown record loading on inline slave"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 +tcp +short large.example TYPE45234 > dig.out || { ret=1 ; echo_i "dig failed" ; }
+$DIFF large.out dig.out > /dev/null || { ret=1 ; echo_i "$DIFF failed"; }
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "stop and restart inline slave"
+$PERL $SYSTEMTESTTOP/stop.pl . ns3
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns3
+
+echo_i "checking large unknown record loading on inline slave"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 +tcp +short large.example TYPE45234 > dig.out || { ret=1 ; echo_i "dig failed" ; }
+$DIFF large.out dig.out > /dev/null || { ret=1 ; echo_i "$DIFF failed"; }
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "check that '"'"\\#"'"' is not treated as the unknown escape sequence"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 +tcp +short txt8.example txt > dig.out
+echo '"#" "2" "0145"' | $DIFF - dig.out || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "check that 'TXT \# text' is not treated as the unknown escape sequence"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 +tcp +short txt9.example txt > dig.out
+echo '"#" "text"' | $DIFF - dig.out || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "check that 'TYPE353 \# cat' produces 'not a valid number'"
+ret=0
+$CHECKZONE nan.bad zones/nan.bad > check.out 2>&1
+grep "not a valid number" check.out > /dev/null || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/unknown/zones/nan.bad b/bin/tests/system/unknown/zones/nan.bad
new file mode 100644
index 0000000..39efac7
--- /dev/null
+++ b/bin/tests/system/unknown/zones/nan.bad
@@ -0,0 +1,10 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..e98c2cf
--- /dev/null
+++ b/bin/tests/system/upforwd/ans4/ans.pl
@@ -0,0 +1,361 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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..d622204
--- /dev/null
+++ b/bin/tests/system/upforwd/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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/nomaster1.db
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f */ans.run
+rm -f Ksig0.example2.*
+rm -f keyname
+rm -f ns*/named.lock
+rm -f ns1/example2.db
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..a703d02
--- /dev/null
+++ b/bin/tests/system/upforwd/ns1/example1.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..e0a30cd
--- /dev/null
+++ b/bin/tests/system/upforwd/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { key update.example.; 10.53.0.3; };
+};
+
+zone "example2" {
+ type master;
+ 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..c650781
--- /dev/null
+++ b/bin/tests/system/upforwd/ns2/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type slave;
+ file "example.bk";
+ masters { 10.53.0.1; };
+};
+
+zone "example2" {
+ type slave;
+ file "example2.bk";
+ masters { 10.53.0.1; };
+};
diff --git a/bin/tests/system/upforwd/ns3/named.conf.in b/bin/tests/system/upforwd/ns3/named.conf.in
new file mode 100644
index 0000000..d6fc26c
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type slave;
+ file "example.bk";
+ allow-update-forwarding { any; };
+ masters { 10.53.0.1; };
+};
+
+zone "example2" {
+ type slave;
+ file "example2.bk";
+ allow-update-forwarding { any; };
+ masters { 10.53.0.1; };
+};
+
+zone "nomaster" {
+ type slave;
+ file "nomaster1.db";
+ allow-update-forwarding { any; };
+ masterfile-format text;
+ masters { 10.53.0.4; };
+};
diff --git a/bin/tests/system/upforwd/ns3/nomaster.db b/bin/tests/system/upforwd/ns3/nomaster.db
new file mode 100644
index 0000000..443bedb
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/nomaster.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 141235 3600 1200 86400 1200
+@ 0 NS ns4
+ns4 0 A 10.53.0.4
diff --git a/bin/tests/system/upforwd/prereq.sh b/bin/tests/system/upforwd/prereq.sh
new file mode 100644
index 0000000..0e299f4
--- /dev/null
+++ b/bin/tests/system/upforwd/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo_i "This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/upforwd/setup.sh b/bin/tests/system/upforwd/setup.sh
new file mode 100644
index 0000000..c32aab4
--- /dev/null
+++ b/bin/tests/system/upforwd/setup.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+cp -f ns1/example1.db ns1/example.db
+cp -f ns3/nomaster.db ns3/nomaster1.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
+
+#
+# SIG(0) required cryptographic support which may not be configured.
+#
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+keyname=`$KEYGEN -q -r $RANDFILE -n HOST -a RSASHA1 -b 1024 -T KEY sig0.example2 2>/dev/null | $D2U`
+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
+ rm -f keyname
+fi
diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh
new file mode 100644
index 0000000..b0694bb
--- /dev/null
+++ b/bin/tests/system/upforwd/tests.sh
@@ -0,0 +1,198 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# ns1 = stealth master
+# ns2 = slave with update forwarding disabled; not currently used
+# ns3 = slave with update forwarding enabled
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+
+status=0
+n=1
+
+sleep 5
+
+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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "fetching master 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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "fetching slave 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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "fetching slave 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=`expr $status + $ret`; fi
+n=`expr $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=`expr $status + $ret`; fi
+
+echo_i "updating zone (signed) ($n)"
+ret=0
+$NSUPDATE -y update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K -- - <<EOF || ret=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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo_i "fetching master 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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "fetching slave 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=`expr $status + $ret`; fi
+
+echo_i "fetching slave 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=`expr $status + $ret`; fi
+n=`expr $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=`expr $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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "updating zone (unsigned) ($n)"
+ret=0
+$NSUPDATE -- - <<EOF || ret=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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo_i "fetching master 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=`expr $status + $ret`; fi
+
+echo_i "fetching slave 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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "fetching slave 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=`expr $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=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+echo_i "checking update forwarding to dead master ($n)"
+count=0
+ret=0
+while [ $count -lt 5 -a $ret -eq 0 ]
+do
+(
+$NSUPDATE -- - <<EOF
+server 10.53.0.3 ${PORT}
+zone nomaster
+update add unsigned.nomaster. 600 A 10.10.10.1
+update add unsigned.nomaster. 600 TXT Foo
+send
+EOF
+) > /dev/null 2>&1 &
+ $DIG -p ${PORT} +noadd +notcp +noauth nomaster. @10.53.0.3 soa > dig.out.ns3 || ret=1
+ grep "status: NOERROR" dig.out.ns3 > /dev/null || ret=1
+ count=`expr $count + 1`
+done
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+n=`expr $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
+ 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=`expr $status + $ret`
+ n=`expr $n + 1`
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/verify/clean.sh b/bin/tests/system/verify/clean.sh
new file mode 100644
index 0000000..74c9be2
--- /dev/null
+++ b/bin/tests/system/verify/clean.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.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/prereq.sh b/bin/tests/system/verify/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/verify/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/verify/setup.sh b/bin/tests/system/verify/setup.sh
new file mode 100644
index 0000000..8c8e10a
--- /dev/null
+++ b/bin/tests/system/verify/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+(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..e8b2210
--- /dev/null
+++ b/bin/tests/system/verify/tests.sh
@@ -0,0 +1,108 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+failed () {
+ cat verify.out.$n | sed 's/^/D:/';
+ echo_i "failed";
+ status=1;
+}
+
+n=0
+status=0
+
+for file in zones/*.good
+do
+ n=`expr $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=`expr $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=`expr $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=`expr $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/zones/genzones.sh b/bin/tests/system/verify/zones/genzones.sh
new file mode 100644
index 0000000..8d89066
--- /dev/null
+++ b/bin/tests/system/verify/zones/genzones.sh
@@ -0,0 +1,241 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=verify
+
+dumpit () {
+ echo "D:${debug}: dumping ${1}"
+ cat "${1}" | sed 's/^/D:/'
+}
+setup () {
+ echo_i "setting up $2 zone: $1"
+ debug="$1"
+ zone="$1"
+ file="$1.$2"
+ n=`expr ${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 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SP -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk-only.nsec good
+$KEYGEN -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SPz -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.nsec good
+$KEYGEN -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.nsec.apex-dname good
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || dumpit s.out$n
+
+# A set of nsec3 zones.
+setup zsk-only.nsec3 good
+$KEYGEN -3 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - -SP -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk-only.nsec3 good
+$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - -SPz -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.nsec3 good
+$KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -3 - -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.optout good
+$KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -3 - -A -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.nsec3.apex-dname good
+zsk=`$KEYGEN -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -3 -r $RANDFILE -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 2>&1 || 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 rsasha256 -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
+zsk=`$KEYGEN -a rsasha256 ${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 2>&1 || 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 -r $RANDFILE ${zone} 2>kg.out` || dumpit kg.out$n
+cat unsigned.db $key1.key > ${file}
+
+setup ksk-only.dnskeyonly bad
+key1=`$KEYGEN -r $RANDFILE -fK ${zone} 2>kg.out` || dumpit kg.out$n
+cat unsigned.db $key1.key > ${file}
+
+setup ksk+zsk.dnskeyonly bad
+key1=`$KEYGEN -r $RANDFILE ${zone} 2>kg.out` || dumpit kg.out$n
+key2=`$KEYGEN -r $RANDFILE -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 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SP ${s} -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk-only.nsec.expired bad
+$KEYGEN -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SPz ${s} -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.nsec.expired bad
+$KEYGEN -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -SP ${s} -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup zsk-only.nsec3.expired bad
+$KEYGEN -3 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - ${s} -SP -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk-only.nsec3.expired bad
+$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - ${s} -SPz -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+setup ksk+zsk.nsec3.expired bad
+$KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -3 - ${s} -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
+
+# ksk expired
+setup ksk+zsk.nsec.ksk-expired bad
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || dumpit s.out$n
+$SIGNER ${s} -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || 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 -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -3 -r $RANDFILE -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 2>&1 || dumpit s.out$n
+$SIGNER -3 - ${s} -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || 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 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || 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 2>&1 || dumpit s.out$n
+
+# bad nsec bitmap
+setup ksk+zsk.nsec.bad-bitmap bad
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || 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 2>&1 || dumpit s.out$n
+
+# extra NSEC record out side of zone
+setup ksk+zsk.nsec.out-of-zone-nsec bad
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || 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 2>&1 || dumpit s.out$n
+
+# extra NSEC record below bottom of zone
+setup ksk+zsk.nsec.below-bottom-of-zone-nsec bad
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || 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 2>&1 || 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 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -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 2>&1 || 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 2>&1 || 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 -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -3 -r $RANDFILE -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 2>&1 || 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 2>&1 || dumpit s.out$n
+
+# extra NSEC3 record
+setup ksk+zsk.nsec3.extra-nsec3 bad
+zsk=`$KEYGEN -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -3 -r $RANDFILE -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 2>&1 || dumpit s.out$n
+awk '
+BEGIN {
+ ZONE="'${zone}'.";
+}
+$4 == "NSEC3" && NF == 9 {
+ $1 = "H9P7U7TR2U91D0V0LJS9L1GIDNP90U3H." ZONE;
+ $9 = "H9P7U7TR2U91D0V0LJS9L1GIDNP90U3I";
+ print;
+}' ${file} >> ${file}
+$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || 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..a1e250e
--- /dev/null
+++ b/bin/tests/system/verify/zones/unsigned.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..3fbb4b0
--- /dev/null
+++ b/bin/tests/system/views/clean.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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 dig.out.external dig.out.internal
+rm -f ns*/named.lock
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..b4a2fa8
--- /dev/null
+++ b/bin/tests/system/views/ns1/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/views/ns1/root.db b/bin/tests/system/views/ns1/root.db
new file mode 100644
index 0000000..dab5cea
--- /dev/null
+++ b/bin/tests/system/views/ns1/root.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ffe6d0d
--- /dev/null
+++ b/bin/tests/system/views/ns2/1.10.in-addr.arpa.db
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN SOA . . 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..52bedaa
--- /dev/null
+++ b/bin/tests/system/views/ns2/clone.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..4a3f33f
--- /dev/null
+++ b/bin/tests/system/views/ns2/example1.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..85af638
--- /dev/null
+++ b/bin/tests/system/views/ns2/example2.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..e41e68c
--- /dev/null
+++ b/bin/tests/system/views/ns2/external/inline.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..38a6b0d
--- /dev/null
+++ b/bin/tests/system/views/ns2/internal.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..8da7940
--- /dev/null
+++ b/bin/tests/system/views/ns2/internal/inline.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..b91f95b
--- /dev/null
+++ b/bin/tests/system/views/ns2/named1.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { any; };
+};
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..b9456e0
--- /dev/null
+++ b/bin/tests/system/views/ns2/named2.conf.in
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "internal.db";
+ allow-update { any; };
+ };
+
+ zone "clone" {
+ type master;
+ file "clone.db";
+ allow-update { any; };
+ };
+
+ zone "1.10.in-addr.arpa" {
+ type master;
+ file "1.10.in-addr.arpa.db";
+ };
+
+ zone "inline" {
+ type master;
+ file "internal/inline.db";
+ key-directory "internal";
+ auto-dnssec maintain;
+ inline-signing yes;
+ };
+};
+
+view "external" {
+ match-clients { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type master;
+ 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 master;
+ file "external/inline.db";
+ key-directory "external";
+ auto-dnssec maintain;
+ inline-signing yes;
+ };
+};
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..9ea8d12
--- /dev/null
+++ b/bin/tests/system/views/ns3/child.clone.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..cdf2648
--- /dev/null
+++ b/bin/tests/system/views/ns3/internal.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..617df48
--- /dev/null
+++ b/bin/tests/system/views/ns3/named1.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ allow-update { any; };
+ file "internal.db";
+};
+
+zone "child.clone" {
+ type master;
+ 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..f72255c
--- /dev/null
+++ b/bin/tests/system/views/ns3/named2.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "internal.bk";
+};
+
+zone "child.clone" {
+ type master;
+ 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..8dd4ec1
--- /dev/null
+++ b/bin/tests/system/views/ns5/child.clone.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+$TTL 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..d309987
--- /dev/null
+++ b/bin/tests/system/views/ns5/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "child.clone" {
+ type master;
+ 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..f91fdd3
--- /dev/null
+++ b/bin/tests/system/views/setup.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+cp -f ns2/example1.db ns2/example.db
+rm -f ns2/external/K*
+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.signed
+rm -f ns2/internal/inline.db.signed.jnl
+
+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 -r $RANDFILE -3q inline > /dev/null 2>&1
+$KEYGEN -K ns2/internal -r $RANDFILE -3qfk inline > /dev/null 2>&1
+k1=`$KEYGEN -K ns2/external -r $RANDFILE -3q inline 2> /dev/null`
+k2=`$KEYGEN -K ns2/external -r $RANDFILE -3qfk inline 2> /dev/null`
+$KEYGEN -K ns2/external -r $RANDFILE -3q inline > /dev/null 2>&1
+$KEYGEN -K ns2/external -r $RANDFILE -3qfk 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..537928f
--- /dev/null
+++ b/bin/tests/system/views/tests.sh
@@ -0,0 +1,134 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth -p ${PORT}"
+SHORTOPTS="+tcp +short -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+
+echo_i "fetching a.example from ns2's initial configuration"
+$DIG $DIGOPTS a.example. @10.53.0.2 any > dig.out.ns2.1 || status=1
+
+echo_i "fetching a.example from ns3's initial configuration"
+$DIG $DIGOPTS 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
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+$RNDCCMD 10.53.0.3 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+
+echo_i "wait for reload"
+a=0 b=0
+for i in 1 2 3 4 5 6 7 8 9 0; do
+ nextpart ns2/named.run | grep "all zones loaded" > /dev/null && a=1
+ nextpart ns3/named.run | grep "all zones loaded" > /dev/null && b=1
+ [ $a -eq 1 -a $b -eq 1 ] && break
+ sleep 1
+done
+
+echo_i "fetching a.example from ns2's 10.53.0.4, source address 10.53.0.4"
+$DIG $DIGOPTS -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 $DIGOPTS -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 $DIGOPTS @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 $SHORTOPTS -b 10.53.0.2 @10.53.0.2 b.clone a`
+two=`$DIG $SHORTOPTS -b 10.53.0.4 @10.53.0.2 b.clone a`
+if [ "$one" != "$two" ]; then
+ echo "'$one' does not match '$two'"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "verifying forwarder in cloned zone works"
+ret=0
+one=`$DIG $SHORTOPTS -b 10.53.0.2 @10.53.0.2 child.clone txt`
+two=`$DIG $SHORTOPTS -b 10.53.0.4 @10.53.0.2 child.clone txt`
+three=`$DIG $SHORTOPTS @10.53.0.3 child.clone txt`
+four=`$DIG $SHORTOPTS @10.53.0.5 child.clone txt`
+echo "$three" | grep NS3 > /dev/null || { ret=1; echo "expected response from NS3 got '$three'"; }
+echo "$four" | grep NS5 > /dev/null || { ret=1; echo "expected response from NS5 got '$four'"; }
+if [ "$one" = "$two" ]; then
+ echo "'$one' matches '$two'"
+ ret=1
+fi
+if [ "$one" != "$three" ]; then
+ echo "'$one' does not match '$three'"
+ ret=1
+fi
+if [ "$two" != "$four" ]; then
+ echo "'$two' does not match '$four'"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if $SHELL ../testcrypto.sh
+then
+ echo_i "verifying inline zones work with views"
+ ret=0
+ $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 || ret=1
+ grep "ANSWER: 4," dig.out.external > /dev/null || 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=`expr $status + $ret`
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/wildcard/clean.sh b/bin/tests/system/wildcard/clean.sh
new file mode 100644
index 0000000..8f99328
--- /dev/null
+++ b/bin/tests/system/wildcard/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.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
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..413ca28
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/dlv.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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/named.conf.in b/bin/tests/system/wildcard/ns1/named.conf.in
new file mode 100644
index 0000000..e02ee67
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-enable yes;
+};
+
+zone "." { type master; file "root.db.signed"; };
+
+zone "dlv" { type master; file "dlv.db.signed"; };
+
+zone "nsec" { type master; file "nsec.db.signed"; };
+zone "private.nsec" { type master; file "private.nsec.db.signed"; };
+
+/*
+ * The contents of nsec3 and private.nsec3 are specially choosen to
+ * have seperate NSEC3 records for the "no qname proof" and the
+ * "closest encloser proof".
+ */
+zone "nsec3" { type master; file "nsec3.db.signed"; };
+zone "private.nsec3" { type master; 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..940e8e1
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/nsec.db.in
@@ -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 http://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..940e8e1
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/nsec3.db.in
@@ -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 http://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..5114ac4
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/private.nsec.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..98b7875
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/private.nsec3.db.in
@@ -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 http://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..493140f
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/root.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+dlv NS a.root-servers.nil
+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..de94423
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/sign.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+SYSTESTDIR=wildcard
+
+dssets=
+
+zone=dlv.
+infile=dlv.db.in
+zonefile=dlv.db
+outfile=dlv.db.signed
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=nsec.
+infile=nsec.db.in
+zonefile=nsec.db
+outfile=nsec.db.signed
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -r $RANDFILE -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 -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_trusted_keys $keyname2 > private.nsec.conf
+
+zone=nsec3.
+infile=nsec3.db.in
+zonefile=nsec3.db
+outfile=nsec3.db.signed
+dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP"
+
+keyname1=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -r $RANDFILE -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 -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -r $RANDFILE -3 - -H 10 -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_trusted_keys $keyname2 > private.nsec3.conf
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+outfile=root.db.signed
+
+keyname1=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
+
+cat $infile $keyname1.key $keyname2.key $dssets >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_trusted_keys $keyname2 > trusted.conf
diff --git a/bin/tests/system/wildcard/ns2/hints b/bin/tests/system/wildcard/ns2/hints
new file mode 100644
index 0000000..b4b8f7a
--- /dev/null
+++ b/bin/tests/system/wildcard/ns2/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.root-servers.nil.
+ns.root-servers.nil. 0 A 10.53.0.1
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..67a50fc
--- /dev/null
+++ b/bin/tests/system/wildcard/ns2/named.conf.in
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+zone "." { type hint; file "hints"; };
diff --git a/bin/tests/system/wildcard/ns3/hints b/bin/tests/system/wildcard/ns3/hints
new file mode 100644
index 0000000..b4b8f7a
--- /dev/null
+++ b/bin/tests/system/wildcard/ns3/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.root-servers.nil.
+ns.root-servers.nil. 0 A 10.53.0.1
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..ad908a4
--- /dev/null
+++ b/bin/tests/system/wildcard/ns3/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+include "../ns1/trusted.conf";
+
+zone "." { type hint; file "hints"; };
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..0b432c0
--- /dev/null
+++ b/bin/tests/system/wildcard/ns4/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ 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/hints b/bin/tests/system/wildcard/ns5/hints
new file mode 100644
index 0000000..b4b8f7a
--- /dev/null
+++ b/bin/tests/system/wildcard/ns5/hints
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns.root-servers.nil.
+ns.root-servers.nil. 0 A 10.53.0.1
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..9ef24c7
--- /dev/null
+++ b/bin/tests/system/wildcard/ns5/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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-lookaside . trust-anchor dlv;
+};
+
+include "../ns1/trusted.conf";
+
+zone "." { type hint; file "hints"; };
diff --git a/bin/tests/system/wildcard/prereq.sh b/bin/tests/system/wildcard/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/wildcard/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/wildcard/setup.sh b/bin/tests/system/wildcard/setup.sh
new file mode 100644
index 0000000..a05c7ae
--- /dev/null
+++ b/bin/tests/system/wildcard/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+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..5037a72
--- /dev/null
+++ b/bin/tests/system/wildcard/tests.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+n=`expr $n + 1`
+echo_i "checking that NSEC wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC wildcard non-existance 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=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo_i "checking that returned NSEC wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that returned NSEC wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that returned NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking that returned NSEC3 wildcard non-existance 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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/win32/bigkey.dsp.in b/bin/tests/system/win32/bigkey.dsp.in
new file mode 100644
index 0000000..18f4478
--- /dev/null
+++ b/bin/tests/system/win32/bigkey.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="bigkey" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=bigkey - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "bigkey.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "bigkey.mak" CFG="bigkey - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bigkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "bigkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/bigkey.exe"
+
+!ELSEIF "$(CFG)" == "bigkey - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/bigkey.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "bigkey - @PLATFORM@ Release"
+# Name "bigkey - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\rsabigexponent\bigkey.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/bigkey.dsw b/bin/tests/system/win32/bigkey.dsw
new file mode 100644
index 0000000..1f54d04
--- /dev/null
+++ b/bin/tests/system/win32/bigkey.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "bigkey"=".\bigkey.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/bigkey.mak.in b/bin/tests/system/win32/bigkey.mak.in
new file mode 100644
index 0000000..5ea956d
--- /dev/null
+++ b/bin/tests/system/win32/bigkey.mak.in
@@ -0,0 +1,346 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on bigkey.dsp
+!IF "$(CFG)" == ""
+CFG=bigkey - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to bigkey - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "bigkey - @PLATFORM@ Release" && "$(CFG)" != "bigkey - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "bigkey.mak" CFG="bigkey - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bigkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "bigkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\bigkey.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\..\Build\Release\bigkey.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\bigkey.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\bigkey.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\bigkey.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\bigkey.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\bigkey.pdb" @MACHINE@ /out:"../../../../Build/Release/bigkey.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\bigkey.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Release\libdns.lib"
+
+"..\..\..\..\Build\Release\bigkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "bigkey - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\bigkey.exe" "$(OUTDIR)\bigkey.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\bigkey.exe" "$(OUTDIR)\bigkey.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\bigkey.obj"
+ -@erase "$(INTDIR)\bigkey.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\bigkey.bsc"
+ -@erase "$(OUTDIR)\bigkey.map"
+ -@erase "$(OUTDIR)\bigkey.pdb"
+ -@erase "..\..\..\..\Build\Debug\bigkey.exe"
+ -@erase "..\..\..\..\Build\Debug\bigkey.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\bigkey.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\bigkey.sbr"
+
+"$(OUTDIR)\bigkey.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\bigkey.pdb" /map:"$(INTDIR)\bigkey.map" /debug @MACHINE@ /out:"../../../../Build/Debug/bigkey.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\bigkey.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Debug\libdns.lib"
+
+"..\..\..\..\Build\Debug\bigkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("bigkey.dep")
+!INCLUDE "bigkey.dep"
+!ELSE
+!MESSAGE Warning: cannot find "bigkey.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release" || "$(CFG)" == "bigkey - @PLATFORM@ Debug"
+SOURCE=..\rsabigexponent\bigkey.c
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release"
+
+
+"$(INTDIR)\bigkey.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "bigkey - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\bigkey.obj" "$(INTDIR)\bigkey.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "bigkey - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "bigkey - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "bigkey - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/bigkey.vcxproj.filters.in b/bin/tests/system/win32/bigkey.vcxproj.filters.in
new file mode 100644
index 0000000..1b592a6
--- /dev/null
+++ b/bin/tests/system/win32/bigkey.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rsabigexponent\bigkey.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/bigkey.vcxproj.in b/bin/tests/system/win32/bigkey.vcxproj.in
new file mode 100644
index 0000000..45bfa4d
--- /dev/null
+++ b/bin/tests/system/win32/bigkey.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{61F9D673-EB5C-47A5-8907-24E034C75EF8}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>bigkey</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rsabigexponent\bigkey.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/bigkey.vcxproj.user b/bin/tests/system/win32/bigkey.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/bigkey.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/feature-test.dsp.in b/bin/tests/system/win32/feature-test.dsp.in
new file mode 100644
index 0000000..4c9136c
--- /dev/null
+++ b/bin/tests/system/win32/feature-test.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="feature-test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=feature-test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "feature-test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "feature-test.mak" CFG="feature-test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "feature-test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "feature-test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "feature-test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/feature-test.exe"
+
+!ELSEIF "$(CFG)" == "feature-test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/feature-test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "feature-test - @PLATFORM@ Release"
+# Name "feature-test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\feature-test.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/feature-test.dsw b/bin/tests/system/win32/feature-test.dsw
new file mode 100644
index 0000000..142a073
--- /dev/null
+++ b/bin/tests/system/win32/feature-test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "feature-test"=".\feature-test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/feature-test.mak.in b/bin/tests/system/win32/feature-test.mak.in
new file mode 100644
index 0000000..33ac54f
--- /dev/null
+++ b/bin/tests/system/win32/feature-test.mak.in
@@ -0,0 +1,318 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on feature-test.dsp
+!IF "$(CFG)" == ""
+CFG=feature-test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to feature-test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "feature-test - @PLATFORM@ Release" && "$(CFG)" != "feature-test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "feature-test.mak" CFG="feature-test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "feature-test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "feature-test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "feature-test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "feature-test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\feature-test.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "..\..\..\..\Build\Release\feature-test.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\feature-test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\feature-test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\feature-test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\feature-test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib $(LIBXML) /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\feature-test.pdb" @MACHINE@ /out:"../../../../Build/Release/feature-test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\feature-test.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib"
+
+"..\..\..\..\Build\Release\feature-test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "feature-test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\feature-test.exe" "$(OUTDIR)\feature-test.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\feature-test.exe" "$(OUTDIR)\feature-test.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\feature-test.obj"
+ -@erase "$(INTDIR)\feature-test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\feature-test.bsc"
+ -@erase "$(OUTDIR)\feature-test.map"
+ -@erase "$(OUTDIR)\feature-test.pdb"
+ -@erase "..\..\..\..\Build\Debug\feature-test.exe"
+ -@erase "..\..\..\..\Build\Debug\feature-test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\feature-test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\feature-test.sbr"
+
+"$(OUTDIR)\feature-test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib $(LIBXML) /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\feature-test.pdb" /map:"$(INTDIR)\feature-test.map" /debug @MACHINE@ /out:"../../../../Build/Debug/feature-test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\feature-test.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib"
+
+"..\..\..\..\Build\Debug\feature-test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("feature-test.dep")
+!INCLUDE "feature-test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "feature-test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "feature-test - @PLATFORM@ Release" || "$(CFG)" == "feature-test - @PLATFORM@ Debug"
+SOURCE=..\feature-test.c
+
+!IF "$(CFG)" == "feature-test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\feature-test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "feature-test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\feature-test.obj" "$(INTDIR)\feature-test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "feature-test - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "feature-test - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/feature-test.vcxproj.filters.in b/bin/tests/system/win32/feature-test.vcxproj.filters.in
new file mode 100644
index 0000000..0e4fe58
--- /dev/null
+++ b/bin/tests/system/win32/feature-test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\feature-test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/feature-test.vcxproj.in b/bin/tests/system/win32/feature-test.vcxproj.in
new file mode 100644
index 0000000..eb051e8
--- /dev/null
+++ b/bin/tests/system/win32/feature-test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{63A921F6-1200-4723-828A-98960127B73D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>feature-test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\feature-test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/feature-test.vcxproj.user b/bin/tests/system/win32/feature-test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/feature-test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/gencheck.dsp.in b/bin/tests/system/win32/gencheck.dsp.in
new file mode 100644
index 0000000..8e8005f
--- /dev/null
+++ b/bin/tests/system/win32/gencheck.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="gencheck" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=gencheck - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gencheck.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gencheck.mak" CFG="gencheck - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gencheck - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "gencheck - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gencheck - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/gencheck.exe"
+
+!ELSEIF "$(CFG)" == "gencheck - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/gencheck.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "gencheck - @PLATFORM@ Release"
+# Name "gencheck - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\rndc\gencheck.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/gencheck.dsw b/bin/tests/system/win32/gencheck.dsw
new file mode 100644
index 0000000..32f6007
--- /dev/null
+++ b/bin/tests/system/win32/gencheck.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gencheck"=".\gencheck.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/gencheck.mak.in b/bin/tests/system/win32/gencheck.mak.in
new file mode 100644
index 0000000..016f290
--- /dev/null
+++ b/bin/tests/system/win32/gencheck.mak.in
@@ -0,0 +1,318 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on gencheck.dsp
+!IF "$(CFG)" == ""
+CFG=gencheck - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to gencheck - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gencheck - @PLATFORM@ Release" && "$(CFG)" != "gencheck - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gencheck.mak" CFG="gencheck - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gencheck - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "gencheck - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "gencheck - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "gencheck - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\gencheck.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "..\..\..\..\Build\Release\gencheck.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\gencheck.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\gencheck.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\gencheck.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gencheck.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib $(LIBXML) /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\gencheck.pdb" @MACHINE@ /out:"../../../../Build/Release/gencheck.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\gencheck.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib"
+
+"..\..\..\..\Build\Release\gencheck.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "gencheck - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\gencheck.exe" "$(OUTDIR)\gencheck.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\gencheck.exe" "$(OUTDIR)\gencheck.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\gencheck.obj"
+ -@erase "$(INTDIR)\gencheck.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\gencheck.bsc"
+ -@erase "$(OUTDIR)\gencheck.map"
+ -@erase "$(OUTDIR)\gencheck.pdb"
+ -@erase "..\..\..\..\Build\Debug\gencheck.exe"
+ -@erase "..\..\..\..\Build\Debug\gencheck.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gencheck.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\gencheck.sbr"
+
+"$(OUTDIR)\gencheck.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib $(LIBXML) /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\gencheck.pdb" /map:"$(INTDIR)\gencheck.map" /debug @MACHINE@ /out:"../../../../Build/Debug/gencheck.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\gencheck.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib"
+
+"..\..\..\..\Build\Debug\gencheck.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("gencheck.dep")
+!INCLUDE "gencheck.dep"
+!ELSE
+!MESSAGE Warning: cannot find "gencheck.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "gencheck - @PLATFORM@ Release" || "$(CFG)" == "gencheck - @PLATFORM@ Debug"
+SOURCE=..\rndc\gencheck.c
+
+!IF "$(CFG)" == "gencheck - @PLATFORM@ Release"
+
+
+"$(INTDIR)\gencheck.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "gencheck - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\gencheck.obj" "$(INTDIR)\gencheck.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "gencheck - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "gencheck - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/gencheck.vcxproj.filters.in b/bin/tests/system/win32/gencheck.vcxproj.filters.in
new file mode 100644
index 0000000..33431cf
--- /dev/null
+++ b/bin/tests/system/win32/gencheck.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rndc\gencheck.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/gencheck.vcxproj.in b/bin/tests/system/win32/gencheck.vcxproj.in
new file mode 100644
index 0000000..c60f6a9
--- /dev/null
+++ b/bin/tests/system/win32/gencheck.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{764DBE24-C8B3-46E8-BE73-196431353A5D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>gencheck</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rndc\gencheck.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/gencheck.vcxproj.user b/bin/tests/system/win32/gencheck.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/gencheck.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/keycreate.dsp.in b/bin/tests/system/win32/keycreate.dsp.in
new file mode 100644
index 0000000..c83b682
--- /dev/null
+++ b/bin/tests/system/win32/keycreate.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="keycreate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=keycreate - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keycreate.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keycreate.mak" CFG="keycreate - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keycreate - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keycreate - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/keycreate.exe"
+
+!ELSEIF "$(CFG)" == "keycreate - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/keycreate.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keycreate - @PLATFORM@ Release"
+# Name "keycreate - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tkey\keycreate.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/keycreate.dsw b/bin/tests/system/win32/keycreate.dsw
new file mode 100644
index 0000000..0678918
--- /dev/null
+++ b/bin/tests/system/win32/keycreate.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keycreate"=".\keycreate.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/keycreate.mak.in b/bin/tests/system/win32/keycreate.mak.in
new file mode 100644
index 0000000..260d3da
--- /dev/null
+++ b/bin/tests/system/win32/keycreate.mak.in
@@ -0,0 +1,346 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keycreate.dsp
+!IF "$(CFG)" == ""
+CFG=keycreate - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to keycreate - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keycreate - @PLATFORM@ Release" && "$(CFG)" != "keycreate - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keycreate.mak" CFG="keycreate - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keycreate - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keycreate - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\keycreate.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\..\Build\Release\keycreate.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\keycreate.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\keycreate.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keycreate.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keycreate.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\keycreate.pdb" @MACHINE@ /out:"../../../../Build/Release/keycreate.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\keycreate.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Release\libdns.lib"
+
+"..\..\..\..\Build\Release\keycreate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keycreate - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\keycreate.exe" "$(OUTDIR)\keycreate.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\keycreate.exe" "$(OUTDIR)\keycreate.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\keycreate.obj"
+ -@erase "$(INTDIR)\keycreate.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\keycreate.bsc"
+ -@erase "$(OUTDIR)\keycreate.map"
+ -@erase "$(OUTDIR)\keycreate.pdb"
+ -@erase "..\..\..\..\Build\Debug\keycreate.exe"
+ -@erase "..\..\..\..\Build\Debug\keycreate.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keycreate.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\keycreate.sbr"
+
+"$(OUTDIR)\keycreate.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\keycreate.pdb" /map:"$(INTDIR)\keycreate.map" /debug @MACHINE@ /out:"../../../../Build/Debug/keycreate.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\keycreate.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Debug\libdns.lib"
+
+"..\..\..\..\Build\Debug\keycreate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keycreate.dep")
+!INCLUDE "keycreate.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keycreate.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release" || "$(CFG)" == "keycreate - @PLATFORM@ Debug"
+SOURCE=..\tkey\keycreate.c
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release"
+
+
+"$(INTDIR)\keycreate.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keycreate - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\keycreate.obj" "$(INTDIR)\keycreate.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "keycreate - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "keycreate - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "keycreate - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/keycreate.vcxproj.filters.in b/bin/tests/system/win32/keycreate.vcxproj.filters.in
new file mode 100644
index 0000000..09f4c3a
--- /dev/null
+++ b/bin/tests/system/win32/keycreate.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\tkey\keycreate.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/keycreate.vcxproj.in b/bin/tests/system/win32/keycreate.vcxproj.in
new file mode 100644
index 0000000..11eecc1
--- /dev/null
+++ b/bin/tests/system/win32/keycreate.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4F9A0F6F-366D-4483-B131-793832840508}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>keycreate</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\tkey\keycreate.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/keycreate.vcxproj.user b/bin/tests/system/win32/keycreate.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/keycreate.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/keydelete.dsp.in b/bin/tests/system/win32/keydelete.dsp.in
new file mode 100644
index 0000000..277e2fb
--- /dev/null
+++ b/bin/tests/system/win32/keydelete.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="keydelete" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=keydelete - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keydelete.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keydelete.mak" CFG="keydelete - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keydelete - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keydelete - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/keydelete.exe"
+
+!ELSEIF "$(CFG)" == "keydelete - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/keydelete.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keydelete - @PLATFORM@ Release"
+# Name "keydelete - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tkey\keydelete.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/keydelete.dsw b/bin/tests/system/win32/keydelete.dsw
new file mode 100644
index 0000000..f228301
--- /dev/null
+++ b/bin/tests/system/win32/keydelete.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keydelete"=".\keydelete.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/keydelete.mak.in b/bin/tests/system/win32/keydelete.mak.in
new file mode 100644
index 0000000..19e6300
--- /dev/null
+++ b/bin/tests/system/win32/keydelete.mak.in
@@ -0,0 +1,346 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keydelete.dsp
+!IF "$(CFG)" == ""
+CFG=keydelete - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to keydelete - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keydelete - @PLATFORM@ Release" && "$(CFG)" != "keydelete - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keydelete.mak" CFG="keydelete - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keydelete - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "keydelete - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\keydelete.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\..\Build\Release\keydelete.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\keydelete.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\keydelete.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keydelete.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keydelete.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\keydelete.pdb" @MACHINE@ /out:"../../../../Build/Release/keydelete.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\keydelete.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Release\libdns.lib"
+
+"..\..\..\..\Build\Release\keydelete.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keydelete - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\keydelete.exe" "$(OUTDIR)\keydelete.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\keydelete.exe" "$(OUTDIR)\keydelete.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\keydelete.obj"
+ -@erase "$(INTDIR)\keydelete.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\keydelete.bsc"
+ -@erase "$(OUTDIR)\keydelete.map"
+ -@erase "$(OUTDIR)\keydelete.pdb"
+ -@erase "..\..\..\..\Build\Debug\keydelete.exe"
+ -@erase "..\..\..\..\Build\Debug\keydelete.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keydelete.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\keydelete.sbr"
+
+"$(OUTDIR)\keydelete.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\keydelete.pdb" /map:"$(INTDIR)\keydelete.map" /debug @MACHINE@ /out:"../../../../Build/Debug/keydelete.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\keydelete.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Debug\libdns.lib"
+
+"..\..\..\..\Build\Debug\keydelete.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keydelete.dep")
+!INCLUDE "keydelete.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keydelete.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release" || "$(CFG)" == "keydelete - @PLATFORM@ Debug"
+SOURCE=..\tkey\keydelete.c
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release"
+
+
+"$(INTDIR)\keydelete.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keydelete - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\keydelete.obj" "$(INTDIR)\keydelete.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "keydelete - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "keydelete - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "keydelete - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/keydelete.vcxproj.filters.in b/bin/tests/system/win32/keydelete.vcxproj.filters.in
new file mode 100644
index 0000000..1e8cb3d
--- /dev/null
+++ b/bin/tests/system/win32/keydelete.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\tkey\keydelete.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/keydelete.vcxproj.in b/bin/tests/system/win32/keydelete.vcxproj.in
new file mode 100644
index 0000000..878ef8d
--- /dev/null
+++ b/bin/tests/system/win32/keydelete.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{85ADFF2A-BE31-4B8D-9089-9AD56CE78D7E}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>keydelete</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\tkey\keydelete.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/keydelete.vcxproj.user b/bin/tests/system/win32/keydelete.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/keydelete.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/lwtest.dsp.in b/bin/tests/system/win32/lwtest.dsp.in
new file mode 100644
index 0000000..2facc34
--- /dev/null
+++ b/bin/tests/system/win32/lwtest.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="lwtest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=lwtest - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "lwtest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "lwtest.mak" CFG="lwtest - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "lwtest - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "lwtest - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/lwres/win32/include" /I "../../../../lib/lwres/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/lwtest.exe"
+
+!ELSEIF "$(CFG)" == "lwtest - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/lwres/win32/include" /I "../../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/lwtest.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "lwtest - @PLATFORM@ Release"
+# Name "lwtest - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\lwresd\lwtest.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/lwtest.dsw b/bin/tests/system/win32/lwtest.dsw
new file mode 100644
index 0000000..8442db4
--- /dev/null
+++ b/bin/tests/system/win32/lwtest.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "lwtest"=".\lwtest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/lwtest.mak.in b/bin/tests/system/win32/lwtest.mak.in
new file mode 100644
index 0000000..1e31f41
--- /dev/null
+++ b/bin/tests/system/win32/lwtest.mak.in
@@ -0,0 +1,346 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on lwtest.dsp
+!IF "$(CFG)" == ""
+CFG=lwtest - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to lwtest - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "lwtest - @PLATFORM@ Release" && "$(CFG)" != "lwtest - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "lwtest.mak" CFG="lwtest - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "lwtest - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "lwtest - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\lwtest.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" "..\..\..\..\Build\Release\lwtest.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"liblwres - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\lwtest.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\lwtest.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/lwres/win32/include" /I "../../../../lib/lwres/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\lwtest.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\lwtest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/lwres/win32/Release/liblwres.lib $(LIBXML) /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\lwtest.pdb" @MACHINE@ /out:"../../../../Build/Release/lwtest.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\lwtest.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\..\Build\Release\lwtest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "lwtest - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\lwtest.exe" "$(OUTDIR)\lwtest.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\lwtest.exe" "$(OUTDIR)\lwtest.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\lwtest.obj"
+ -@erase "$(INTDIR)\lwtest.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\lwtest.bsc"
+ -@erase "$(OUTDIR)\lwtest.map"
+ -@erase "$(OUTDIR)\lwtest.pdb"
+ -@erase "..\..\..\..\Build\Debug\lwtest.exe"
+ -@erase "..\..\..\..\Build\Debug\lwtest.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/lwres/win32/include" /I "../../../../lib/lwres/include"/D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\lwtest.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\lwtest.sbr"
+
+"$(OUTDIR)\lwtest.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/lwres/win32/Debug/liblwres.lib $(LIBXML) /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\lwtest.pdb" /map:"$(INTDIR)\lwtest.map" /debug @MACHINE@ /out:"../../../../Build/Debug/lwtest.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\lwtest.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\..\Build\Debug\lwtest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("lwtest.dep")
+!INCLUDE "lwtest.dep"
+!ELSE
+!MESSAGE Warning: cannot find "lwtest.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release" || "$(CFG)" == "lwtest - @PLATFORM@ Debug"
+SOURCE=..\lwresd\lwtest.c
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lwtest.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "lwtest - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lwtest.obj" "$(INTDIR)\lwtest.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "lwtest - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "lwtest - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "lwtest - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/lwtest.vcxproj.filters.in b/bin/tests/system/win32/lwtest.vcxproj.filters.in
new file mode 100644
index 0000000..b50ca14
--- /dev/null
+++ b/bin/tests/system/win32/lwtest.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\lwresd\lwtest.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/lwtest.vcxproj.in b/bin/tests/system/win32/lwtest.vcxproj.in
new file mode 100644
index 0000000..4a32dfc
--- /dev/null
+++ b/bin/tests/system/win32/lwtest.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5D7D17B1-18A2-4468-BC26-D9F9800E76D2}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>lwtest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\lwres\win32\include;..\..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@libisc.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\lwres\win32\include;..\..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@libisc.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\lwresd\lwtest.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/lwtest.vcxproj.user b/bin/tests/system/win32/lwtest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/lwtest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/pipequeries.dsp.in b/bin/tests/system/win32/pipequeries.dsp.in
new file mode 100644
index 0000000..6d63416
--- /dev/null
+++ b/bin/tests/system/win32/pipequeries.dsp.in
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="pipequeries" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=pipequeries - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pipequeries.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pipequeries.mak" CFG="pipequeries - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pipequeries - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pipequeries - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/pipequeries.exe"
+
+!ELSEIF "$(CFG)" == "pipequeries - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/pipequeries.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pipequeries - @PLATFORM@ Release"
+# Name "pipequeries - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\pipelined\pipequeries.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/system/win32/pipequeries.dsw b/bin/tests/system/win32/pipequeries.dsw
new file mode 100644
index 0000000..6dcf30f
--- /dev/null
+++ b/bin/tests/system/win32/pipequeries.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "pipequeries"=".\pipequeries.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/system/win32/pipequeries.mak.in b/bin/tests/system/win32/pipequeries.mak.in
new file mode 100644
index 0000000..3f11a32
--- /dev/null
+++ b/bin/tests/system/win32/pipequeries.mak.in
@@ -0,0 +1,346 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on pipequeries.dsp
+!IF "$(CFG)" == ""
+CFG=pipequeries - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to pipequeries - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "pipequeries - @PLATFORM@ Release" && "$(CFG)" != "pipequeries - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pipequeries.mak" CFG="pipequeries - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pipequeries - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "pipequeries - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Release\pipequeries.exe"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\..\Build\Release\pipequeries.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\pipequeries.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\..\Build\Release\pipequeries.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\pipequeries.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pipequeries.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pipequeries.pdb" @MACHINE@ /out:"../../../../Build/Release/pipequeries.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\pipequeries.obj" \
+ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Release\libdns.lib"
+
+"..\..\..\..\Build\Release\pipequeries.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "pipequeries - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\..\Build\Debug\pipequeries.exe" "$(OUTDIR)\pipequeries.bsc"
+
+!ELSE
+
+ALL : "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\pipequeries.exe" "$(OUTDIR)\pipequeries.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\pipequeries.obj"
+ -@erase "$(INTDIR)\pipequeries.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\pipequeries.bsc"
+ -@erase "$(OUTDIR)\pipequeries.map"
+ -@erase "$(OUTDIR)\pipequeries.pdb"
+ -@erase "..\..\..\..\Build\Debug\pipequeries.exe"
+ -@erase "..\..\..\..\Build\Debug\pipequeries.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\pipequeries.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\pipequeries.sbr"
+
+"$(OUTDIR)\pipequeries.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib $(LIBXML) @OPENSSL_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pipequeries.pdb" /map:"$(INTDIR)\pipequeries.map" /debug @MACHINE@ /out:"../../../../Build/Debug/pipequeries.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\pipequeries.obj" \
+ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\..\lib\isc\win32\Debug\libdns.lib"
+
+"..\..\..\..\Build\Debug\pipequeries.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("pipequeries.dep")
+!INCLUDE "pipequeries.dep"
+!ELSE
+!MESSAGE Warning: cannot find "pipequeries.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release" || "$(CFG)" == "pipequeries - @PLATFORM@ Debug"
+SOURCE=..\pipelined\pipequeries.c
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pipequeries.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "pipequeries - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pipequeries.obj" "$(INTDIR)\pipequeries.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "pipequeries - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "pipequeries - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ELSEIF "$(CFG)" == "pipequeries - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\tests\system\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\tests\system\win32"
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/system/win32/pipequeries.vcxproj.filters.in b/bin/tests/system/win32/pipequeries.vcxproj.filters.in
new file mode 100644
index 0000000..62374cd
--- /dev/null
+++ b/bin/tests/system/win32/pipequeries.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pipelined\pipequeries.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/system/win32/pipequeries.vcxproj.in b/bin/tests/system/win32/pipequeries.vcxproj.in
new file mode 100644
index 0000000..2e06b46
--- /dev/null
+++ b/bin/tests/system/win32/pipequeries.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E1478F40-786C-4738-8E99-E7A71DD98661}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>pipequeries</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\pipelined\pipequeries.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/system/win32/pipequeries.vcxproj.user b/bin/tests/system/win32/pipequeries.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/system/win32/pipequeries.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
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/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/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/clean.sh b/bin/tests/system/xfer/clean.sh
new file mode 100644
index 0000000..aac849b
--- /dev/null
+++ b/bin/tests/system/xfer/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out.*
+rm -f axfr.out
+rm -f ns1/slave.db ns2/slave.db
+rm -f ns1/edns-expire.db
+rm -f ns2/example.db ns2/tsigzone.db ns2/example.db.jnl
+rm -f ns3/example.bk ns3/tsigzone.bk ns3/example.bk.jnl
+rm -f ns3/master.bk ns3/master.bk.jnl
+rm -f ns4/nil.db ns4/root.db
+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 */named.conf
+rm -f */named.run
+rm -f */named.memstats
+rm -f */named.run
+rm -f */ans.run
+rm -f ns*/named.lock
+rm -f ns2/mapped.db
+rm -f ns3/mapped.bk
+rm -f ns1/ixfr-too-big.db ns1/ixfr-too-big.db.jnl
diff --git a/bin/tests/system/xfer/dig1.good b/bin/tests/system/xfer/dig1.good
new file mode 100644
index 0000000..aba6a43
--- /dev/null
+++ b/bin/tests/system/xfer/dig1.good
@@ -0,0 +1,155 @@
+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 .
+apl01.example. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.0/24
+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
+eui48.example. 3600 IN EUI48 01-23-45-67-89-ab
+eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef
+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.
+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.
+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 512 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.
+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\\;"
+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"
+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..40c8c40
--- /dev/null
+++ b/bin/tests/system/xfer/dig2.good
@@ -0,0 +1,155 @@
+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 .
+apl01.example. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.1/24
+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
+eui48.example. 3600 IN EUI48 01-23-45-67-89-ab
+eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef
+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=
+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.
+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 512 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
+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\\;"
+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"
+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/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-too-big.db b/bin/tests/system/xfer/ns1/axfr-too-big.db
new file mode 100644
index 0000000..ff6e4b9
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/axfr-too-big.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/ixfr-too-big.db.in b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in
new file mode 100644
index 0000000..7372793
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/named.conf.in b/bin/tests/system/xfer/ns1/named.conf.in
new file mode 100644
index 0000000..c0e8112
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/named.conf.in
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "slave" {
+ type master;
+ file "slave.db";
+};
+
+zone "edns-expire" {
+ type master;
+ file "edns-expire.db";
+};
+
+zone "axfr-too-big" {
+ type master;
+ file "axfr-too-big.db";
+};
+
+zone "ixfr-too-big" {
+ type master;
+ allow-update { any; };
+ file "ixfr-too-big.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..8aaa4ea
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/root.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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/ns2/mapped.db.in b/bin/tests/system/xfer/ns2/mapped.db.in
new file mode 100644
index 0000000..fc79118
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/mapped.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+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..547a9b0
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ 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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { tzkey; };
+};
+
+zone "slave" {
+ type slave;
+ file "slave.db";
+ masters { 10.53.0.1; };
+ masterfile-format text;
+};
+
+zone "mapped" {
+ type slave;
+ file "mapped.db";
+ masterfile-format text;
+ masters { 10.53.0.100; };
+};
diff --git a/bin/tests/system/xfer/ns2/slave.db.in b/bin/tests/system/xfer/ns2/slave.db.in
new file mode 100644
index 0000000..4ee2094
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/slave.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..1143613
--- /dev/null
+++ b/bin/tests/system/xfer/ns3/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "master" {
+ type slave;
+ masters { 10.53.0.6; };
+ file "master.bk";
+};
+
+server 10.53.0.2 {
+ keys { tsigzone.; };
+};
+
+zone "tsigzone" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "tsigzone.bk";
+ allow-transfer { key tsigzone.; };
+};
+
+zone "mapped" {
+ type slave;
+ masters { 10.53.0.2; };
+ masterfile-format map;
+ file "mapped.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..14a5e05
--- /dev/null
+++ b/bin/tests/system/xfer/ns4/named.conf.base
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+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 master;
+ 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..c675b90
--- /dev/null
+++ b/bin/tests/system/xfer/ns4/root.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
+@ 0 A 10.53.0.4
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..5983f98
--- /dev/null
+++ b/bin/tests/system/xfer/ns6/named.conf.in
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ notify yes;
+ ixfr-from-differences master;
+ check-integrity no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "master" {
+ type master;
+ file "master.db";
+};
+
+zone "slave" {
+ type slave;
+ notify no;
+ masters { 10.53.0.1; };
+ file "slave.bk";
+};
+
+zone "edns-expire" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "edns-expire.bk";
+};
+
+zone "axfr-too-big" {
+ type slave;
+ max-records 30;
+ masters { 10.53.0.1; };
+ file "axfr-too-big.bk";
+};
+
+zone "ixfr-too-big" {
+ type slave;
+ max-records 30;
+ masters { 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..04f1e4e
--- /dev/null
+++ b/bin/tests/system/xfer/ns7/named.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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 yes;
+ ixfr-from-differences slave;
+ check-integrity no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "master2" {
+ type master;
+ file "master2.db";
+};
+
+zone "slave" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "slave.bk";
+};
+
+zone "edns-expire" {
+ type slave;
+ masters { 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..d9a664b
--- /dev/null
+++ b/bin/tests/system/xfer/ns8/example.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..ab6e0c9
--- /dev/null
+++ b/bin/tests/system/xfer/ns8/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ notify no;
+ transfer-message-size 1024;
+};
+
+key key1. {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl tzkey {
+ key key1.;
+};
+
+zone "example." {
+ type master;
+ 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..b8982d6
--- /dev/null
+++ b/bin/tests/system/xfer/prereq.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION >= 0.69 && $Net::DNS::VERSION <= 0.74);' 2>/dev/null
+ then
+ :
+ else
+ echo_i "Net::DNS versions 0.69 to 0.74 have bugs that cause this test to fail: please update." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh
new file mode 100644
index 0000000..19fed32
--- /dev/null
+++ b/bin/tests/system/xfer/setup.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+$SHELL ../genzone.sh 1 6 7 >ns1/slave.db
+$SHELL ../genzone.sh 1 6 7 >ns1/edns-expire.db
+$SHELL ../genzone.sh 2 3 >ns2/example.db
+$SHELL ../genzone.sh 2 3 >ns2/tsigzone.db
+$SHELL ../genzone.sh 6 3 >ns6/master.db
+$SHELL ../genzone.sh 7 >ns7/master2.db
+
+rm -f ns4/*.db ns4/*.jnl
+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/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 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 ns2/slave.db.in ns2/slave.db
+touch -t 200101010000 ns2/slave.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..91b23b3
--- /dev/null
+++ b/bin/tests/system/xfer/tests.sh
@@ -0,0 +1,468 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "testing basic zone transfer functionality"
+$DIG $DIGOPTS example. \
+ @10.53.0.2 axfr > dig.out.ns2 || status=1
+grep "^;" dig.out.ns2 | cat_i
+
+#
+# Spin to allow the zone to tranfer.
+#
+for i in 1 2 3 4 5
+do
+tmp=0
+$DIG $DIGOPTS example. \
+ @10.53.0.3 axfr > dig.out.ns3 || tmp=1
+ grep "^;" dig.out.ns3 > /dev/null
+ if test $? -ne 0 ; then break; fi
+ echo_i "plain zone re-transfer"
+ sleep 5
+done
+if test $tmp -eq 1 ; then status=1; fi
+grep "^;" dig.out.ns3 | cat_i
+
+digcomp dig1.good dig.out.ns2 || status=1
+
+digcomp dig1.good dig.out.ns3 || status=1
+
+n=`expr $n + 1`
+echo_i "testing TSIG signed zone transfers"
+$DIG $DIGOPTS tsigzone. @10.53.0.2 axfr -y tsigzone.:1234abcd8765 > dig.out.ns2 || status=1
+grep "^;" dig.out.ns2 | cat_i
+
+#
+# Spin to allow the zone to tranfer.
+#
+for i in 1 2 3 4 5
+do
+tmp=0
+ $DIG $DIGOPTS tsigzone. @10.53.0.3 axfr -y tsigzone.:1234abcd8765 > dig.out.ns3 || tmp=1
+ grep "^;" dig.out.ns3 > /dev/null
+ if test $? -ne 0 ; then break; fi
+ echo_i "plain zone re-transfer"
+ sleep 5
+done
+if test $tmp -eq 1 ; then status=1; fi
+grep "^;" dig.out.ns3 | cat_i
+
+digcomp dig.out.ns2 dig.out.ns3 || status=1
+
+echo_i "reload servers for in preparation for ixfr-from-differences tests"
+
+$RNDCCMD 10.53.0.1 reload 2>&1 | sed 's/^/ns1 /' | cat_i
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+$RNDCCMD 10.53.0.3 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+$RNDCCMD 10.53.0.6 reload 2>&1 | sed 's/^/ns6 /' | cat_i
+$RNDCCMD 10.53.0.7 reload 2>&1 | sed 's/^/ns7 /' | cat_i
+
+sleep 2
+
+echo_i "updating master zones for ixfr-from-differences tests"
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns1/slave.db
+
+$RNDCCMD 10.53.0.1 reload 2>&1 | sed 's/^/ns1 /' | cat_i
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns2/example.db
+
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns6/master.db
+
+$RNDCCMD 10.53.0.6 reload 2>&1 | sed 's/^/ns6 /' | cat_i
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns7/master2.db
+
+$RNDCCMD 10.53.0.7 reload 2>&1 | sed 's/^/ns7 /' | cat_i
+
+sleep 3
+
+echo_i "testing zone is dumped after successful transfer"
+$DIG $DIGOPTS +noall +answer +multi @10.53.0.2 \
+ slave. soa > dig.out.ns2 || tmp=1
+grep "1397051952 ; serial" dig.out.ns2 > /dev/null 2>&1 || tmp=1
+grep "1397051952 ; serial" ns2/slave.db > /dev/null 2>&1 || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+n=`expr $n + 1`
+echo_i "testing ixfr-from-differences yes;"
+tmp=0
+
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ a=0 b=0 c=0 d=0
+ echo_i "wait for reloads..."
+ $DIG $DIGOPTS @10.53.0.6 +noall +answer soa master > dig.out.soa1.ns6
+ grep "1397051953" dig.out.soa1.ns6 > /dev/null && a=1
+ $DIG $DIGOPTS @10.53.0.1 +noall +answer soa slave > dig.out.soa2.ns1
+ grep "1397051953" dig.out.soa2.ns1 > /dev/null && b=1
+ $DIG $DIGOPTS @10.53.0.2 +noall +answer soa example > dig.out.soa3.ns2
+ grep "1397051953" dig.out.soa3.ns2 > /dev/null && c=1
+ [ $a -eq 1 -a $b -eq 1 -a $c -eq 1 ] && break
+ sleep 2
+done
+
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ a=0 b=0 c=0 d=0
+ echo_i "wait for transfers..."
+ $DIG $DIGOPTS @10.53.0.3 +noall +answer soa example > dig.out.soa1.ns3
+ grep "1397051953" dig.out.soa1.ns3 > /dev/null && a=1
+ $DIG $DIGOPTS @10.53.0.3 +noall +answer soa master > dig.out.soa2.ns3
+ grep "1397051953" dig.out.soa2.ns3 > /dev/null && b=1
+ $DIG $DIGOPTS @10.53.0.6 +noall +answer soa slave > dig.out.soa3.ns6
+ grep "1397051953" dig.out.soa3.ns6 > /dev/null && c=1
+ [ $a -eq 1 -a $b -eq 1 -a $c -eq 1 ] && break
+
+ # re-notify if necessary
+ $RNDCCMD 10.53.0.6 notify master 2>&1 | sed 's/^/ns6 /' | cat_i
+ $RNDCCMD 10.53.0.1 notify slave 2>&1 | sed 's/^/ns1 /' | cat_i
+ $RNDCCMD 10.53.0.2 notify example 2>&1 | sed 's/^/ns2 /' | cat_i
+ sleep 2
+done
+
+$DIG $DIGOPTS example. \
+ @10.53.0.3 axfr > dig.out.ns3 || tmp=1
+grep "^;" dig.out.ns3 | cat_i
+
+digcomp dig2.good dig.out.ns3 || 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=`expr $status + $tmp`
+
+n=`expr $n + 1`
+echo_i "testing ixfr-from-differences master; (master zone)"
+tmp=0
+
+$DIG $DIGOPTS master. \
+ @10.53.0.6 axfr > dig.out.ns6 || tmp=1
+grep "^;" dig.out.ns6 | cat_i
+
+$DIG $DIGOPTS master. \
+ @10.53.0.3 axfr > dig.out.ns3 || tmp=1
+grep "^;" dig.out.ns3 > /dev/null && cat_i dig.out.ns3
+
+digcomp dig.out.ns6 dig.out.ns3 || tmp=1
+
+# ns3 has a journal iff it received an IXFR.
+test -f ns3/master.bk || tmp=1
+test -f ns3/master.bk.jnl || tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+n=`expr $n + 1`
+echo_i "testing ixfr-from-differences master; (slave zone)"
+tmp=0
+
+$DIG $DIGOPTS slave. \
+ @10.53.0.6 axfr > dig.out.ns6 || tmp=1
+grep "^;" dig.out.ns6 | cat_i
+
+$DIG $DIGOPTS slave. \
+ @10.53.0.1 axfr > dig.out.ns1 || tmp=1
+grep "^;" dig.out.ns1 | cat_i
+
+digcomp dig.out.ns6 dig.out.ns1 || tmp=1
+
+# ns6 has a journal iff it received an IXFR.
+test -f ns6/slave.bk || tmp=1
+test -f ns6/slave.bk.jnl && tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+n=`expr $n + 1`
+echo_i "testing ixfr-from-differences slave; (master zone)"
+tmp=0
+
+# ns7 has a journal iff it generates an IXFR.
+test -f ns7/master2.db || tmp=1
+test -f ns7/master2.db.jnl && tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+n=`expr $n + 1`
+echo_i "testing ixfr-from-differences slave; (slave zone)"
+tmp=0
+
+$DIG $DIGOPTS slave. \
+ @10.53.0.1 axfr > dig.out.ns1 || tmp=1
+grep "^;" dig.out.ns1 | cat_i
+
+$DIG $DIGOPTS slave. \
+ @10.53.0.7 axfr > dig.out.ns7 || tmp=1
+grep "^;" dig.out.ns1 | cat_i
+
+digcomp dig.out.ns7 dig.out.ns1 || tmp=1
+
+# ns7 has a journal iff it generates an IXFR.
+test -f ns7/slave.bk || tmp=1
+test -f ns7/slave.bk.jnl || tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+echo_i "check that a multi-message uncompressable zone transfers"
+$DIG axfr . -p ${PORT} @10.53.0.4 | grep SOA > axfr.out
+if test `wc -l < axfr.out` != 2
+then
+ echo_i "failed"
+ status=`expr $status + 1`
+fi
+
+# now we test transfers with assorted TSIG glitches
+DIGCMD="$DIG $DIGOPTS @10.53.0.4"
+SENDCMD="$PERL ../send.pl 10.53.0.5 $EXTRAPORT1"
+
+echo_i "testing that incorrectly signed transfers will fail..."
+echo_i "initial correctly-signed transfer should succeed"
+
+$SENDCMD < ans5/goodaxfr
+sleep 1
+
+# Initially, ns4 is not authoritative for anything.
+# Now that ans is up and running with the right data, we make ns4
+# a slave for nil.
+
+cat <<EOF >>ns4/named.conf
+zone "nil" {
+ type slave;
+ file "nil.db";
+ masters { 10.53.0.5 key tsig_key; };
+};
+EOF
+
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$RNDCCMD 10.53.0.4 reload | sed 's/^/ns4 /' | cat_i
+
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIGCMD nil. SOA > dig.out.ns4
+ grep SOA dig.out.ns4 > /dev/null && break
+ sleep 1
+done
+
+sed -n "$cur,\$p" < ns4/named.run | grep "Transfer status: success" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=1
+}
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$DIGCMD nil. TXT | grep 'initial AXFR' >/dev/null || {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "unsigned transfer"
+
+$SENDCMD < ans5/unsigned
+sleep 1
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+sed -n "$cur,\$p" < ns4/named.run | grep "Transfer status: expected a TSIG or SIG(0)" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=1
+}
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$DIGCMD nil. TXT | grep 'unsigned AXFR' >/dev/null && {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "bad keydata"
+
+$SENDCMD < ans5/badkeydata
+sleep 1
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+sed -n "$cur,\$p" < ns4/named.run | grep "Transfer status: tsig verify failure" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=1
+}
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$DIGCMD nil. TXT | grep 'bad keydata AXFR' >/dev/null && {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "partially-signed transfer"
+
+$SENDCMD < ans5/partial
+sleep 1
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+sed -n "$cur,\$p" < ns4/named.run | grep "Transfer status: expected a TSIG or SIG(0)" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=1
+}
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$DIGCMD nil. TXT | grep 'partially signed AXFR' >/dev/null && {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "unknown key"
+
+$SENDCMD < ans5/unknownkey
+sleep 1
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+sed -n "$cur,\$p" < 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=1
+}
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$DIGCMD nil. TXT | grep 'unknown key AXFR' >/dev/null && {
+ echo_i "failed"
+ status=1
+}
+
+echo_i "incorrect key"
+
+$SENDCMD < ans5/wrongkey
+sleep 1
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+sed -n "$cur,\$p" < 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=1
+}
+cur=`awk 'END {print NR}' ns4/named.run`
+
+$DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && {
+ echo_i "failed"
+ status=1
+}
+
+n=`expr $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=1
+}
+
+n=`expr $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 || status=1
+
+$DOS2UNIX dig.out.msgsize >/dev/null
+
+bytes=`wc -c < dig.out.msgsize`
+if [ $bytes -ne 459357 ]; then
+ echo_i "failed axfr size check"
+ 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=1
+fi
+
+n=`expr $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.$n
+grep "status: NOERROR," dig.out.1.$n > /dev/null || tmp=1
+$PERL $SYSTEMTESTTOP/stop.pl . ns3
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} . ns3
+$DIG -p ${PORT} txt mapped @10.53.0.3 > dig.out.2.$n
+grep "status: NOERROR," dig.out.2.$n > /dev/null || tmp=1
+$DIG -p ${PORT} axfr mapped @10.53.0.3 > dig.out.3.$n
+digcomp knowngood.mapped dig.out.3.$n || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+n=`expr $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=`expr $status + $tmp`
+
+n=`expr $n + 1`
+echo_i "test that a zone with too many records is rejected (IXFR) ($n)"
+tmp=0
+grep "'ixfr-too-big./IN.*: too many records" ns6/named.run >/dev/null && tmp=1
+$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
+for i in 1 2 3 4 5 6 7 8
+do
+ grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null && break
+ sleep 1
+done
+grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=`expr $status + $tmp`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/xferquota/clean.sh b/bin/tests/system/xferquota/clean.sh
new file mode 100644
index 0000000..e823c91
--- /dev/null
+++ b/bin/tests/system/xferquota/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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
diff --git a/bin/tests/system/xferquota/ns1/changing1.db b/bin/tests/system/xferquota/ns1/changing1.db
new file mode 100644
index 0000000..f103492
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/changing1.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..9afaf71
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/changing2.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..290778e
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "changing." {
+ type master;
+ 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..91692f7
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/root.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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..e47efcb
--- /dev/null
+++ b/bin/tests/system/xferquota/ns2/example.db
@@ -0,0 +1,144 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$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..8b68164
--- /dev/null
+++ b/bin/tests/system/xferquota/ns2/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+
+ transfers-in 5;
+ transfers-per-ns 5;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "changing." {
+ type slave;
+ masters { 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..6acbb73
--- /dev/null
+++ b/bin/tests/system/xferquota/setup.pl
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up test data for zone transfer quota tests.
+#
+use FileHandle;
+
+my $masterconf = new FileHandle("ns1/zones.conf", "w") or die;
+my $slaveconf = new FileHandle("ns2/zones.conf", "w") or die;
+
+for ($z = 0; $z < 300; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ print $masterconf "zone \"$zn\" { type master; file \"$zn.db\"; };\n";
+ print $slaveconf "zone \"$zn\" { type slave; file \"$zn.bk\"; masterfile-format text; masters { 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..5d41899
--- /dev/null
+++ b/bin/tests/system/xferquota/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up test data for zone transfer quota tests.
+#
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.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..0fbc114
--- /dev/null
+++ b/bin/tests/system/xferquota/tests.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/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
+ if [ ! "$CYGWIN" ]; then
+ $KILL -HUP `cat ns1/named.pid`
+ else
+ $RNDCCMD 10.53.0.1 reload > /dev/null 2>&1
+ fi
+ fi
+ sleep 1
+ ticks=`expr $ticks + 1`
+ seconds=`expr $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/zero/ans5/ans.pl b/bin/tests/system/zero/ans5/ans.pl
new file mode 100644
index 0000000..6f81e7c
--- /dev/null
+++ b/bin/tests/system/zero/ans5/ans.pl
@@ -0,0 +1,79 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# 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..00fc10a
--- /dev/null
+++ b/bin/tests/system/zero/clean.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */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
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..9731fdf
--- /dev/null
+++ b/bin/tests/system/zero/ns1/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+};
+
+zone "." {
+ type master;
+ 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..c20b5fc
--- /dev/null
+++ b/bin/tests/system/zero/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.conf.in b/bin/tests/system/zero/ns2/named.conf.in
new file mode 100644
index 0000000..b764a96
--- /dev/null
+++ b/bin/tests/system/zero/ns2/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+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;
+ acache-enable yes;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tld" {
+ type master;
+ 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..11b5b13
--- /dev/null
+++ b/bin/tests/system/zero/ns2/tld.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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.conf.in b/bin/tests/system/zero/ns3/named.conf.in
new file mode 100644
index 0000000..613af5d
--- /dev/null
+++ b/bin/tests/system/zero/ns3/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+};
+
+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..c1784c7
--- /dev/null
+++ b/bin/tests/system/zero/ns3/root.hint
@@ -0,0 +1,11 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1.
+ns1. A 10.53.0.1
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..c88881e
--- /dev/null
+++ b/bin/tests/system/zero/ns4/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ acache-enable yes;
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "one.tld" {
+ type master;
+ 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..7706e44
--- /dev/null
+++ b/bin/tests/system/zero/ns4/one.tld.db
@@ -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 http://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/prereq.sh b/bin/tests/system/zero/prereq.sh
new file mode 100644
index 0000000..de147a4
--- /dev/null
+++ b/bin/tests/system/zero/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/zero/setup.sh b/bin/tests/system/zero/setup.sh
new file mode 100644
index 0000000..27b8ba7
--- /dev/null
+++ b/bin/tests/system/zero/setup.sh
@@ -0,0 +1,20 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports 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 ../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..73c277c
--- /dev/null
+++ b/bin/tests/system/zero/tests.sh
@@ -0,0 +1,89 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+n=0
+
+n=`expr $n + 1`
+echo_i "check lookups against TTL=0 records ($n)"
+i=0
+passes=10
+$DIG $DIGOPTS @10.53.0.2 axfr example | grep -v "^ds0" |
+awk '$2 == "0" { print "-q", $1, $4; print "-q", "zzz"$1, $4;}' > query.list
+while [ $i -lt $passes ]
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 -f query.list > dig.out$i.1.test$n &
+ $DIG $DIGOPTS @10.53.0.3 -f query.list > dig.out$i.2.test$n &
+ $DIG $DIGOPTS @10.53.0.3 -f query.list > dig.out$i.3.test$n &
+ $DIG $DIGOPTS @10.53.0.3 -f query.list > dig.out$i.4.test$n &
+ $DIG $DIGOPTS @10.53.0.3 -f query.list > dig.out$i.5.test$n &
+ $DIG $DIGOPTS @10.53.0.3 -f query.list > dig.out$i.6.test$n &
+ wait
+ grep "status: SERVFAIL" dig.out$i.1.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.2.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.3.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.4.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.5.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.6.test$n && ret=1
+ [ $ret = 1 ] && break
+ i=`expr $i + 1`
+ echo_i "successfully completed pass $i of $passes"
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check repeated recursive lookups of non recurring TTL=0 responses get new values ($n)"
+count=`(
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+$DIG $DIGOPTS +short @10.53.0.3 foo.increment
+) | sort -u | wc -l `
+if [ $count -ne 7 ] ; then echo_i "failed (count=$count)"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check lookups against TTL=1 records ($n)"
+i=0
+passes=10
+while [ $i -lt $passes ]
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 www.one.tld > dig.out$i.1.test$n
+ $DIG $DIGOPTS @10.53.0.3 www.one.tld > dig.out$i.2.test$n
+ $DIG $DIGOPTS @10.53.0.3 www.one.tld > dig.out$i.3.test$n
+ $DIG $DIGOPTS @10.53.0.3 www.one.tld > dig.out$i.4.test$n
+ $DIG $DIGOPTS @10.53.0.3 www.one.tld > dig.out$i.5.test$n
+ $DIG $DIGOPTS @10.53.0.3 www.one.tld > dig.out$i.6.test$n
+ grep "status: SERVFAIL" dig.out$i.1.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.2.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.3.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.4.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.5.test$n && ret=1
+ grep "status: SERVFAIL" dig.out$i.6.test$n && ret=1
+ [ $ret = 1 ] && break
+ i=`expr $i + 1`
+ echo_i "successfully completed pass $i of $passes"
+ $PERL -e 'select(undef, undef, undef, 0.3);'
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/zonechecks/a.db b/bin/tests/system/zonechecks/a.db
new file mode 100644
index 0000000..637d5ed
--- /dev/null
+++ b/bin/tests/system/zonechecks/a.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..9c833a7
--- /dev/null
+++ b/bin/tests/system/zonechecks/aaaa.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..8925fc1
--- /dev/null
+++ b/bin/tests/system/zonechecks/bigserial.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..16cad7a
--- /dev/null
+++ b/bin/tests/system/zonechecks/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f *.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
diff --git a/bin/tests/system/zonechecks/cname.db b/bin/tests/system/zonechecks/cname.db
new file mode 100644
index 0000000..0bd9106
--- /dev/null
+++ b/bin/tests/system/zonechecks/cname.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..a5b4f07
--- /dev/null
+++ b/bin/tests/system/zonechecks/dname.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..4227bd5
--- /dev/null
+++ b/bin/tests/system/zonechecks/noaddress.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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..eacbd5b
--- /dev/null
+++ b/bin/tests/system/zonechecks/ns1/named.conf.in
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view unused {
+ match-clients { none; };
+
+ zone "duplicate.example" {
+ type master;
+ file "duplicate.db";
+ };
+};
+
+view primary {
+ match-clients { any; };
+
+ zone "master.example" {
+ type master;
+ file "master.db";
+ allow-update { any; };
+ allow-transfer { any; };
+ auto-dnssec maintain;
+ };
+
+ zone "bigserial.example" {
+ type master;
+ file "bigserial.db";
+ };
+
+ zone "reload.example" {
+ type master;
+ file "reload.db";
+ };
+
+ zone "duplicate.example" {
+ type master;
+ 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..936d4a4
--- /dev/null
+++ b/bin/tests/system/zonechecks/ns2/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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-enable yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "master.example" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "slave.db";
+};
diff --git a/bin/tests/system/zonechecks/nxdomain.db b/bin/tests/system/zonechecks/nxdomain.db
new file mode 100644
index 0000000..7512e98
--- /dev/null
+++ b/bin/tests/system/zonechecks/nxdomain.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 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/prereq.sh b/bin/tests/system/zonechecks/prereq.sh
new file mode 100644
index 0000000..a0d4e9c
--- /dev/null
+++ b/bin/tests/system/zonechecks/prereq.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+exec $SHELL ../testcrypto.sh
diff --git a/bin/tests/system/zonechecks/setup.sh b/bin/tests/system/zonechecks/setup.sh
new file mode 100644
index 0000000..24d4575
--- /dev/null
+++ b/bin/tests/system/zonechecks/setup.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+
+$SHELL ../genzone.sh 1 > ns1/master.db
+$SHELL ../genzone.sh 1 > ns1/duplicate.db
+cp bigserial.db ns1/
+cd ns1
+touch master.db.signed
+echo '$INCLUDE "master.db.signed"' >> master.db
+$KEYGEN -r $RANDFILE -3q master.example > /dev/null 2>&1
+$KEYGEN -r $RANDFILE -3qfk master.example > /dev/null 2>&1
+$SIGNER -SD -o master.example master.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..fb3b466
--- /dev/null
+++ b/bin/tests/system/zonechecks/tests.sh
@@ -0,0 +1,255 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
+
+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=`expr $status + 1`
+else
+ if grep "is a CNAME" cname.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=`expr $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=`expr $status + 1`
+else
+ if grep "is below a DNAME" dname.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=`expr $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=`expr $status + 1`
+else
+ if grep "has no address records" noaddress.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=`expr $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=`expr $status + 1`
+else
+ if grep "has no address records" noaddress.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=`expr $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=`expr $status + 1`
+else
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=`expr $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=`expr $status + 1`
+ fi
+else
+ echo_i "failed (status)"; status=`expr $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=`expr $status + 1`
+ else
+ :
+ fi
+else
+ echo_i "failed (status)"; status=`expr $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=`expr $status + 1`
+else
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=`expr $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=`expr $status + 1`
+ fi
+else
+ echo_i "failed (status)"; status=`expr $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=`expr $status + 1`
+ else
+ :
+ fi
+else
+ echo_i "failed (status)"; status=`expr $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 master.example > rndc.out.master 2>&1
+ grep "zone not loaded" rndc.out.master > /dev/null || break
+ sleep 1
+done
+checkfor() {
+ grep "$1" $2 > /dev/null || {
+ ret=1;
+ echo_i "missing string '$1' from '$2'"
+ }
+}
+checkfor "name: master.example" rndc.out.master
+checkfor "type: master" rndc.out.master
+checkfor "files: master.db, master.db.signed" rndc.out.master
+checkfor "serial: " rndc.out.master
+checkfor "nodes: " rndc.out.master
+checkfor "last loaded: " rndc.out.master
+checkfor "secure: yes" rndc.out.master
+checkfor "inline signing: no" rndc.out.master
+checkfor "key maintenance: automatic" rndc.out.master
+checkfor "next key event: " rndc.out.master
+checkfor "next resign node: " rndc.out.master
+checkfor "next resign time: " rndc.out.master
+checkfor "dynamic: yes" rndc.out.master
+checkfor "frozen: no" rndc.out.master
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $RNDCCMD 10.53.0.2 zonestatus master.example > rndc.out.slave 2>&1
+ grep "zone not loaded" rndc.out.slave > /dev/null || break
+ sleep 1
+done
+checkfor "name: master.example" rndc.out.slave
+checkfor "type: slave" rndc.out.slave
+checkfor "files: slave.db" rndc.out.slave
+checkfor "serial: " rndc.out.slave
+checkfor "nodes: " rndc.out.slave
+checkfor "next refresh: " rndc.out.slave
+checkfor "expires: " rndc.out.slave
+checkfor "secure: yes" rndc.out.slave
+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
+$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 " 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=`expr $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
+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
+checkfor "name: duplicate.example" rndc.out.duplicate
+$RNDCCMD 10.53.0.1 zonestatus nosuchzone.example > rndc.out.duplicate 2>&1
+checkfor "no matching zone 'nosuchzone.example' in any view" rndc.out.duplicate
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $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=`expr $status + $ret`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/testdata/wire/wire_test.data b/bin/tests/testdata/wire/wire_test.data
new file mode 100644
index 0000000..cbda586
--- /dev/null
+++ b/bin/tests/testdata/wire/wire_test.data
@@ -0,0 +1,9 @@
+000a 8580 0001 0003 0000 0003 # message header
+0376697803636f6d00 0002 0001 # question section: vix.com IN NS
+c00c 0002 0001 00000e10 # vix.com IN NS 3600
+000b 056973727631027061c00c # rdlen=0xb isrv1.pa.vix.com
+c00c 0002 0001 00000e10 0009 066e732d657874c00c
+c00c 0002 0001 00000e10 000e 036e733104676e616303636f6d00
+c025 0001 0001 00000e10 0004 cc98b886
+c03c 0001 0001 00000e10 0004 cc98b840
+c051 0001 0001 0002a14a 0004 c697f8f6
diff --git a/bin/tests/testdata/wire/wire_test.data2 b/bin/tests/testdata/wire/wire_test.data2
new file mode 100644
index 0000000..503eac7
--- /dev/null
+++ b/bin/tests/testdata/wire/wire_test.data2
@@ -0,0 +1,14 @@
+1707 8180
+ 0001 0005 0002 0002 027a 6202 6d78 0361
+ 6f6c 0363 6f6d 0000 0100 01c0 0c00 0100
+ 0100 000b a100 04c6 5110 21c0 0c00 0100
+ 0100 000b a100 04c6 5110 22c0 0c00 0100
+ 0100 000b a100 04c6 5110 23c0 0c00 0100
+ 0100 000b a100 04c6 5110 24c0 0c00 0100
+ 0100 000b a100 04c6 5110 2502 6d78 0341
+ 4f4c 0363 6f6d 0000 0200 0100 000d 9900
+ 0c06 646e 732d 3031 026e 73c0 72c0 6f00
+ 0200 0100 000d 9900 0906 646e 732d 3032
+ c08c c085 0001 0001 0000 0d99 0004 c651
+ 11e8 c09d 0001 0001 0000 0d99 0004 cdbc
+ 9de8
diff --git a/bin/tests/testdata/wire/wire_test.data3 b/bin/tests/testdata/wire/wire_test.data3
new file mode 100644
index 0000000..86a80ab
--- /dev/null
+++ b/bin/tests/testdata/wire/wire_test.data3
@@ -0,0 +1,14 @@
+1706 8180
+ 0001 0005 0002 0002 027a 6102 6d78 0361
+ 6f6c 0363 6f6d 0000 0100 01c0 0c00 0100
+ 0100 000b a100 04c6 5110 05c0 0c00 0100
+ 0100 000b a100 04c6 5110 01c0 0c00 0100
+ 0100 000b a100 04c6 5110 02c0 0c00 0100
+ 0100 000b a100 04c6 5110 03c0 0c00 0100
+ 0100 000b a100 04c6 5110 0402 6d78 0341
+ 4f4c 0363 6f6d 0000 0200 0100 000d 9900
+ 0c06 646e 732d 3031 026e 73c0 72c0 6f00
+ 0200 0100 000d 9900 0906 646e 732d 3032
+ c08c c085 0001 0001 0000 0d99 0004 c651
+ 11e8 c09d 0001 0001 0000 0d99 0004 cdbc
+ 9de8
diff --git a/bin/tests/testdata/wire/wire_test.data4 b/bin/tests/testdata/wire/wire_test.data4
new file mode 100644
index 0000000..b934a60
--- /dev/null
+++ b/bin/tests/testdata/wire/wire_test.data4
@@ -0,0 +1,31 @@
+00068180
+000100070002001103616f6c03636f6d
+00000f0001c00c000f000100000d1b00
+0a000f027a64026d78c00cc00c000f00
+0100000d1b0007000f027962c02ac00c
+000f000100000d1b0007000f027963c0
+2ac00c000f000100000d1b0007000f02
+7964c02ac00c000f000100000d1b0007
+000f027a61c02ac00c000f000100000d
+1b0007000f027a62c02ac00c000f0001
+00000d1b0007000f027a63c02ac00c00
+02000100000d1b000c06444e532d3031
+024e53c00cc00c0002000100000d1b00
+0906444e532d3032c0b4c02700010001
+00000d1c0004c6511062c02700010001
+00000d1c0004c6511063c02700010001
+00000d1c0004c6511064c02700010001
+00000d1c0004c6511065c02700010001
+00000d1c0004c6511061c03d00010001
+00000d1c0004cdbc9c63c03d00010001
+00000d1c0004cdbc9c64c03d00010001
+00000d1c0004cdbc9c65c03d00010001
+00000d1c0004cdbc9c61c03d00010001
+00000d1c0004cdbc9c62c05000010001
+00000d1c0004cdbc9c83c05000010001
+00000d1c0004cdbc9c84c05000010001
+00000d1c0004cdbc9c85c05000010001
+00000d1c0004cdbc9c81c05000010001
+00000d1c0004cdbc9c82c0ad00010001
+00000d1c0004c65111e8c0c500010001
+00000d1c0004cdbc9de8
diff --git a/bin/tests/virtual-time/Makefile.in b/bin/tests/virtual-time/Makefile.in
new file mode 100644
index 0000000..bd51ce9
--- /dev/null
+++ b/bin/tests/virtual-time/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+TARGETS = libvtwrapper.so
+SRCS = vtwrapper.c
+CFLAGS += -fPIC
+LDFLAGS =
+LIBS =
+
+all: libvtwrapper.so
+
+.SUFFIXES: .c .o
+
+.c.o:
+ ${CC} ${CFLAGS} -c $<
+
+libvtwrapper.so: vtwrapper.o
+ ${CC} ${CFLAGS} ${LDFLAGS} -nostdlib -export-dynamic -shared -o $@ vtwrapper.o ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS} *.o
+
+SUBDIRS =
+
+test:
+ if test -f ./runall.sh; then sh ./runall.sh; fi
+
+testclean clean distclean::
+ if test -f ./cleanall.sh; then sh ./cleanall.sh; fi
+
+distclean::
+ rm -f conf.sh
diff --git a/bin/tests/virtual-time/README b/bin/tests/virtual-time/README
new file mode 100644
index 0000000..a58940f
--- /dev/null
+++ b/bin/tests/virtual-time/README
@@ -0,0 +1,18 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This is copied from ../system.
+
+This test suite uses a virtual time, gettimeofday(), select(),
+poll(), kevent() and epoll_wait() Unix system calls are redirected:
+gettimeofday() returns a date in virtual/exponentially inflated
+delay from an epoch, select(), poll(), kevent() and epoll_wait()
+timeouts are deflated down to at least 10ms.
+
+These tests depends on LD_PRELOAD being supported by the runtime
+loader.
+
+Beware BIND clock uses unsigned integer, in 22 seconds isc_time_now()
+overflows and breaks assertions. Note 22 real seconds is 136 virtual
+years...
diff --git a/bin/tests/virtual-time/autosign-ksk/clean.sh b/bin/tests/virtual-time/autosign-ksk/clean.sh
new file mode 100644
index 0000000..5fd766e
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/clean.sh
@@ -0,0 +1,20 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after virtual time tests.
+#
+rm -f */K* */dsset-* */*.signed */*.jnl */tmp*
+rm -f dig.out.*
+rm -f random.data*
+rm -f */named.memstats
+rm -f */*vtwrapper.*
+rm -f ns1/example.db
+rm -f ns1/keyname
+rm -f ns*/named.lock
diff --git a/bin/tests/virtual-time/autosign-ksk/ns1/example.db.in b/bin/tests/virtual-time/autosign-ksk/ns1/example.db.in
new file mode 100644
index 0000000..c61ebd3
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/ns1/example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60 ; 1 mn (to avoid to delay activation with ttl > prepublish)
+@ IN SOA ns root (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 12000 ; expire
+ 600 ; minimum
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
diff --git a/bin/tests/virtual-time/autosign-ksk/ns1/named.conf b/bin/tests/virtual-time/autosign-ksk/ns1/named.conf
new file mode 100644
index 0000000..141ce62
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/ns1/named.conf
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ sig-validity-interval 20;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example." {
+ type master;
+ file "example.db.signed";
+ allow-query { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
diff --git a/bin/tests/virtual-time/autosign-ksk/ns1/root.db b/bin/tests/virtual-time/autosign-ksk/ns1/root.db
new file mode 100644
index 0000000..d2c6cd4
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/ns1/root.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example NS ns.example
+ns.example A 10.53.0.1
+
diff --git a/bin/tests/virtual-time/autosign-ksk/ns1/sign.sh b/bin/tests/virtual-time/autosign-ksk/ns1/sign.sh
new file mode 100644
index 0000000..acccdf0
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/ns1/sign.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data1
+RANDFILE2=../random.data2
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+zskname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+kskname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -f KSK -n zone $zone`
+
+cat $infile $zskname.key $kskname.key > $zonefile
+
+$SIGNER -P -e +1000d -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# ksk
+keyname=`$KEYGEN -q -r $RANDFILE2 -a RSASHA1 -b 1024 -n zone \
+ -f KSK -P +20 -A +1h -R +6h -I +1d -D +1mo $zone`
+
+echo $keyname > keyname
diff --git a/bin/tests/virtual-time/autosign-ksk/ns1/wrap.sh b/bin/tests/virtual-time/autosign-ksk/ns1/wrap.sh
new file mode 100644
index 0000000..9bc15bb
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/ns1/wrap.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Wrapper for named
+#
+
+LD_PRELOAD=../../libvtwrapper.so
+export LD_PRELOAD
+
+exec $*
diff --git a/bin/tests/virtual-time/autosign-ksk/setup.sh b/bin/tests/virtual-time/autosign-ksk/setup.sh
new file mode 100644
index 0000000..85a723a
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+. ./clean.sh
+
+../../../tools/genrandom 800 random.data
+dd if=random.data of=random.data1 bs=1k count=400 2> /dev/null
+dd if=random.data of=random.data2 bs=1k skip=400 2> /dev/null
+
+cd ns1 && sh sign.sh
+
diff --git a/bin/tests/virtual-time/autosign-ksk/tests.sh b/bin/tests/virtual-time/autosign-ksk/tests.sh
new file mode 100644
index 0000000..8588b0f
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-ksk/tests.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+DIGOPTS="+noadd +nosea +nostat +nocmd +noauth +dnssec -p 5300"
+
+ksk=ns1/`cat ns1/keyname`.key
+kskpat=`awk '/DNSKEY/ { print $8 }' $ksk`
+kskid=`sed 's/^Kexample\.+005+0*//' < ns1/keyname`
+rkskid=`expr \( $kskid + 128 \) \% 65536`
+
+echo "I:checking for KSK not yet published ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+tr -d ' ' < dig.out.ns1.test$n | grep $kskpat > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 5s real, 55s virtual, P +20
+sleep 4
+
+echo "I:checking for KSK published but not yet active ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+tr -d ' ' < dig.out.ns1.test$n | grep $kskpat > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep 'RRSIG.*'" $kskid "'example\. ' dig.out.ns1.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 10s real, 2h15mn virtual, A +1h
+sleep 5
+
+echo "I:checking for KSK active ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+tr -d ' ' < dig.out.ns1.test$n | grep $kskpat > /dev/null || ret=1
+grep 'RRSIG.*'" $kskid "'example\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 11s real, 6h7,m virtual, R +6h
+sleep 1
+
+echo "I:checking for KSK revoked ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+tr -d ' ' < dig.out.ns1.test$n | grep $kskpat > /dev/null || ret=1
+awk 'BEGIN { $noksk=1 } \
+/DNSKEY/ { $5==385 && $noksk=0 } \
+END { exit $noksk }' < dig.out.ns1.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep 'RRSIG.*'" $kskid "'example\. ' dig.out.ns1.test$n > /dev/null && ret=1
+grep 'RRSIG.*'" $rkskid "'example\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 13s real, 45h virtual, I +1d
+sleep 2
+
+echo "I:checking for KSK retired but not yet deleted ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+tr -d ' ' < dig.out.ns1.test$n | grep $kskpat > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 17s real, 103d virtual, D +1mo
+sleep 4
+
+echo "I:checking for KSK deleted ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+tr -d ' ' < dig.out.ns1.test$n | grep $kskpat > /dev/null && ret=1
+# Note - this is looking for failure, hence the &&
+grep 'RRSIG.*'" $rkskid "'example\. ' dig.out.ns1.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/virtual-time/autosign-zsk/clean.sh b/bin/tests/virtual-time/autosign-zsk/clean.sh
new file mode 100644
index 0000000..5fd766e
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/clean.sh
@@ -0,0 +1,20 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after virtual time tests.
+#
+rm -f */K* */dsset-* */*.signed */*.jnl */tmp*
+rm -f dig.out.*
+rm -f random.data*
+rm -f */named.memstats
+rm -f */*vtwrapper.*
+rm -f ns1/example.db
+rm -f ns1/keyname
+rm -f ns*/named.lock
diff --git a/bin/tests/virtual-time/autosign-zsk/ns1/example.db.in b/bin/tests/virtual-time/autosign-zsk/ns1/example.db.in
new file mode 100644
index 0000000..c61ebd3
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/ns1/example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60 ; 1 mn (to avoid to delay activation with ttl > prepublish)
+@ IN SOA ns root (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 12000 ; expire
+ 600 ; minimum
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
diff --git a/bin/tests/virtual-time/autosign-zsk/ns1/named.conf b/bin/tests/virtual-time/autosign-zsk/ns1/named.conf
new file mode 100644
index 0000000..94e9126
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/ns1/named.conf
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ sig-validity-interval 2;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example." {
+ type master;
+ file "example.db.signed";
+ allow-query { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
diff --git a/bin/tests/virtual-time/autosign-zsk/ns1/root.db b/bin/tests/virtual-time/autosign-zsk/ns1/root.db
new file mode 100644
index 0000000..d2c6cd4
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/ns1/root.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example NS ns.example
+ns.example A 10.53.0.1
+
diff --git a/bin/tests/virtual-time/autosign-zsk/ns1/sign.sh b/bin/tests/virtual-time/autosign-zsk/ns1/sign.sh
new file mode 100644
index 0000000..d0723db
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/ns1/sign.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data1
+RANDFILE2=../random.data2
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+zskname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+kskname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -f KSK -n zone $zone`
+
+cat $infile $zskname.key $kskname.key > $zonefile
+
+$SIGNER -P -e +1000d -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# zsk, no -R
+keyname=`$KEYGEN -q -r $RANDFILE2 -a RSASHA1 -b 768 -n zone \
+ -P +20 -A +1h -I +1d -D +1mo $zone`
+
+echo $keyname > keyname
diff --git a/bin/tests/virtual-time/autosign-zsk/ns1/wrap.sh b/bin/tests/virtual-time/autosign-zsk/ns1/wrap.sh
new file mode 100644
index 0000000..9bc15bb
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/ns1/wrap.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Wrapper for named
+#
+
+LD_PRELOAD=../../libvtwrapper.so
+export LD_PRELOAD
+
+exec $*
diff --git a/bin/tests/virtual-time/autosign-zsk/setup.sh b/bin/tests/virtual-time/autosign-zsk/setup.sh
new file mode 100644
index 0000000..85a723a
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+. ./clean.sh
+
+../../../tools/genrandom 800 random.data
+dd if=random.data of=random.data1 bs=1k count=400 2> /dev/null
+dd if=random.data of=random.data2 bs=1k skip=400 2> /dev/null
+
+cd ns1 && sh sign.sh
+
diff --git a/bin/tests/virtual-time/autosign-zsk/tests.sh b/bin/tests/virtual-time/autosign-zsk/tests.sh
new file mode 100644
index 0000000..e71af8f
--- /dev/null
+++ b/bin/tests/virtual-time/autosign-zsk/tests.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+DIGOPTS="+noadd +nosea +nostat +nocmd +noauth +dnssec -p 5300"
+
+zsk=ns1/`cat ns1/keyname`.key
+zskpat=`awk '/DNSKEY/ { print $8 }' $zsk`
+zskid=`sed 's/^Kexample\.+005+0*//' < ns1/keyname`
+
+echo "I:checking for ZSK not yet published ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.key$n || ret=1
+# Note - this is looking for failure, hence the &&
+tr -d ' ' < dig.out.ns1.key$n | grep $zskpat > /dev/null && ret=1
+$DIG $DIGOPTS -t txt txt.example. @10.53.0.1 > dig.out.ns1.txt$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep 'RRSIG.*'" $zskid "'example\. ' dig.out.ns1.txt$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 5s real, 55s virtual, P +20
+sleep 4
+
+echo "I:checking for ZSK published but not yet active ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.key$n || ret=1
+tr -d ' ' < dig.out.ns1.key$n | grep $zskpat > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+$DIG $DIGOPTS -t txt txt.example. @10.53.0.1 > dig.out.ns1.txt$n || ret=1
+grep 'RRSIG.*'" $zskid "'example\. ' dig.out.ns1.txt$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 10s real, 2h15mn virtual, A +1h
+sleep 5
+
+echo "I:checking for ZSK active ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.key$n || ret=1
+tr -d ' ' < dig.out.ns1.key$n | grep $zskpat > /dev/null || ret=1
+$DIG $DIGOPTS -t txt txt.example. @10.53.0.1 > dig.out.ns1.txt$n || ret=1
+grep 'RRSIG.*'" $zskid "'example\. ' dig.out.ns1.txt$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 13s real, 45h virtual, I +1d
+sleep 3
+
+echo "I:checking for ZSK retired but not yet deleted ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.key$n || ret=1
+tr -d ' ' < dig.out.ns1.key$n | grep $zskpat > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+$DIG $DIGOPTS -t txt txt.example. @10.53.0.1 > dig.out.ns1.txt$n || ret=1
+grep 'RRSIG.*'" $zskid "'example\. ' dig.out.ns1.txt$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# 17s real, 103d virtual, D +1mo
+sleep 4
+
+echo "I:checking for ZSK deleted ($n)"
+ret=0
+$DIG $DIGOPTS -t dnskey example. @10.53.0.1 > dig.out.ns1.key$n || ret=1
+# Note - this is looking for failure, hence the &&
+tr -d ' ' < dig.out.ns1.key$n | grep $zskpat > /dev/null && ret=1
+# Note - this is looking for failure, hence the &&
+$DIG $DIGOPTS -t txt txt.example. @10.53.0.1 > dig.out.ns1.txt$n || ret=1
+grep 'RRSIG.*'" $zskid "'example\. ' dig.out.ns1.txt$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ] ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/virtual-time/cleanall.sh b/bin/tests/virtual-time/cleanall.sh
new file mode 100644
index 0000000..ad1f105
--- /dev/null
+++ b/bin/tests/virtual-time/cleanall.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after system tests.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+
+find . -type f \( \
+ -name 'K*' -o -name '*~' -o -name '*.core' -o -name '*.log' \
+ -o -name '*.pid' -o -name '*.keyset' -o -name named.run \
+ -o -name lwresd.run -o -name ans.run \) -print | xargs rm -f
+
+status=0
+
+for d in $SUBDIRS
+do
+ test ! -f $d/clean.sh || ( cd $d && sh clean.sh )
+done
diff --git a/bin/tests/virtual-time/common/controls.conf b/bin/tests/virtual-time/common/controls.conf
new file mode 100644
index 0000000..021bf86
--- /dev/null
+++ b/bin/tests/virtual-time/common/controls.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
+
diff --git a/bin/tests/virtual-time/common/rndc.conf b/bin/tests/virtual-time/common/rndc.conf
new file mode 100644
index 0000000..b47ca45
--- /dev/null
+++ b/bin/tests/virtual-time/common/rndc.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ default-key "rndc_key";
+};
+
+key rndc_key {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
diff --git a/bin/tests/virtual-time/common/root.hint b/bin/tests/virtual-time/common/root.hint
new file mode 100644
index 0000000..418ea96
--- /dev/null
+++ b/bin/tests/virtual-time/common/root.hint
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/virtual-time/conf.sh.in b/bin/tests/virtual-time/conf.sh.in
new file mode 100644
index 0000000..79cf4e0
--- /dev/null
+++ b/bin/tests/virtual-time/conf.sh.in
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Common configuration data for system tests, to be sourced into
+# other shell scripts.
+#
+
+# Find the top of the BIND9 tree.
+TOP=${SYSTEMTESTTOP:=.}/../../..
+
+# Make it absolute so that it continues to work after we cd.
+TOP=`cd $TOP && pwd`
+
+NAMED=$TOP/bin/named/named
+# We must use "named -l" instead of "lwresd" because argv[0] is lost
+# if the program is libtoolized.
+LWRESD="$TOP/bin/named/named -l"
+DIG=$TOP/bin/dig/dig
+RNDC=$TOP/bin/rndc/rndc
+NSUPDATE=$TOP/bin/nsupdate/nsupdate
+DDNSCONFGEN=$TOP/bin/confgen/ddns-confgen
+KEYGEN=$TOP/bin/dnssec/dnssec-keygen
+SIGNER=$TOP/bin/dnssec/dnssec-signzone
+REVOKE=$TOP/bin/dnssec/dnssec-revoke
+SETTIME=$TOP/bin/dnssec/dnssec-settime
+DSFROMKEY=$TOP/bin/dnssec/dnssec-dsfromkey
+CHECKZONE=$TOP/bin/check/named-checkzone
+CHECKCONF=$TOP/bin/check/named-checkconf
+
+SUBDIRS="slave autosign-zsk autosign-ksk"
+
+# PERL will be an empty string if no perl interpreter was found.
+PERL=@PERL@
+
+export NAMED LWRESD DIG NSUPDATE KEYGEN SIGNER KEYSIGNER KEYSETTOOL PERL \
+ SUBDIRS RNDC CHECKZONE
diff --git a/bin/tests/virtual-time/run.sh b/bin/tests/virtual-time/run.sh
new file mode 100644
index 0000000..c29d2ed
--- /dev/null
+++ b/bin/tests/virtual-time/run.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+stopservers=true
+
+case $1 in
+ --keep) stopservers=false; shift ;;
+esac
+
+test $# -gt 0 || { echo "usage: $0 [--keep] test-directory" >&2; exit 1; }
+
+test=$1
+shift
+
+test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
+
+echo "S:$test:`date`" >&2
+echo "T:$test:1:A" >&2
+echo "A:Virtual time test $test" >&2
+
+if [ x$PERL = x ]
+then
+ echo "I:Perl not available. Skipping test." >&2
+ echo "R:UNTESTED" >&2
+ echo "E:$test:`date`" >&2
+ exit 0;
+fi
+
+$PERL testsock.pl || {
+ echo "I:Network interface aliases not set up. Skipping test." >&2
+ echo "R:UNTESTED" >&2
+ echo "E:$test:`date`" >&2
+ exit 0;
+}
+
+# Check for test-specific prerequisites.
+if
+ test ! -f $test/prereq.sh ||
+ ( cd $test && sh prereq.sh "$@" )
+then
+ : prereqs ok
+else
+ echo "I:Prerequisites for $test missing, skipping test." >&2
+ echo "R:UNTESTED" >&2
+ echo "E:$test:`date`" >&2
+ exit 0;
+fi
+
+# Set up any dynamically generated test data
+if test -f $test/setup.sh
+then
+ ( cd $test && sh setup.sh "$@" )
+fi
+
+# Start name servers running
+$PERL start.pl $test || exit 1
+
+# Run the tests
+( cd $test ; sh tests.sh )
+
+status=$?
+
+if $stopservers
+then
+ :
+else
+ exit $status
+fi
+
+# Shutdown
+$PERL stop.pl $test
+
+status=`expr $status + $?`
+
+if [ $status != 0 ]; then
+ echo "R:FAIL"
+ # Don't clean up - we need the evidence.
+ find . -name core -exec chmod 0644 '{}' \;
+else
+ echo "R:PASS"
+
+ # Clean up.
+ if test -f $test/clean.sh
+ then
+ ( cd $test && sh clean.sh "$@" )
+ fi
+fi
+
+echo "E:$test:`date`"
+
+exit $status
diff --git a/bin/tests/virtual-time/runall.sh b/bin/tests/virtual-time/runall.sh
new file mode 100644
index 0000000..82b26bd
--- /dev/null
+++ b/bin/tests/virtual-time/runall.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run all the virtual time tests.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+$PERL testsock.pl || {
+ echo "I:Network interface aliases not set up. Skipping tests." >&2;
+ echo "R:UNTESTED" >&2;
+ echo "E:virtual-time:`date`" >&2;
+ exit 0;
+}
+
+status=0
+
+for d in $SUBDIRS
+do
+ sh run.sh $d || status=1
+done
+
+exit $status
diff --git a/bin/tests/virtual-time/setup.sh b/bin/tests/virtual-time/setup.sh
new file mode 100644
index 0000000..e2db2e5
--- /dev/null
+++ b/bin/tests/virtual-time/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run a system test.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/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 && sh setup.sh "$@" )
+fi
diff --git a/bin/tests/virtual-time/slave/clean.sh b/bin/tests/virtual-time/slave/clean.sh
new file mode 100644
index 0000000..780e8b2
--- /dev/null
+++ b/bin/tests/virtual-time/slave/clean.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after virtual time tests.
+#
+rm -f dig.out.*
+rm -f ns1/named.memstats
+rm -f ns1/vtwrapper.*
+rm -f ns1/example.db
+rm -f ns*/named.lock
diff --git a/bin/tests/virtual-time/slave/ns1/example.db.in b/bin/tests/virtual-time/slave/ns1/example.db.in
new file mode 100644
index 0000000..9b54373
--- /dev/null
+++ b/bin/tests/virtual-time/slave/ns1/example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 12000 ; expire
+ 600 ; minimum
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
diff --git a/bin/tests/virtual-time/slave/ns1/named.conf b/bin/tests/virtual-time/slave/ns1/named.conf
new file mode 100644
index 0000000..5cd3931
--- /dev/null
+++ b/bin/tests/virtual-time/slave/ns1/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example." {
+ type slave;
+ masters { 10.53.0.111; };
+ file "example.db";
+};
+
diff --git a/bin/tests/virtual-time/slave/ns1/root.db b/bin/tests/virtual-time/slave/ns1/root.db
new file mode 100644
index 0000000..d2c6cd4
--- /dev/null
+++ b/bin/tests/virtual-time/slave/ns1/root.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example NS ns.example
+ns.example A 10.53.0.1
+
diff --git a/bin/tests/virtual-time/slave/ns1/wrap.sh b/bin/tests/virtual-time/slave/ns1/wrap.sh
new file mode 100644
index 0000000..9bc15bb
--- /dev/null
+++ b/bin/tests/virtual-time/slave/ns1/wrap.sh
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Wrapper for named
+#
+
+LD_PRELOAD=../../libvtwrapper.so
+export LD_PRELOAD
+
+exec $*
diff --git a/bin/tests/virtual-time/slave/setup.sh b/bin/tests/virtual-time/slave/setup.sh
new file mode 100644
index 0000000..4b385e8
--- /dev/null
+++ b/bin/tests/virtual-time/slave/setup.sh
@@ -0,0 +1,11 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/example.db
+cp ns1/example.db.in ns1/example.db
diff --git a/bin/tests/virtual-time/slave/tests.sh b/bin/tests/virtual-time/slave/tests.sh
new file mode 100644
index 0000000..3768910
--- /dev/null
+++ b/bin/tests/virtual-time/slave/tests.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p 5300"
+
+echo "I:checking slave expiry"
+ret=0
+$DIG $DIGOPTS txt.example. txt @10.53.0.1 > dig.out.before || ret=1
+echo "I:waiting for expiry (10s real, 6h virtual)"
+sleep 10
+$DIG $DIGOPTS txt.example. txt @10.53.0.1 > dig.out.after || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+ret=0
+grep "status: NOERROR" dig.out.before > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I:failed (before)"; status=1
+fi
+ret=0
+grep "status: SERVFAIL" dig.out.after > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I:failed (after)"; status=1
+fi
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/virtual-time/start.pl b/bin/tests/virtual-time/start.pl
new file mode 100644
index 0000000..8e29033
--- /dev/null
+++ b/bin/tests/virtual-time/start.pl
@@ -0,0 +1,177 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 Cwd 'abs_path';
+use Getopt::Long;
+
+# Option handling
+# --noclean test [server [options]]
+#
+# --noclean - Do not cleanup files in server directory
+# test - name of the test directory
+# server - name of the server directory
+# options - alternate options for the server
+
+my $usage = "usage: $0 [--noclean] test-directory [server-directory [server-options]]";
+my $noclean;
+GetOptions('noclean' => \$noclean);
+my $test = $ARGV[0];
+my $server = $ARGV[1];
+my $options = $ARGV[2];
+
+if (!$test) {
+ print "$usage\n";
+}
+if (!-d $test) {
+ print "No test directory: \"$test\"\n";
+}
+if ($server && !-d "$test/$server") {
+ print "No server directory: \"$test/$server\"\n";
+}
+
+# Global variables
+my $topdir = abs_path("$test/..");
+my $testdir = abs_path("$test");
+my $NAMED = $ENV{'NAMED'};
+my $DIG = $ENV{'DIG'};
+my $PERL = $ENV{'PERL'};
+
+# Start the server(s)
+
+if ($server) {
+ if ($server =~ /^ns/) {
+ &check_ports($server);
+ }
+ &start_server($server, $options);
+ if ($server =~ /^ns/) {
+ &verify_server($server);
+ }
+} else {
+ # Determine which servers need to be started for this test.
+ opendir DIR, $testdir;
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ my @ns = grep /^ns[0-9]*$/, @files;
+
+ # Start the servers we found.
+ &check_ports();
+ foreach (@ns) {
+ &start_server($_);
+ }
+ foreach (@ns) {
+ &verify_server($_);
+ }
+}
+
+# Subroutines
+
+sub check_ports {
+ my $server = shift;
+ my $options = "";
+
+ if ($server && $server =~ /(\d+)$/) {
+ $options = "-i $1";
+ }
+
+ my $tries = 0;
+ while (1) {
+ my $return = system("$PERL $topdir/testsock.pl -p 5300 $options");
+ last if ($return == 0);
+ if (++$tries > 4) {
+ print "$0: could not bind to server addresses, still running?\n";
+ print "I:server sockets not available\n";
+ print "R:FAIL\n";
+ system("$PERL $topdir/stop.pl $testdir"); # Is this the correct behavior?
+ exit 1;
+ }
+ print "I:Couldn't bind to socket (yet)\n";
+ sleep 2;
+ }
+}
+
+sub start_server {
+ my $server = shift;
+ my $options = shift;
+
+ my $cleanup_files;
+ my $command;
+ my $pid_file;
+
+ if ($server =~ /^ns/) {
+ $cleanup_files = "{*.jnl,*.bk,*.st,named.run}";
+ $command = "sh wrap.sh ";
+ $command .= "$NAMED ";
+ if ($options) {
+ $command .= "$options";
+ } else {
+ $command .= "-m record,size,mctx ";
+ $command .= "-T clienttest ";
+ $command .= "-X named.lock ";
+ $command .= "-c named.conf -d 99 -g";
+ }
+ $command .= " >named.run 2>&1 &";
+ $pid_file = "named.pid";
+ } else {
+ print "I:Unknown server type $server\n";
+ print "R:FAIL\n";
+ system "$PERL $topdir/stop.pl $testdir";
+ exit 1;
+ }
+
+# print "I:starting server $server\n";
+
+ chdir "$testdir/$server";
+
+ unless ($noclean) {
+ unlink glob $cleanup_files;
+ }
+
+ system "$command";
+
+ my $tries = 0;
+ while (!-f $pid_file) {
+ if (++$tries > 14) {
+ print "I:Couldn't start server $server\n";
+ print "R:FAIL\n";
+ system "$PERL $topdir/stop.pl $testdir";
+ exit 1;
+ }
+ sleep 1;
+ }
+}
+
+sub verify_server {
+ my $server = shift;
+ my $n = $server;
+ $n =~ s/^ns//;
+
+ my $tries = 0;
+ while (1) {
+ my $return = system("$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p 5300 version.bind. chaos txt \@10.53.0.$n > dig.out");
+ last if ($return == 0);
+ print `grep ";" dig.out`;
+ if (++$tries >= 30) {
+ print "I:no response from $server\n";
+ print "R:FAIL\n";
+ system("$PERL $topdir/stop.pl $testdir");
+ exit 1;
+ }
+ sleep 2;
+ }
+ unlink "dig.out";
+}
diff --git a/bin/tests/virtual-time/start.sh b/bin/tests/virtual-time/start.sh
new file mode 100644
index 0000000..78fb044
--- /dev/null
+++ b/bin/tests/virtual-time/start.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ./conf.sh
+$PERL start.pl "$@"
diff --git a/bin/tests/virtual-time/stop.pl b/bin/tests/virtual-time/stop.pl
new file mode 100644
index 0000000..b46aa60
--- /dev/null
+++ b/bin/tests/virtual-time/stop.pl
@@ -0,0 +1,174 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# 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 Cwd 'abs_path';
+
+# Option handling
+# [--use-rndc] test [server]
+#
+# test - name of the test directory
+# server - name of the server directory
+
+my $usage = "usage: $0 [--use-rndc] test-directory [server-directory]";
+my $use_rndc;
+
+while (@ARGV && $ARGV[0] =~ /^-/) {
+ my $opt = shift @ARGV;
+ if ($opt eq '--use-rndc') {
+ $use_rndc = 1;
+ } else {
+ die "$usage\n";
+ }
+}
+
+my $test = $ARGV[0];
+my $server = $ARGV[1];
+
+my $errors = 0;
+
+die "$usage\n" unless defined($test);
+die "No test directory: \"$test\"\n" unless (-d $test);
+die "No server directory: \"$server\"\n" if (defined($server) && !-d "$test/$server");
+
+# Global variables
+my $testdir = abs_path($test);
+my @servers;
+
+
+# Determine which servers need to be stopped.
+if (defined $server) {
+ @servers = ($server);
+} else {
+ local *DIR;
+ opendir DIR, $testdir or die "$testdir: $!\n";
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ my @ns = grep /^ns[0-9]*$/, @files;
+
+ push @servers, @ns;
+}
+
+
+# Stop the server(s), pass 1: rndc.
+if ($use_rndc) {
+ foreach my $server (grep /^ns/, @servers) {
+ stop_rndc($server);
+ }
+
+ wait_for_servers(30, grep /^ns/, @servers);
+}
+
+
+# Pass 2: SIGTERM
+foreach my $server (@servers) {
+ stop_signal($server, "TERM");
+}
+
+wait_for_servers(60, @servers);
+
+# Pass 3: SIGABRT
+foreach my $server (@servers) {
+ stop_signal($server, "ABRT");
+}
+
+exit($errors ? 1 : 0);
+
+# Subroutines
+
+# Return the full path to a given server's PID file.
+sub server_pid_file {
+ my($server) = @_;
+
+ my $pid_file;
+ if ($server =~ /^ns/) {
+ $pid_file = "named.pid";
+ } else {
+ print "I:Unknown server type $server\n";
+ exit 1;
+ }
+ $pid_file = "$testdir/$server/$pid_file";
+}
+
+# Read a PID.
+sub read_pid {
+ my($pid_file) = @_;
+
+ local *FH;
+ my $result = open FH, "< $pid_file";
+ if (!$result) {
+ print "I:$pid_file: $!\n";
+ unlink $pid_file;
+ return;
+ }
+
+ my $pid = <FH>;
+ chomp($pid);
+ return $pid;
+}
+
+# Stop a named process with rndc.
+sub stop_rndc {
+ my($server) = @_;
+
+ return unless ($server =~ /^ns(\d+)$/);
+ my $ip = "10.53.0.$1";
+
+ # Ugly, but should work.
+ system("$ENV{RNDC} -c $testdir/../common/rndc.conf -s $ip -p 9953 stop | sed 's/^/I:$server /'");
+ return;
+}
+
+# Stop a server by sending a signal to it.
+sub stop_signal {
+ my($server, $sig) = @_;
+
+ my $pid_file = server_pid_file($server);
+ return unless -f $pid_file;
+
+ my $pid = read_pid($pid_file);
+ return unless defined($pid);
+
+ if ($sig eq 'ABRT') {
+ print "I:$server didn't die when sent a SIGTERM\n";
+ $errors++;
+ }
+
+ my $result = kill $sig, $pid;
+ if (!$result) {
+ print "I:$server died before a SIG$sig was sent\n";
+ unlink $pid_file;
+ $errors++;
+ }
+
+ return;
+}
+
+sub wait_for_servers {
+ my($timeout, @servers) = @_;
+
+ my @pid_files = grep { defined($_) }
+ map { server_pid_file($_) } @servers;
+
+ while ($timeout > 0 && @pid_files > 0) {
+ @pid_files = grep { -f $_ } @pid_files;
+ sleep 1 if (@pid_files > 0);
+ $timeout--;
+ }
+
+ return;
+}
diff --git a/bin/tests/virtual-time/stop.sh b/bin/tests/virtual-time/stop.sh
new file mode 100644
index 0000000..a2ae614
--- /dev/null
+++ b/bin/tests/virtual-time/stop.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ./conf.sh
+$PERL ./stop.pl "$@"
+
diff --git a/bin/tests/virtual-time/testsock.pl b/bin/tests/virtual-time/testsock.pl
new file mode 100644
index 0000000..b793bae
--- /dev/null
+++ b/bin/tests/virtual-time/testsock.pl
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Test whether the interfaces on 10.53.0.* are up.
+
+require 5.001;
+
+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 {
+ @ids = (1..5);
+}
+
+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);
+ sleep(1);
+}
diff --git a/bin/tests/virtual-time/vtwrapper.c b/bin/tests/virtual-time/vtwrapper.c
new file mode 100644
index 0000000..36471f2
--- /dev/null
+++ b/bin/tests/virtual-time/vtwrapper.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#define _GNU_SOURCE
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef SYS_select
+#include <sys/select.h>
+#endif
+#ifdef SYS_poll
+#include <poll.h>
+#endif
+#ifdef SYS_kevent
+#include <sys/event.h>
+#endif
+#ifdef SYS_epoll_wait
+#include <sys/epoll.h>
+#endif
+
+
+#ifdef SYS_gettimeofday
+#define VIRTUAL_TIME
+#ifdef VIRTUAL_TIME
+static struct timeval epoch = { 0, 0 };
+static int _init_called = 0;
+
+void
+_init(void) {
+ (void)syscall(SYS_gettimeofday, &epoch, NULL);
+ _init_called = 1;
+}
+
+static void
+absolute_inflate(struct timeval *vt, struct timeval *rt)
+{
+ double d;
+
+ rt->tv_sec = vt->tv_sec;
+ rt->tv_usec = vt->tv_usec;
+
+ if ((epoch.tv_sec > vt->tv_sec) ||
+ ((epoch.tv_sec == vt->tv_sec) && (epoch.tv_usec > vt->tv_usec)))
+ return;
+
+ rt->tv_sec -= epoch.tv_sec;
+ rt->tv_usec -= epoch.tv_usec;
+ while (rt->tv_usec < 0) {
+ rt->tv_sec -= 1;
+ rt->tv_usec += 1000000;
+ }
+
+ if (rt->tv_sec == 0)
+ goto done;
+
+ d = (double) (rt->tv_sec - 1);
+ d += (double) rt->tv_usec / 1000000.;
+ d = exp(d);
+ rt->tv_sec = (time_t) d;
+ d -= (double) rt->tv_sec;
+ rt->tv_usec = (suseconds_t) (d * 1000000.);
+
+ done:
+ rt->tv_sec += epoch.tv_sec;
+ rt->tv_usec += epoch.tv_usec;
+ while (rt->tv_usec >= 1000000) {
+ rt->tv_sec += 1;
+ rt->tv_usec -= 1000000;
+ }
+ return;
+}
+
+static void
+absolute_deflate(struct timeval *rt, struct timeval *vt) {
+ double d;
+
+ vt->tv_sec = rt->tv_sec;
+ vt->tv_usec = rt->tv_usec;
+
+ if ((epoch.tv_sec > rt->tv_sec) ||
+ ((epoch.tv_sec == rt->tv_sec) && (epoch.tv_usec > rt->tv_usec)))
+ return;
+
+ vt->tv_sec -= epoch.tv_sec;
+ vt->tv_usec -= epoch.tv_usec;
+ while (vt->tv_usec < 0) {
+ vt->tv_sec -= 1;
+ vt->tv_usec += 1000000;
+ }
+
+ if (vt->tv_sec == 0)
+ goto done;
+
+ d = (double) vt->tv_sec;
+ d += (double) vt->tv_usec / 1000000.;
+ d = log(d);
+ vt->tv_sec = (time_t) d;
+ d -= (double) vt->tv_sec;
+ vt->tv_sec += 1;
+ vt->tv_usec = (suseconds_t) (d * 1000000.);
+
+ done:
+ vt->tv_sec += epoch.tv_sec;
+ vt->tv_usec += epoch.tv_usec;
+ while (vt->tv_usec >= 1000000) {
+ vt->tv_sec += 1;
+ vt->tv_usec -= 1000000;
+ }
+ return;
+}
+
+static void
+interval_inflate(struct timeval *vt, struct timeval *rt) {
+ struct timeval now, tv;
+
+ (void) gettimeofday(&now, NULL);
+
+ absolute_deflate(&now, &tv);
+
+ tv.tv_sec += vt->tv_sec;
+ tv.tv_usec += vt->tv_usec;
+ while (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+
+ absolute_inflate(&tv, rt);
+
+ rt->tv_sec -= now.tv_sec;
+ rt->tv_usec -= now.tv_usec;
+ if (rt->tv_usec < 0) {
+ rt->tv_sec -= 1;
+ rt->tv_usec += 1000000;
+ }
+ return;
+}
+
+static void
+interval_deflate(struct timeval *rt, struct timeval *vt) {
+ struct timeval now, tv;
+
+ vt->tv_sec = rt->tv_sec;
+ vt->tv_usec = rt->tv_usec;
+
+ if ((vt->tv_sec == 0) && (vt->tv_usec <= 10000))
+ return;
+
+ (void) gettimeofday(&now, NULL);
+
+ tv.tv_sec = now.tv_sec + rt->tv_sec;
+ tv.tv_usec = now.tv_usec + rt->tv_usec;
+ while (tv.tv_usec >= 1000000) {
+ tv.tv_sec += 1;
+ tv.tv_usec -= 1000000;
+ }
+
+ absolute_deflate(&now, &now);
+ absolute_deflate(&tv, vt);
+
+ vt->tv_sec -= now.tv_sec;
+ vt->tv_usec -= now.tv_usec;
+ while (vt->tv_usec < 0) {
+ vt->tv_sec -= 1;
+ vt->tv_usec += 1000000;
+ }
+
+ if ((vt->tv_sec == 0) && (vt->tv_usec < 10000))
+ vt->tv_usec = 10000;
+ return;
+}
+#endif
+
+int
+gettimeofday(struct timeval *tv, struct timezone *tz) {
+#ifdef VIRTUAL_TIME
+ struct timeval now;
+ int ret;
+
+ if (!_init_called) _init();
+
+ if (epoch.tv_sec == 0)
+ return syscall(SYS_gettimeofday, tv, tz);
+
+ ret = syscall(SYS_gettimeofday, &now, tz);
+ if (ret == 0)
+ absolute_inflate(&now, tv);
+ return ret;
+#else
+ return syscall(SYS_gettimeofday, tv, tz);
+#endif
+}
+
+#ifdef SYS_select
+int
+select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+ struct timeval *timeout)
+{
+#ifdef VIRTUAL_TIME
+ struct timeval tv;
+
+ if (!_init_called) _init();
+
+ if (epoch.tv_sec == 0 || timeout == NULL ||
+ (timeout->tv_sec == 0 && timeout->tv_usec == 0))
+ return syscall(SYS_select, nfds, rfds, wfds, xfds, timeout);
+
+ interval_deflate(timeout, &tv);
+ return syscall(SYS_select, nfds, rfds, wfds, xfds, &tv);
+#else
+ return syscall(SYS_select, nfds, rfds, wfds, xfds, timeout);
+#endif
+}
+#endif
+
+#ifdef SYS_poll
+int
+poll(struct pollfd fds[], nfds_t nfds, int timeout) {
+#ifdef VIRTUAL_TIME
+ struct timeval in, out;
+
+ if (!_init_called) _init();
+
+ if (timeout <= 0 || epoch.tv_sec == 0)
+ return syscall(SYS_poll, fds, nfds, timeout);
+
+ in.tv_sec = timeout / 1000;
+ in.tv_usec = (timeout % 1000) * 1000;
+ interval_deflate(&in, &out);
+ timeout = out.tv_sec * 1000 + out.tv_usec / 1000;
+ return syscall(SYS_poll, fds, nfds, timeout);
+#else
+ return syscall(SYS_poll, fds, nfds, timeout);
+#endif
+}
+#endif
+
+#ifdef SYS_kevent
+int
+kevent(int kq, struct kevent *changelist, int nchanges,
+ struct kevent *eventlist, int nevents, const struct timespec *timeout)
+{
+#ifdef VIRTUAL_TIME
+ struct timeval in, out;
+ struct timespec ts;
+
+ if (!_init_called) _init();
+
+ if (epoch.tv_sec == 0 || timeout == NULL ||
+ (timeout->tv_sec == 0 && timeout->tv_nsec == 0))
+ return syscall(SYS_kevent, kq, changelist, nchanges,
+ eventlist, nevents, timeout);
+
+ in.tv_sec = timeout->tv_sec;
+ in.tv_usec = timeout->tv_nsec / 1000;
+ interval_deflate(&in, &out);
+ ts.tv_sec = out.tv_sec;
+ ts.tv_nsec = out.tv_usec * 1000;
+ return syscall(SYS_kevent, kq, changelist, nchanges, eventlist,
+ nevents, &ts);
+#else
+ return syscall(SYS_kevent, kq, changelist, nchanges, eventlist,
+ nevents, timeout);
+#endif
+}
+#endif
+
+#ifdef SYS_epoll_wait
+int
+epoll_wait(int fd, struct epoll_event *events, int maxevents, int timeout) {
+#ifdef VIRTUAL_TIME
+ struct timeval in, out;
+
+ if (!_init_called) _init();
+
+ if (timeout == 0 || timeout == -1 || epoch.tv_sec == 0)
+ return syscall(SYS_epoll_wait, fd, events, maxevents, timeout);
+
+ in.tv_sec = timeout / 1000;
+ in.tv_usec = (timeout % 1000) * 1000;
+ interval_deflate(&in, &out);
+ timeout = out.tv_sec * 1000 + out.tv_usec / 1000;
+ return syscall(SYS_poll, fd, events, maxevents, timeout);
+#else
+ return syscall(SYS_poll, fd, events, maxevents, timeout);
+#endif
+}
+#endif
+#endif
diff --git a/bin/tests/win32/backtrace_test.dsp.in b/bin/tests/win32/backtrace_test.dsp.in
new file mode 100644
index 0000000..732cba5
--- /dev/null
+++ b/bin/tests/win32/backtrace_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="backtrace_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=backtrace_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "backtrace_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "backtrace_test.mak" CFG="backtrace_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "backtrace_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "backtrace_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "backtrace_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/backtrace_test.exe"
+
+!ELSEIF "$(CFG)" == "backtrace_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/backtrace_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "backtrace_test - @PLATFORM@ Release"
+# Name "backtrace_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\backtrace_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/backtrace_test.dsw b/bin/tests/win32/backtrace_test.dsw
new file mode 100644
index 0000000..233b328
--- /dev/null
+++ b/bin/tests/win32/backtrace_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "backtrace_test"=".\backtrace_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/backtrace_test.mak.in b/bin/tests/win32/backtrace_test.mak.in
new file mode 100644
index 0000000..23348eb
--- /dev/null
+++ b/bin/tests/win32/backtrace_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on backtrace_test.dsp
+!IF "$(CFG)" == ""
+CFG=backtrace_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to backtrace_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "backtrace_test - @PLATFORM@ Release" && "$(CFG)" != "backtrace_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "backtrace_test.mak" CFG="backtrace_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "backtrace_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "backtrace_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "backtrace_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "backtrace_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\backtrace_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\backtrace_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\backtrace_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\backtrace_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\backtrace_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\backtrace_test.pdb" @MACHINE@ /out:"../../../Build/Release/backtrace_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\backtrace_test.obj"
+
+"..\..\..\Build\Release\backtrace_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "backtrace_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\backtrace_test.exe" "$(OUTDIR)\backtrace_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\backtrace_test.obj"
+ -@erase "$(INTDIR)\backtrace_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\backtrace_test.pdb"
+ -@erase "$(OUTDIR)\backtrace_test.bsc"
+ -@erase "..\..\..\Build\Debug\backtrace_test.exe"
+ -@erase "..\..\..\Build\Debug\backtrace_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\backtrace_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\backtrace_test.sbr"
+
+"$(OUTDIR)\backtrace_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\backtrace_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/backtrace_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\backtrace_test.obj"
+
+"..\..\..\Build\Debug\backtrace_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("backtrace_test.dep")
+!INCLUDE "backtrace_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "backtrace_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "backtrace_test - @PLATFORM@ Release" || "$(CFG)" == "backtrace_test - @PLATFORM@ Debug"
+SOURCE="..\backtrace_test.c"
+
+!IF "$(CFG)" == "backtrace_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\backtrace_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "backtrace_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\backtrace_test.obj" "$(INTDIR)\backtrace_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/backtrace_test.vcxproj.filters.in b/bin/tests/win32/backtrace_test.vcxproj.filters.in
new file mode 100644
index 0000000..307a6ec
--- /dev/null
+++ b/bin/tests/win32/backtrace_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\backtrace_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/backtrace_test.vcxproj.in b/bin/tests/win32/backtrace_test.vcxproj.in
new file mode 100644
index 0000000..a07b20a
--- /dev/null
+++ b/bin/tests/win32/backtrace_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{14751171-C40E-40EE-A2F0-37FFC3CCD4A2}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>backtrace_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\backtrace_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/backtrace_test.vcxproj.user b/bin/tests/win32/backtrace_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/backtrace_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/inter_test.dsp.in b/bin/tests/win32/inter_test.dsp.in
new file mode 100644
index 0000000..afdb63e
--- /dev/null
+++ b/bin/tests/win32/inter_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="inter_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=inter_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "inter_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "inter_test.mak" CFG="inter_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "inter_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "inter_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "inter_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/inter_test.exe"
+
+!ELSEIF "$(CFG)" == "inter_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/inter_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "inter_test - @PLATFORM@ Release"
+# Name "inter_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\inter_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/inter_test.dsw b/bin/tests/win32/inter_test.dsw
new file mode 100644
index 0000000..602bf9d
--- /dev/null
+++ b/bin/tests/win32/inter_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "inter_test"=".\inter_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/inter_test.mak.in b/bin/tests/win32/inter_test.mak.in
new file mode 100644
index 0000000..b13e31b
--- /dev/null
+++ b/bin/tests/win32/inter_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on inter_test.dsp
+!IF "$(CFG)" == ""
+CFG=inter_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to inter_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "inter_test - @PLATFORM@ Release" && "$(CFG)" != "inter_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "inter_test.mak" CFG="inter_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "inter_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "inter_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "inter_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "inter_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\inter_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\inter_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\inter_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\inter_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\inter_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\inter_test.pdb" @MACHINE@ /out:"../../../Build/Release/inter_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\inter_test.obj"
+
+"..\..\..\Build\Release\inter_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "inter_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\inter_test.exe" "$(OUTDIR)\inter_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\inter_test.obj"
+ -@erase "$(INTDIR)\inter_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\inter_test.pdb"
+ -@erase "$(OUTDIR)\inter_test.bsc"
+ -@erase "..\..\..\Build\Debug\inter_test.exe"
+ -@erase "..\..\..\Build\Debug\inter_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\inter_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\inter_test.sbr"
+
+"$(OUTDIR)\inter_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\inter_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/inter_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\inter_test.obj"
+
+"..\..\..\Build\Debug\inter_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("inter_test.dep")
+!INCLUDE "inter_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "inter_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "inter_test - @PLATFORM@ Release" || "$(CFG)" == "inter_test - @PLATFORM@ Debug"
+SOURCE="..\inter_test.c"
+
+!IF "$(CFG)" == "inter_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\inter_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "inter_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\inter_test.obj" "$(INTDIR)\inter_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/inter_test.vcxproj.filters.in b/bin/tests/win32/inter_test.vcxproj.filters.in
new file mode 100644
index 0000000..2797475
--- /dev/null
+++ b/bin/tests/win32/inter_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\inter_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/inter_test.vcxproj.in b/bin/tests/win32/inter_test.vcxproj.in
new file mode 100644
index 0000000..17cb856
--- /dev/null
+++ b/bin/tests/win32/inter_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{06AA5F16-7121-4C3A-91EF-AFC3BF3B8CE1}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>inter_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\inter_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/inter_test.vcxproj.user b/bin/tests/win32/inter_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/inter_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/makejournal.dsp.in b/bin/tests/win32/makejournal.dsp.in
new file mode 100644
index 0000000..fc04c62
--- /dev/null
+++ b/bin/tests/win32/makejournal.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="makejournal" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=makejournal - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "makejournal.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "makejournal.mak" CFG="makejournal - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "makejournal - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "makejournal - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "makejournal - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/makejournal.exe"
+
+!ELSEIF "$(CFG)" == "makejournal - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/makejournal.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "makejournal - @PLATFORM@ Release"
+# Name "makejournal - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\makejournal.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/makejournal.dsw b/bin/tests/win32/makejournal.dsw
new file mode 100644
index 0000000..8f6214b
--- /dev/null
+++ b/bin/tests/win32/makejournal.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "makejournal"=".\makejournal.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/makejournal.mak.in b/bin/tests/win32/makejournal.mak.in
new file mode 100644
index 0000000..00802d6
--- /dev/null
+++ b/bin/tests/win32/makejournal.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on makejournal.dsp
+!IF "$(CFG)" == ""
+CFG=makejournal - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to makejournal - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "makejournal - @PLATFORM@ Release" && "$(CFG)" != "makejournal - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "makejournal.mak" CFG="makejournal - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "makejournal - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "makejournal - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "makejournal - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "makejournal - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\makejournal.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\makejournal.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\makejournal.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\makejournal.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\makejournal.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\makejournal.pdb" @MACHINE@ /out:"../../../Build/Release/makejournal.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\makejournal.obj"
+
+"..\..\..\Build\Release\makejournal.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "makejournal - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\makejournal.exe" "$(OUTDIR)\makejournal.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\makejournal.obj"
+ -@erase "$(INTDIR)\makejournal.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\makejournal.pdb"
+ -@erase "$(OUTDIR)\makejournal.bsc"
+ -@erase "..\..\..\Build\Debug\makejournal.exe"
+ -@erase "..\..\..\Build\Debug\makejournal.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\makejournal.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\makejournal.sbr"
+
+"$(OUTDIR)\makejournal.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\makejournal.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/makejournal.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\makejournal.obj"
+
+"..\..\..\Build\Debug\makejournal.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("makejournal.dep")
+!INCLUDE "makejournal.dep"
+!ELSE
+!MESSAGE Warning: cannot find "makejournal.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "makejournal - @PLATFORM@ Release" || "$(CFG)" == "makejournal - @PLATFORM@ Debug"
+SOURCE="..\makejournal.c"
+
+!IF "$(CFG)" == "makejournal - @PLATFORM@ Release"
+
+
+"$(INTDIR)\makejournal.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "makejournal - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\makejournal.obj" "$(INTDIR)\makejournal.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/makejournal.vcxproj.filters.in b/bin/tests/win32/makejournal.vcxproj.filters.in
new file mode 100644
index 0000000..44aa47b
--- /dev/null
+++ b/bin/tests/win32/makejournal.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\makejournal.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/makejournal.vcxproj.in b/bin/tests/win32/makejournal.vcxproj.in
new file mode 100644
index 0000000..e574dd1
--- /dev/null
+++ b/bin/tests/win32/makejournal.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{31715139-2C27-47D2-8394-71B71A8AC3D5}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>makejournal</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\makejournal.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/makejournal.vcxproj.user b/bin/tests/win32/makejournal.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/makejournal.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/rwlock_test.dsp.in b/bin/tests/win32/rwlock_test.dsp.in
new file mode 100644
index 0000000..e852c6f
--- /dev/null
+++ b/bin/tests/win32/rwlock_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="rwlock_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=rwlock_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rwlock_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rwlock_test.mak" CFG="rwlock_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rwlock_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rwlock_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rwlock_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/rwlock_test.exe"
+
+!ELSEIF "$(CFG)" == "rwlock_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/rwlock_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rwlock_test - @PLATFORM@ Release"
+# Name "rwlock_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\rwlock_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/rwlock_test.dsw b/bin/tests/win32/rwlock_test.dsw
new file mode 100644
index 0000000..94ef272
--- /dev/null
+++ b/bin/tests/win32/rwlock_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rwlock_test"=".\rwlock_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/rwlock_test.mak.in b/bin/tests/win32/rwlock_test.mak.in
new file mode 100644
index 0000000..bed1f31
--- /dev/null
+++ b/bin/tests/win32/rwlock_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on rwlock_test.dsp
+!IF "$(CFG)" == ""
+CFG=rwlock_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to rwlock_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rwlock_test - @PLATFORM@ Release" && "$(CFG)" != "rwlock_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rwlock_test.mak" CFG="rwlock_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rwlock_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rwlock_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "rwlock_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "rwlock_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\rwlock_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\rwlock_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\rwlock_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\rwlock_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rwlock_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\rwlock_test.pdb" @MACHINE@ /out:"../../../Build/Release/rwlock_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\rwlock_test.obj"
+
+"..\..\..\Build\Release\rwlock_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "rwlock_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\rwlock_test.exe" "$(OUTDIR)\rwlock_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\rwlock_test.obj"
+ -@erase "$(INTDIR)\rwlock_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\rwlock_test.pdb"
+ -@erase "$(OUTDIR)\rwlock_test.bsc"
+ -@erase "..\..\..\Build\Debug\rwlock_test.exe"
+ -@erase "..\..\..\Build\Debug\rwlock_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rwlock_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\rwlock_test.sbr"
+
+"$(OUTDIR)\rwlock_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rwlock_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/rwlock_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\rwlock_test.obj"
+
+"..\..\..\Build\Debug\rwlock_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("rwlock_test.dep")
+!INCLUDE "rwlock_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "rwlock_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rwlock_test - @PLATFORM@ Release" || "$(CFG)" == "rwlock_test - @PLATFORM@ Debug"
+SOURCE="..\rwlock_test.c"
+
+!IF "$(CFG)" == "rwlock_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\rwlock_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rwlock_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\rwlock_test.obj" "$(INTDIR)\rwlock_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/rwlock_test.vcxproj.filters.in b/bin/tests/win32/rwlock_test.vcxproj.filters.in
new file mode 100644
index 0000000..99ad567
--- /dev/null
+++ b/bin/tests/win32/rwlock_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rwlock_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/rwlock_test.vcxproj.in b/bin/tests/win32/rwlock_test.vcxproj.in
new file mode 100644
index 0000000..46a1200
--- /dev/null
+++ b/bin/tests/win32/rwlock_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7705EEF6-6980-48F9-A045-699DAFE860C9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>rwlock_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\rwlock_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/rwlock_test.vcxproj.user b/bin/tests/win32/rwlock_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/rwlock_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/shutdown_test.dsp.in b/bin/tests/win32/shutdown_test.dsp.in
new file mode 100644
index 0000000..c304d24
--- /dev/null
+++ b/bin/tests/win32/shutdown_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="shutdown_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=shutdown_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "shutdown_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "shutdown_test.mak" CFG="shutdown_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "shutdown_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "shutdown_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "shutdown_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/shutdown_test.exe"
+
+!ELSEIF "$(CFG)" == "shutdown_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/shutdown_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "shutdown_test - @PLATFORM@ Release"
+# Name "shutdown_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\shutdown_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/shutdown_test.dsw b/bin/tests/win32/shutdown_test.dsw
new file mode 100644
index 0000000..770ffe4
--- /dev/null
+++ b/bin/tests/win32/shutdown_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "shutdown_test"=".\shutdown_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/shutdown_test.mak.in b/bin/tests/win32/shutdown_test.mak.in
new file mode 100644
index 0000000..c5d9efc
--- /dev/null
+++ b/bin/tests/win32/shutdown_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on shutdown_test.dsp
+!IF "$(CFG)" == ""
+CFG=shutdown_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to shutdown_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "shutdown_test - @PLATFORM@ Release" && "$(CFG)" != "shutdown_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "shutdown_test.mak" CFG="shutdown_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "shutdown_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "shutdown_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "shutdown_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "shutdown_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\shutdown_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\shutdown_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\shutdown_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\shutdown_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\shutdown_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\shutdown_test.pdb" @MACHINE@ /out:"../../../Build/Release/shutdown_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\shutdown_test.obj"
+
+"..\..\..\Build\Release\shutdown_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "shutdown_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\shutdown_test.exe" "$(OUTDIR)\shutdown_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\shutdown_test.obj"
+ -@erase "$(INTDIR)\shutdown_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\shutdown_test.pdb"
+ -@erase "$(OUTDIR)\shutdown_test.bsc"
+ -@erase "..\..\..\Build\Debug\shutdown_test.exe"
+ -@erase "..\..\..\Build\Debug\shutdown_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\shutdown_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\shutdown_test.sbr"
+
+"$(OUTDIR)\shutdown_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\shutdown_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/shutdown_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\shutdown_test.obj"
+
+"..\..\..\Build\Debug\shutdown_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("shutdown_test.dep")
+!INCLUDE "shutdown_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "shutdown_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "shutdown_test - @PLATFORM@ Release" || "$(CFG)" == "shutdown_test - @PLATFORM@ Debug"
+SOURCE="..\shutdown_test.c"
+
+!IF "$(CFG)" == "shutdown_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\shutdown_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "shutdown_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\shutdown_test.obj" "$(INTDIR)\shutdown_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/shutdown_test.vcxproj.filters.in b/bin/tests/win32/shutdown_test.vcxproj.filters.in
new file mode 100644
index 0000000..64f052c
--- /dev/null
+++ b/bin/tests/win32/shutdown_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\shutdown_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/shutdown_test.vcxproj.in b/bin/tests/win32/shutdown_test.vcxproj.in
new file mode 100644
index 0000000..943a8bb
--- /dev/null
+++ b/bin/tests/win32/shutdown_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{551561F6-4A2A-4824-8A34-A4AF0EB7C179}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>shutdown_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\shutdown_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/shutdown_test.vcxproj.user b/bin/tests/win32/shutdown_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/shutdown_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/sock_test.dsp.in b/bin/tests/win32/sock_test.dsp.in
new file mode 100644
index 0000000..713aff0
--- /dev/null
+++ b/bin/tests/win32/sock_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="sock_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=sock_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sock_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sock_test.mak" CFG="sock_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sock_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "sock_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sock_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/sock_test.exe"
+
+!ELSEIF "$(CFG)" == "sock_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/sock_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "sock_test - @PLATFORM@ Release"
+# Name "sock_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\sock_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/sock_test.dsw b/bin/tests/win32/sock_test.dsw
new file mode 100644
index 0000000..7cebb7a
--- /dev/null
+++ b/bin/tests/win32/sock_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sock_test"=".\sock_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/sock_test.mak.in b/bin/tests/win32/sock_test.mak.in
new file mode 100644
index 0000000..d92c0e8
--- /dev/null
+++ b/bin/tests/win32/sock_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on sock_test.dsp
+!IF "$(CFG)" == ""
+CFG=sock_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to sock_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "sock_test - @PLATFORM@ Release" && "$(CFG)" != "sock_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sock_test.mak" CFG="sock_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sock_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "sock_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "sock_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "sock_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\sock_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\sock_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\sock_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\sock_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\sock_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\sock_test.pdb" @MACHINE@ /out:"../../../Build/Release/sock_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\sock_test.obj"
+
+"..\..\..\Build\Release\sock_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "sock_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\sock_test.exe" "$(OUTDIR)\sock_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\sock_test.obj"
+ -@erase "$(INTDIR)\sock_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\sock_test.pdb"
+ -@erase "$(OUTDIR)\sock_test.bsc"
+ -@erase "..\..\..\Build\Debug\sock_test.exe"
+ -@erase "..\..\..\Build\Debug\sock_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\sock_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\sock_test.sbr"
+
+"$(OUTDIR)\sock_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\sock_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/sock_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\sock_test.obj"
+
+"..\..\..\Build\Debug\sock_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("sock_test.dep")
+!INCLUDE "sock_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "sock_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "sock_test - @PLATFORM@ Release" || "$(CFG)" == "sock_test - @PLATFORM@ Debug"
+SOURCE="..\sock_test.c"
+
+!IF "$(CFG)" == "sock_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\sock_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "sock_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\sock_test.obj" "$(INTDIR)\sock_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/sock_test.vcxproj.filters.in b/bin/tests/win32/sock_test.vcxproj.filters.in
new file mode 100644
index 0000000..bbe2ff8
--- /dev/null
+++ b/bin/tests/win32/sock_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sock_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/sock_test.vcxproj.in b/bin/tests/win32/sock_test.vcxproj.in
new file mode 100644
index 0000000..729826c
--- /dev/null
+++ b/bin/tests/win32/sock_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6200ED9D-CAB1-4C00-8D79-478F64A19B8F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>sock_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sock_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/sock_test.vcxproj.user b/bin/tests/win32/sock_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/sock_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/task_test.dsp.in b/bin/tests/win32/task_test.dsp.in
new file mode 100644
index 0000000..9e5f9f8
--- /dev/null
+++ b/bin/tests/win32/task_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="task_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=task_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "task_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "task_test.mak" CFG="task_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "task_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "task_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "task_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/task_test.exe"
+
+!ELSEIF "$(CFG)" == "task_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/task_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "task_test - @PLATFORM@ Release"
+# Name "task_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\task_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/task_test.dsw b/bin/tests/win32/task_test.dsw
new file mode 100644
index 0000000..c28d0c2
--- /dev/null
+++ b/bin/tests/win32/task_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "task_test"=".\task_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/task_test.mak.in b/bin/tests/win32/task_test.mak.in
new file mode 100644
index 0000000..3ac4bb5
--- /dev/null
+++ b/bin/tests/win32/task_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on task_test.dsp
+!IF "$(CFG)" == ""
+CFG=task_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to task_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "task_test - @PLATFORM@ Release" && "$(CFG)" != "task_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "task_test.mak" CFG="task_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "task_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "task_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "task_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "task_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\task_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\task_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\task_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\task_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\task_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\task_test.pdb" @MACHINE@ /out:"../../../Build/Release/task_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\task_test.obj"
+
+"..\..\..\Build\Release\task_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "task_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\task_test.exe" "$(OUTDIR)\task_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\task_test.obj"
+ -@erase "$(INTDIR)\task_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\task_test.pdb"
+ -@erase "$(OUTDIR)\task_test.bsc"
+ -@erase "..\..\..\Build\Debug\task_test.exe"
+ -@erase "..\..\..\Build\Debug\task_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\task_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\task_test.sbr"
+
+"$(OUTDIR)\task_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\task_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/task_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\task_test.obj"
+
+"..\..\..\Build\Debug\task_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("task_test.dep")
+!INCLUDE "task_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "task_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "task_test - @PLATFORM@ Release" || "$(CFG)" == "task_test - @PLATFORM@ Debug"
+SOURCE="..\task_test.c"
+
+!IF "$(CFG)" == "task_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\task_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "task_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\task_test.obj" "$(INTDIR)\task_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/task_test.vcxproj.filters.in b/bin/tests/win32/task_test.vcxproj.filters.in
new file mode 100644
index 0000000..b229ca1
--- /dev/null
+++ b/bin/tests/win32/task_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\task_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/task_test.vcxproj.in b/bin/tests/win32/task_test.vcxproj.in
new file mode 100644
index 0000000..ba75ffc
--- /dev/null
+++ b/bin/tests/win32/task_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CC7340C1-CBAF-4145-969A-73AE960401D6}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>task_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\task_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/task_test.vcxproj.user b/bin/tests/win32/task_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/task_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/timer_test.dsp.in b/bin/tests/win32/timer_test.dsp.in
new file mode 100644
index 0000000..8614893
--- /dev/null
+++ b/bin/tests/win32/timer_test.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="timer_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=timer_test - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "timer_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "timer_test.mak" CFG="timer_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "timer_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "timer_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "timer_test - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/timer_test.exe"
+
+!ELSEIF "$(CFG)" == "timer_test - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/timer_test.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "timer_test - @PLATFORM@ Release"
+# Name "timer_test - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\timer_test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tests/win32/timer_test.dsw b/bin/tests/win32/timer_test.dsw
new file mode 100644
index 0000000..a998f62
--- /dev/null
+++ b/bin/tests/win32/timer_test.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "timer_test"=".\timer_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/win32/timer_test.mak.in b/bin/tests/win32/timer_test.mak.in
new file mode 100644
index 0000000..c11438b
--- /dev/null
+++ b/bin/tests/win32/timer_test.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on timer_test.dsp
+!IF "$(CFG)" == ""
+CFG=timer_test - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to timer_test - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "timer_test - @PLATFORM@ Release" && "$(CFG)" != "timer_test - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "timer_test.mak" CFG="timer_test - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "timer_test - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "timer_test - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "timer_test - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "timer_test - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\timer_test.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\timer_test.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\timer_test.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\timer_test.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\timer_test.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\timer_test.pdb" @MACHINE@ /out:"../../../Build/Release/timer_test.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\timer_test.obj"
+
+"..\..\..\Build\Release\timer_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "timer_test - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\timer_test.exe" "$(OUTDIR)\timer_test.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\timer_test.obj"
+ -@erase "$(INTDIR)\timer_test.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\timer_test.pdb"
+ -@erase "$(OUTDIR)\timer_test.bsc"
+ -@erase "..\..\..\Build\Debug\timer_test.exe"
+ -@erase "..\..\..\Build\Debug\timer_test.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\timer_test.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\timer_test.sbr"
+
+"$(OUTDIR)\timer_test.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\timer_test.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/timer_test.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\timer_test.obj"
+
+"..\..\..\Build\Debug\timer_test.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("timer_test.dep")
+!INCLUDE "timer_test.dep"
+!ELSE
+!MESSAGE Warning: cannot find "timer_test.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "timer_test - @PLATFORM@ Release" || "$(CFG)" == "timer_test - @PLATFORM@ Debug"
+SOURCE="..\timer_test.c"
+
+!IF "$(CFG)" == "timer_test - @PLATFORM@ Release"
+
+
+"$(INTDIR)\timer_test.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "timer_test - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\timer_test.obj" "$(INTDIR)\timer_test.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tests/win32/timer_test.vcxproj.filters.in b/bin/tests/win32/timer_test.vcxproj.filters.in
new file mode 100644
index 0000000..40a5b36
--- /dev/null
+++ b/bin/tests/win32/timer_test.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\timer_test.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tests/win32/timer_test.vcxproj.in b/bin/tests/win32/timer_test.vcxproj.in
new file mode 100644
index 0000000..f053f0a
--- /dev/null
+++ b/bin/tests/win32/timer_test.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E55653C8-5501-4871-A97C-C926631F40F9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>timer_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\timer_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tests/win32/timer_test.vcxproj.user b/bin/tests/win32/timer_test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tests/win32/timer_test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c
new file mode 100644
index 0000000..f95d2cc
--- /dev/null
+++ b/bin/tests/wire_test.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#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/string.h>
+#include <isc/util.h>
+
+#include <dns/message.h>
+#include <dns/result.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 inline void
+CHECKRESULT(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ printf("%s: %s\n", msg, dns_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);
+ /* NOTREACHED */
+}
+
+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);
+ if (buf == NULL) {
+ result = ISC_R_NOMEMORY;
+ break;
+ }
+
+ 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;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ 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;
+
+ result = isc_buffer_allocate(mctx, &input, 64 * 1024);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ 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);
+
+ if (input != NULL)
+ 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;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
+ CHECKRESULT(result, "dns_message_create failed");
+
+ 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_destroy(&message);
+
+ printf("Message rendered.\n");
+ if (printmemstats)
+ isc_mem_stats(mctx, stdout);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+ &message);
+ CHECKRESULT(result, "dns_message_create failed");
+
+ result = dns_message_parse(message, &buffer, parseflags);
+ CHECKRESULT(result, "dns_message_parse failed");
+
+ result = printmessage(message);
+ CHECKRESULT(result, "printmessage() failed");
+ }
+ dns_message_destroy(&message);
+}
diff --git a/bin/tools/Makefile.in b/bin/tools/Makefile.in
new file mode 100644
index 0000000..7bf2af4
--- /dev/null
+++ b/bin/tools/Makefile.in
@@ -0,0 +1,185 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${LWRES_INCLUDES} \
+ ${BIND9_INCLUDES} @DST_OPENSSL_INC@
+
+CDEFINES = @CRYPTO@ -DVERSION=\"${VERSION}\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+
+LIBS = ${ISCLIBS} @LIBS@
+NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@
+
+SUBDIRS =
+
+DNSTAPTARGETS = dnstap-read@EXEEXT@
+NZDTARGETS = named-nzd2nzf@EXEEXT@
+TARGETS = arpaname@EXEEXT@ named-journalprint@EXEEXT@ \
+ named-rrchecker@EXEEXT@ nsec3hash@EXEEXT@ \
+ genrandom@EXEEXT@ isc-hmac-fixup@EXEEXT@ mdig@EXEEXT@ \
+ @DNSTAPTARGETS@ @NZDTARGETS@
+
+DNSTAPSRCS = dnstap-read.c
+NZDSRCS = named-nzd2nzf.c
+SRCS = arpaname.c named-journalprint.c named-rrchecker.c \
+ nsec3hash.c genrandom.c isc-hmac-fixup.c mdig.c \
+ @DNSTAPSRCS@ @NZDSRCS@
+
+MANPAGES = arpaname.1 dnstap-read.1 genrandom.8 \
+ isc-hmac-fixup.8 mdig.1 named-journalprint.8 \
+ named-nzd2nzf.8 named-rrchecker.1 nsec3hash.8
+
+HTMLPAGES = arpaname.html dnstap-read.html genrandom.html \
+ isc-hmac-fixup.html mdig.html named-journalprint.html \
+ named-nzd2nzf.html named-rrchecker.html nsec3hash.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+arpaname@EXEEXT@: arpaname.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+ -o $@ arpaname.@O@ ${ISCLIBS} ${LIBS}
+
+named-journalprint@EXEEXT@: named-journalprint.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="named-journalprint.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+named-rrchecker@EXEEXT@: named-rrchecker.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="named-rrchecker.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+nsec3hash@EXEEXT@: nsec3hash.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="nsec3hash.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+isc-hmac-fixup@EXEEXT@: isc-hmac-fixup.@O@ ${ISCDEPLIBS}
+ export BASEOBJS="isc-hmac-fixup.@O@"; \
+ export LIBS0="${ISCLIBS}"; \
+ ${FINALBUILDCMD}
+
+genrandom@EXEEXT@: genrandom.@O@
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+ -o $@ genrandom.@O@ @GENRANDOMLIB@ ${LIBS}
+
+mdig@EXEEXT@: mdig.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS}
+ export BASEOBJS="mdig.@O@"; \
+ export LIBS0="${DNSLIBS} ${BIND9LIBS}"; \
+ ${FINALBUILDCMD}
+
+dnstap-read@EXEEXT@: dnstap-read.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="dnstap-read.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+named-nzd2nzf@EXEEXT@: named-nzd2nzf.@O@ ${NZDDEPLIBS}
+ export BASEOBJS="named-nzd2nzf.@O@"; \
+ export LIBS0="${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+nzd:
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-nzd2nzf@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${INSTALL_DATA} ${srcdir}/named-nzd2nzf.8 ${DESTDIR}${mandir}/man8
+
+dnstap:
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} dnstap-read@EXEEXT@ \
+ ${DESTDIR}${bindir}
+ ${INSTALL_DATA} ${srcdir}/dnstap-read.1 ${DESTDIR}${mandir}/man1
+
+install:: ${TARGETS} installdirs @DNSTAP@ @NZD_TOOLS@
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} arpaname@EXEEXT@ \
+ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-journalprint@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-rrchecker@EXEEXT@ \
+ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsec3hash@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} genrandom@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} isc-hmac-fixup@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} mdig@EXEEXT@ \
+ ${DESTDIR}${bindir}
+ ${INSTALL_DATA} ${srcdir}/arpaname.1 ${DESTDIR}${mandir}/man1
+ ${INSTALL_DATA} ${srcdir}/isc-hmac-fixup.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/named-journalprint.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/named-rrchecker.1 ${DESTDIR}${mandir}/man1
+ ${INSTALL_DATA} ${srcdir}/nsec3hash.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/genrandom.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/mdig.1 ${DESTDIR}${mandir}/man1
+
+uninstall::
+ rm -f ${DESTDIR}${mandir}/man1/mdig.1
+ rm -f ${DESTDIR}${mandir}/man8/genrandom.8
+ rm -f ${DESTDIR}${mandir}/man8/nsec3hash.8
+ rm -f ${DESTDIR}${mandir}/man1/named-rrchecker.1
+ rm -f ${DESTDIR}${mandir}/man8/named-journalprint.8
+ rm -f ${DESTDIR}${mandir}/man8/isc-hmac-fixup.8
+ rm -f ${DESTDIR}${mandir}/man1/arpaname.1
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/mdig@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/isc-hmac-fixup@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/genrandom@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/nsec3hash@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/named-rrchecker@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/named-journalprint@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/arpaname@EXEEXT@
+ rm -f ${DESTDIR}${mandir}/man1/dnstap-read.1
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/dnstap-read@EXEEXT@
+ rm -f ${DESTDIR}${mandir}/man8/named-nzd2nzf.8
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/named-nzd2nzf@EXEEXT@
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tools/arpaname.1 b/bin/tools/arpaname.1
new file mode 100644
index 0000000..6948234
--- /dev/null
+++ b/bin/tools/arpaname.1
@@ -0,0 +1,56 @@
+.\" Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: arpaname
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-03-03
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "ARPANAME" "1" "2009\-03\-03" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+arpaname \- translate IP addresses to the corresponding ARPA names
+.SH "SYNOPSIS"
+.HP \w'\fBarpaname\fR\ 'u
+\fBarpaname\fR {\fIipaddress\ \fR...}
+.SH "DESCRIPTION"
+.PP
+\fBarpaname\fR
+translates IP addresses (IPv4 and IPv6) to the corresponding IN\-ADDR\&.ARPA or IP6\&.ARPA names\&.
+.SH "SEE ALSO"
+.PP
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/arpaname.c b/bin/tools/arpaname.c
new file mode 100644
index 0000000..c154ee5
--- /dev/null
+++ b/bin/tools/arpaname.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include "config.h"
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#include <stdio.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.docbook b/bin/tools/arpaname.docbook
new file mode 100644
index 0000000..2ae1ac0
--- /dev/null
+++ b/bin/tools/arpaname.docbook
@@ -0,0 +1,66 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.arpaname">
+ <info>
+ <date>2009-03-03</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle><application>arpaname</application></refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>arpaname</application></refname>
+ <refpurpose>translate IP addresses to the corresponding ARPA names</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>arpaname</command>
+ <arg choice="req" rep="repeat"><replaceable class="parameter">ipaddress </replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>arpaname</command> translates IP addresses (IPv4 and
+ IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/arpaname.html b/bin/tools/arpaname.html
new file mode 100644
index 0000000..c7a0134
--- /dev/null
+++ b/bin/tools/arpaname.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>arpaname</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.arpaname"></a><div class="titlepage"></div>
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">arpaname</span>
+ &#8212; translate IP addresses to the corresponding ARPA names
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">arpaname</code>
+ {<em class="replaceable"><code>ipaddress </code></em>...}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>arpaname</strong></span> translates IP addresses (IPv4 and
+ IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/dnstap-read.1 b/bin/tools/dnstap-read.1
new file mode 100644
index 0000000..6565daf
--- /dev/null
+++ b/bin/tools/dnstap-read.1
@@ -0,0 +1,86 @@
+.\" Copyright (C) 2015, 2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dnstap-read
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2015-09-13
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DNSTAP\-READ" "1" "2015\-09\-13" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dnstap-read \- print dnstap data in human\-readable form
+.SH "SYNOPSIS"
+.HP \w'\fBdnstap\-read\fR\ 'u
+\fBdnstap\-read\fR [\fB\-m\fR] [\fB\-p\fR] [\fB\-y\fR] {\fIfile\fR}
+.SH "DESCRIPTION"
+.PP
+\fBdnstap\-read\fR
+reads
+\fBdnstap\fR
+data from a specified file and prints it in a human\-readable format\&. By default,
+\fBdnstap\fR
+data is printed in a short summary format, but if the
+\fB\-y\fR
+option is specified, then a longer and more detailed YAML format is used instead\&.
+.SH "OPTIONS"
+.PP
+\-m
+.RS 4
+Trace memory allocations; used for debugging memory leaks\&.
+.RE
+.PP
+\-p
+.RS 4
+After printing the
+\fBdnstap\fR
+data, print the text form of the DNS message that was encapsulated in the
+\fBdnstap\fR
+frame\&.
+.RE
+.PP
+\-y
+.RS 4
+Print
+\fBdnstap\fR
+data in a detailed YAML format\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBrndc\fR(8),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2015, 2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c
new file mode 100644
index 0000000..4cafdb4
--- /dev/null
+++ b/bin/tools/dnstap-read.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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 <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.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 <dns/result.h>
+
+isc_mem_t *mctx = NULL;
+bool memrecord = false;
+bool printmessage = 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)
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
+
+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 [-mp] [filename]\n");
+ fprintf(stderr, "\t-m\ttrace memory allocations\n");
+ fprintf(stderr, "\t-p\tprint the full 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_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) {
+ 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) {
+ 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, "mpy")) != -1) {
+ switch (ch) {
+ case 'm':
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ memrecord = true;
+ break;
+ case 'p':
+ printmessage = true;
+ break;
+ case 'y':
+ yaml = true;
+ dns_master_indentstr = " ";
+ dns_master_indent = 2;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1)
+ fatal("no file specified");
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ 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 (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_destroy(&message);
+ if (b != NULL)
+ isc_buffer_free(&b);
+ isc_mem_destroy(&mctx);
+
+ exit(rv);
+}
diff --git a/bin/tools/dnstap-read.docbook b/bin/tools/dnstap-read.docbook
new file mode 100644
index 0000000..81b7add
--- /dev/null
+++ b/bin/tools/dnstap-read.docbook
@@ -0,0 +1,115 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnstap-read">
+ <info>
+ <date>2015-09-13</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnstap-read</application></refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnstap-read</application></refname>
+ <refpurpose>print dnstap data in human-readable form</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dnstap-read</command>
+ <arg choice="opt" rep="norepeat"><option>-m</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-y</option></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">file</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>dnstap-read</command>
+ reads <command>dnstap</command> data from a specified file
+ and prints it in a human-readable format. By default,
+ <command>dnstap</command> data is printed in a short summary
+ format, but if the <option>-y</option> option is specified,
+ then a longer and more detailed YAML format is used instead.
+ </para>
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-m</term>
+ <listitem>
+ <para>
+ Trace memory allocations; used for debugging memory leaks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p</term>
+ <listitem>
+ <para>
+ After printing the <command>dnstap</command> data, print
+ the text form of the DNS message that was encapsulated in the
+ <command>dnstap</command> frame.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y</term>
+ <listitem>
+ <para>
+ Print <command>dnstap</command> data in a detailed YAML
+ format.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/dnstap-read.html b/bin/tools/dnstap-read.html
new file mode 100644
index 0000000..2e3bdc0
--- /dev/null
+++ b/bin/tools/dnstap-read.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2015, 2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnstap-read</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dnstap-read"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">dnstap-read</span>
+ &#8212; print dnstap data in human-readable form
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dnstap-read</code>
+ [<code class="option">-m</code>]
+ [<code class="option">-p</code>]
+ [<code class="option">-y</code>]
+ {<em class="replaceable"><code>file</code></em>}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>dnstap-read</strong></span>
+ reads <span class="command"><strong>dnstap</strong></span> data from a specified file
+ and prints it in a human-readable format. By default,
+ <span class="command"><strong>dnstap</strong></span> data is printed in a short summary
+ format, but if the <code class="option">-y</code> option is specified,
+ then a longer and more detailed YAML format is used instead.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-m</span></dt>
+<dd>
+ <p>
+ Trace memory allocations; used for debugging memory leaks.
+ </p>
+ </dd>
+<dt><span class="term">-p</span></dt>
+<dd>
+ <p>
+ After printing the <span class="command"><strong>dnstap</strong></span> data, print
+ the text form of the DNS message that was encapsulated in the
+ <span class="command"><strong>dnstap</strong></span> frame.
+ </p>
+ </dd>
+<dt><span class="term">-y</span></dt>
+<dd>
+ <p>
+ Print <span class="command"><strong>dnstap</strong></span> data in a detailed YAML
+ format.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">rndc</span>(8)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/genrandom.8 b/bin/tools/genrandom.8
new file mode 100644
index 0000000..f946510
--- /dev/null
+++ b/bin/tools/genrandom.8
@@ -0,0 +1,77 @@
+.\" Copyright (C) 2009-2011, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: genrandom
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2011-08-08
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "GENRANDOM" "8" "2011\-08\-08" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+genrandom \- generate a file containing random data
+.SH "SYNOPSIS"
+.HP \w'\fBgenrandom\fR\ 'u
+\fBgenrandom\fR [\fB\-n\ \fR\fB\fInumber\fR\fR] {\fIsize\fR} {\fIfilename\fR}
+.SH "DESCRIPTION"
+.PP
+\fBgenrandom\fR
+generates a file or a set of files containing a specified quantity of pseudo\-random data, which can be used as a source of entropy for other commands on systems with no random device\&.
+.SH "ARGUMENTS"
+.PP
+\-n \fInumber\fR
+.RS 4
+In place of generating one file, generates
+\fBnumber\fR
+(from 2 to 9) files, appending
+\fBnumber\fR
+to the name\&.
+.RE
+.PP
+size
+.RS 4
+The size of the file, in kilobytes, to generate\&.
+.RE
+.PP
+filename
+.RS 4
+The file name into which random data should be written\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBrand\fR(3),
+\fBarc4random\fR(3)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009-2011, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/genrandom.c b/bin/tools/genrandom.c
new file mode 100644
index 0000000..cedd13d
--- /dev/null
+++ b/bin/tools/genrandom.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+#include <config.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/stdlib.h>
+#include <isc/util.h>
+
+#include <stdio.h>
+#include <string.h>
+
+const char *program = "genrandom";
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: %s [-n 2..9] k file\n", program);
+ exit(1);
+}
+
+static void
+generate(char *filename, unsigned int bytes) {
+ FILE *fp;
+
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ printf("failed to open %s\n", filename);
+ exit(1);
+ }
+
+ while (bytes > 0) {
+#ifndef HAVE_ARC4RANDOM
+ unsigned short int x = (rand() & 0xFFFF);
+#else
+ unsigned short int x = (arc4random() & 0xFFFF);
+#endif
+ unsigned char c = x & 0xFF;
+ if (putc(c, fp) == EOF) {
+ printf("error writing to %s\n", filename);
+ exit(1);
+ }
+ c = x >> 8;
+ if (putc(c, fp) == EOF) {
+ printf("error writing to %s\n", filename);
+ exit(1);
+ }
+ bytes -= 2;
+ }
+ fclose(fp);
+}
+
+int
+main(int argc, char **argv) {
+ unsigned int bytes;
+ unsigned int k;
+ char *endp;
+ int c, i, n = 1;
+ size_t len;
+ char *name;
+
+ isc_commandline_errprint = false;
+
+ while ((c = isc_commandline_parse(argc, argv, "hn:")) != EOF) {
+ switch (c) {
+ case 'n':
+ n = strtol(isc_commandline_argument, &endp, 10);
+ if ((*endp != 0) || (n <= 1) || (n > 9))
+ usage();
+ 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 (isc_commandline_index + 2 != argc)
+ usage();
+
+ k = strtoul(argv[isc_commandline_index++], &endp, 10);
+ if (*endp != 0)
+ usage();
+ bytes = k << 10;
+
+#ifndef HAVE_ARC4RANDOM
+ srand(0x12345678);
+#endif
+ if (n == 1) {
+ generate(argv[isc_commandline_index], bytes);
+ return (0);
+ }
+
+ len = strlen(argv[isc_commandline_index]);
+ INSIST((len + 2) > len);
+ len += 2;
+ name = (char *) malloc(len);
+ if (name == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ for (i = 1; i <= n; i++) {
+ snprintf(name, len, "%s%d", argv[isc_commandline_index], i);
+ generate(name, bytes);
+ }
+ free(name);
+
+ return (0);
+}
diff --git a/bin/tools/genrandom.docbook b/bin/tools/genrandom.docbook
new file mode 100644
index 0000000..4fa1d3c
--- /dev/null
+++ b/bin/tools/genrandom.docbook
@@ -0,0 +1,111 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.genrandom">
+ <info>
+ <date>2011-08-08</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>genrandom</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>genrandom</application></refname>
+ <refpurpose>generate a file containing random data</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>genrandom</command>
+ <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">number</replaceable></option></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">size</replaceable></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">filename</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>genrandom</command>
+ generates a file or a set of files containing a specified quantity
+ of pseudo-random data, which can be used as a source of entropy for
+ other commands on systems with no random device.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>-n <replaceable class="parameter">number</replaceable></term>
+ <listitem>
+ <para>
+ In place of generating one file, generates <option>number</option>
+ (from 2 to 9) files, appending <option>number</option> to the name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>size</term>
+ <listitem>
+ <para>
+ The size of the file, in kilobytes, to generate.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>filename</term>
+ <listitem>
+ <para>
+ The file name into which random data should be written.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>rand</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>arc4random</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/genrandom.html b/bin/tools/genrandom.html
new file mode 100644
index 0000000..e6a5c0a
--- /dev/null
+++ b/bin/tools/genrandom.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009-2011, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>genrandom</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.genrandom"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">genrandom</span>
+ &#8212; generate a file containing random data
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">genrandom</code>
+ [<code class="option">-n <em class="replaceable"><code>number</code></em></code>]
+ {<em class="replaceable"><code>size</code></em>}
+ {<em class="replaceable"><code>filename</code></em>}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>genrandom</strong></span>
+ generates a file or a set of files containing a specified quantity
+ of pseudo-random data, which can be used as a source of entropy for
+ other commands on systems with no random device.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-n <em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ In place of generating one file, generates <code class="option">number</code>
+ (from 2 to 9) files, appending <code class="option">number</code> to the name.
+ </p>
+ </dd>
+<dt><span class="term">size</span></dt>
+<dd>
+ <p>
+ The size of the file, in kilobytes, to generate.
+ </p>
+ </dd>
+<dt><span class="term">filename</span></dt>
+<dd>
+ <p>
+ The file name into which random data should be written.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">rand</span>(3)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">arc4random</span>(3)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/isc-hmac-fixup.8 b/bin/tools/isc-hmac-fixup.8
new file mode 100644
index 0000000..3124159
--- /dev/null
+++ b/bin/tools/isc-hmac-fixup.8
@@ -0,0 +1,69 @@
+.\" Copyright (C) 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: isc-hmac-fixup
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2013-04-28
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "ISC\-HMAC\-FIXUP" "8" "2013\-04\-28" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+isc-hmac-fixup \- fixes HMAC keys generated by older versions of BIND
+.SH "SYNOPSIS"
+.HP \w'\fBisc\-hmac\-fixup\fR\ 'u
+\fBisc\-hmac\-fixup\fR {\fIalgorithm\fR} {\fIsecret\fR}
+.SH "DESCRIPTION"
+.PP
+Versions of BIND 9 up to and including BIND 9\&.6 had a bug causing HMAC\-SHA* TSIG keys which were longer than the digest length of the hash algorithm (i\&.e\&., SHA1 keys longer than 160 bits, SHA256 keys longer than 256 bits, etc) to be used incorrectly, generating a message authentication code that was incompatible with other DNS implementations\&.
+.PP
+This bug was fixed in BIND 9\&.7\&. However, the fix may cause incompatibility between older and newer versions of BIND, when using long keys\&.
+\fBisc\-hmac\-fixup\fR
+modifies those keys to restore compatibility\&.
+.PP
+To modify a key, run
+\fBisc\-hmac\-fixup\fR
+and specify the key\*(Aqs algorithm and secret on the command line\&. If the secret is longer than the digest length of the algorithm (64 bytes for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a new secret will be generated consisting of a hash digest of the old secret\&. (If the secret did not require conversion, then it will be printed without modification\&.)
+.SH "SECURITY CONSIDERATIONS"
+.PP
+Secrets that have been converted by
+\fBisc\-hmac\-fixup\fR
+are shortened, but as this is how the HMAC protocol works in operation anyway, it does not affect security\&. RFC 2104 notes, "Keys longer than [the digest length] are acceptable but the extra length would not significantly increase the function strength\&."
+.SH "SEE ALSO"
+.PP
+BIND 9 Administrator Reference Manual,
+RFC 2104\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/isc-hmac-fixup.c b/bin/tools/isc-hmac-fixup.c
new file mode 100644
index 0000000..27e9fbb
--- /dev/null
+++ b/bin/tools/isc-hmac-fixup.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id: isc-hmac-fixup.c,v 1.4 2010/03/10 02:17:52 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/md5.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+
+#include <pk11/site.h>
+
+#define HMAC_LEN 64
+
+int
+main(int argc, char **argv) {
+ isc_buffer_t buf;
+ unsigned char key[1024];
+ char secret[1024];
+ char base64[(1024*4)/3];
+ isc_region_t r;
+ isc_result_t result;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage:\t%s algorithm secret\n", argv[0]);
+#ifndef PK11_MD5_DISABLE
+ fprintf(stderr, "\talgorithm: (MD5 | SHA1 | SHA224 | "
+ "SHA256 | SHA384 | SHA512)\n");
+#else
+ fprintf(stderr, "\talgorithm: (SHA1 | SHA224 | "
+ "SHA256 | SHA384 | SHA512)\n");
+#endif
+ return (1);
+ }
+
+ isc_buffer_init(&buf, secret, sizeof(secret));
+ result = isc_base64_decodestring(argv[2], &buf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "error: %s\n", isc_result_totext(result));
+ return (1);
+ }
+ isc_buffer_usedregion(&buf, &r);
+
+#ifndef PK11_MD5_DISABLE
+ if (!strcasecmp(argv[1], "md5") ||
+ !strcasecmp(argv[1], "hmac-md5")) {
+ if (r.length > HMAC_LEN) {
+ isc_md5_t md5ctx;
+ isc_md5_init(&md5ctx);
+ isc_md5_update(&md5ctx, r.base, r.length);
+ isc_md5_final(&md5ctx, key);
+
+ r.base = key;
+ r.length = ISC_MD5_DIGESTLENGTH;
+ }
+ } else
+#endif
+ if (!strcasecmp(argv[1], "sha1") ||
+ !strcasecmp(argv[1], "hmac-sha1")) {
+ if (r.length > ISC_SHA1_DIGESTLENGTH) {
+ isc_sha1_t sha1ctx;
+ isc_sha1_init(&sha1ctx);
+ isc_sha1_update(&sha1ctx, r.base, r.length);
+ isc_sha1_final(&sha1ctx, key);
+
+ r.base = key;
+ r.length = ISC_SHA1_DIGESTLENGTH;
+ }
+ } else if (!strcasecmp(argv[1], "sha224") ||
+ !strcasecmp(argv[1], "hmac-sha224")) {
+ if (r.length > ISC_SHA224_DIGESTLENGTH) {
+ isc_sha224_t sha224ctx;
+ isc_sha224_init(&sha224ctx);
+ isc_sha224_update(&sha224ctx, r.base, r.length);
+ isc_sha224_final(key, &sha224ctx);
+
+ r.base = key;
+ r.length = ISC_SHA224_DIGESTLENGTH;
+ }
+ } else if (!strcasecmp(argv[1], "sha256") ||
+ !strcasecmp(argv[1], "hmac-sha256")) {
+ if (r.length > ISC_SHA256_DIGESTLENGTH) {
+ isc_sha256_t sha256ctx;
+ isc_sha256_init(&sha256ctx);
+ isc_sha256_update(&sha256ctx, r.base, r.length);
+ isc_sha256_final(key, &sha256ctx);
+
+ r.base = key;
+ r.length = ISC_SHA256_DIGESTLENGTH;
+ }
+ } else if (!strcasecmp(argv[1], "sha384") ||
+ !strcasecmp(argv[1], "hmac-sha384")) {
+ if (r.length > ISC_SHA384_DIGESTLENGTH) {
+ isc_sha384_t sha384ctx;
+ isc_sha384_init(&sha384ctx);
+ isc_sha384_update(&sha384ctx, r.base, r.length);
+ isc_sha384_final(key, &sha384ctx);
+
+ r.base = key;
+ r.length = ISC_SHA384_DIGESTLENGTH;
+ }
+ } else if (!strcasecmp(argv[1], "sha512") ||
+ !strcasecmp(argv[1], "hmac-sha512")) {
+ if (r.length > ISC_SHA512_DIGESTLENGTH) {
+ isc_sha512_t sha512ctx;
+ isc_sha512_init(&sha512ctx);
+ isc_sha512_update(&sha512ctx, r.base, r.length);
+ isc_sha512_final(key, &sha512ctx);
+
+ r.base = key;
+ r.length = ISC_SHA512_DIGESTLENGTH;
+ }
+ } else {
+ fprintf(stderr, "unknown hmac/digest algorithm: %s\n", argv[1]);
+ return (1);
+ }
+
+ isc_buffer_init(&buf, base64, sizeof(base64));
+ result = isc_base64_totext(&r, 0, "", &buf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "error: %s\n", isc_result_totext(result));
+ return (1);
+ }
+ fprintf(stdout, "%.*s\n", (int)isc_buffer_usedlength(&buf), base64);
+ return (0);
+}
diff --git a/bin/tools/isc-hmac-fixup.docbook b/bin/tools/isc-hmac-fixup.docbook
new file mode 100644
index 0000000..ecf32f3
--- /dev/null
+++ b/bin/tools/isc-hmac-fixup.docbook
@@ -0,0 +1,102 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.isc-hmac-fixup">
+ <info>
+ <date>2013-04-28</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>isc-hmac-fixup</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>isc-hmac-fixup</application></refname>
+ <refpurpose>fixes HMAC keys generated by older versions of BIND</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2010</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>isc-hmac-fixup</command>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">secret</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ Versions of BIND 9 up to and including BIND 9.6 had a bug causing
+ HMAC-SHA* TSIG keys which were longer than the digest length of the
+ hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys
+ longer than 256 bits, etc) to be used incorrectly, generating a
+ message authentication code that was incompatible with other DNS
+ implementations.
+ </para>
+ <para>
+ This bug was fixed in BIND 9.7. However, the fix may
+ cause incompatibility between older and newer versions of
+ BIND, when using long keys. <command>isc-hmac-fixup</command>
+ modifies those keys to restore compatibility.
+ </para>
+ <para>
+ To modify a key, run <command>isc-hmac-fixup</command> and
+ specify the key's algorithm and secret on the command line. If the
+ secret is longer than the digest length of the algorithm (64 bytes
+ for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a
+ new secret will be generated consisting of a hash digest of the old
+ secret. (If the secret did not require conversion, then it will be
+ printed without modification.)
+ </para>
+ </refsection>
+
+ <refsection><info><title>SECURITY CONSIDERATIONS</title></info>
+
+ <para>
+ Secrets that have been converted by <command>isc-hmac-fixup</command>
+ are shortened, but as this is how the HMAC protocol works in
+ operation anyway, it does not affect security. RFC 2104 notes,
+ "Keys longer than [the digest length] are acceptable but the
+ extra length would not significantly increase the function
+ strength."
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2104</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/isc-hmac-fixup.html b/bin/tools/isc-hmac-fixup.html
new file mode 100644
index 0000000..dc1bb8a
--- /dev/null
+++ b/bin/tools/isc-hmac-fixup.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>isc-hmac-fixup</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.isc-hmac-fixup"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">isc-hmac-fixup</span>
+ &#8212; fixes HMAC keys generated by older versions of BIND
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">isc-hmac-fixup</code>
+ {<em class="replaceable"><code>algorithm</code></em>}
+ {<em class="replaceable"><code>secret</code></em>}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ Versions of BIND 9 up to and including BIND 9.6 had a bug causing
+ HMAC-SHA* TSIG keys which were longer than the digest length of the
+ hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys
+ longer than 256 bits, etc) to be used incorrectly, generating a
+ message authentication code that was incompatible with other DNS
+ implementations.
+ </p>
+ <p>
+ This bug was fixed in BIND 9.7. However, the fix may
+ cause incompatibility between older and newer versions of
+ BIND, when using long keys. <span class="command"><strong>isc-hmac-fixup</strong></span>
+ modifies those keys to restore compatibility.
+ </p>
+ <p>
+ To modify a key, run <span class="command"><strong>isc-hmac-fixup</strong></span> and
+ specify the key's algorithm and secret on the command line. If the
+ secret is longer than the digest length of the algorithm (64 bytes
+ for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a
+ new secret will be generated consisting of a hash digest of the old
+ secret. (If the secret did not require conversion, then it will be
+ printed without modification.)
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SECURITY CONSIDERATIONS</h2>
+
+ <p>
+ Secrets that have been converted by <span class="command"><strong>isc-hmac-fixup</strong></span>
+ are shortened, but as this is how the HMAC protocol works in
+ operation anyway, it does not affect security. RFC 2104 notes,
+ "Keys longer than [the digest length] are acceptable but the
+ extra length would not significantly increase the function
+ strength."
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2104</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/mdig.1 b/bin/tools/mdig.1
new file mode 100644
index 0000000..4affcea
--- /dev/null
+++ b/bin/tools/mdig.1
@@ -0,0 +1,408 @@
+.\" Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: mdig
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2015-01-05
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "MDIG" "1" "2015\-01\-05" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+mdig \- DNS pipelined lookup utility
+.SH "SYNOPSIS"
+.HP \w'\fBmdig\fR\ 'u
+\fBmdig\fR {@server} [\fB\-f\ \fR\fB\fIfilename\fR\fR] [\fB\-h\fR] [\fB\-v\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-m\fR] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-i\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [plusopt...]
+.HP \w'\fBmdig\fR\ 'u
+\fBmdig\fR {\-h}
+.HP \w'\fBmdig\fR\ 'u
+\fBmdig\fR [@server] {global\-opt...} {{local\-opt...}\ {query}...}
+.SH "DESCRIPTION"
+.PP
+\fBmdig\fR
+is a multiple/pipelined query version of
+\fBdig\fR: 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\&.
+.PP
+\fBmdig\fR
+options are a subset of the
+\fBdig\fR
+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\&.
+.PP
+The
+{@server}
+option is a mandatory global option\&. It is the name or IP address of the name server to query\&. (Unlike
+\fBdig\fR, 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
+\fIserver\fR
+argument is a hostname,
+\fBmdig\fR
+resolves that name before querying the name server\&.
+.PP
+\fBmdig\fR
+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\&.
+.PP
+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
+\fB+keyword=value\fR\&.
+.SH "ANYWHERE OPTIONS"
+.PP
+The
+\fB\-f\fR
+option makes
+\fBmdig\fR
+operate in batch mode by reading a list of lookup requests to process from the file
+\fIfilename\fR\&. 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
+\fBmdig\fR
+using the command\-line interface\&.
+.PP
+The
+\fB\-h\fR
+causes
+\fBmdig\fR
+to print the detailed help with the full list of options and exit\&.
+.PP
+The
+\fB\-v\fR
+causes
+\fBmdig\fR
+to print the version number and exit\&.
+.SH "GLOBAL OPTIONS"
+.PP
+The
+\fB\-4\fR
+option forces
+\fBmdig\fR
+to only use IPv4 query transport\&.
+.PP
+The
+\fB\-6\fR
+option forces
+\fBmdig\fR
+to only use IPv6 query transport\&.
+.PP
+The
+\fB\-b\fR
+option sets the source IP address of the query to
+\fIaddress\fR\&. This must be a valid address on one of the host\*(Aqs network interfaces or "0\&.0\&.0\&.0" or "::"\&. An optional port may be specified by appending "#<port>"
+.PP
+The
+\fB\-m\fR
+option enables memory usage debugging\&.
+.PP
+The
+\fB\-p\fR
+option is used when a non\-standard port number is to be queried\&.
+\fIport#\fR
+is the port number that
+\fBmdig\fR
+will send its queries instead of the standard DNS port number 53\&. This option would be used to test a name server that has been configured to listen for queries on a non\-standard port number\&.
+.PP
+The global query options are:
+.PP
+\fB+[no]additional\fR
+.RS 4
+Display [do not display] the additional section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]all\fR
+.RS 4
+Set or clear all display flags\&.
+.RE
+.PP
+\fB+[no]answer\fR
+.RS 4
+Display [do not display] the answer section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]authority\fR
+.RS 4
+Display [do not display] the authority section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]besteffort\fR
+.RS 4
+Attempt to display the contents of messages which are malformed\&. The default is to not display malformed answers\&.
+.RE
+.PP
+\fB+[no]cl\fR
+.RS 4
+Display [do not display] the CLASS when printing the record\&.
+.RE
+.PP
+\fB+[no]comments\fR
+.RS 4
+Toggle the display of comment lines in the output\&. The default is to print comments\&.
+.RE
+.PP
+\fB+[no]continue\fR
+.RS 4
+Continue on errors (e\&.g\&. timeouts)\&.
+.RE
+.PP
+\fB+[no]crypto\fR
+.RS 4
+Toggle the display of cryptographic fields in DNSSEC records\&. The contents of these field 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 ]"\&.
+.RE
+.PP
+\fB+dscp[=value]\fR
+.RS 4
+Set the DSCP code point to be used when sending the query\&. Valid DSCP code points are in the range [0\&.\&.63]\&. By default no code point is explicitly set\&.
+.RE
+.PP
+\fB+[no]multiline\fR
+.RS 4
+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
+\fBmdig\fR
+output\&.
+.RE
+.PP
+\fB+[no]question\fR
+.RS 4
+Print [do not print] the question section of a query when an answer is returned\&. The default is to print the question section as a comment\&.
+.RE
+.PP
+\fB+[no]rrcomments\fR
+.RS 4
+Toggle 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\&.
+.RE
+.PP
+\fB+[no]short\fR
+.RS 4
+Provide a terse answer\&. The default is to print the answer in a verbose form\&.
+.RE
+.PP
+\fB+split=W\fR
+.RS 4
+Split long hex\- or base64\-formatted fields in resource records into chunks of
+\fIW\fR
+characters (where
+\fIW\fR
+is rounded up to the nearest multiple of 4)\&.
+\fI+nosplit\fR
+or
+\fI+split=0\fR
+causes fields not to be split at all\&. The default is 56 characters, or 44 characters when multiline mode is active\&.
+.RE
+.PP
+\fB+[no]tcp\fR
+.RS 4
+Use [do not use] TCP when querying name servers\&. The default behavior is to use UDP\&.
+.RE
+.PP
+\fB+[no]ttlid\fR
+.RS 4
+Display [do not display] the TTL when printing the record\&.
+.RE
+.PP
+\fB+[no]ttlunits\fR
+.RS 4
+Display [do not display] the TTL in friendly human\-readable time units of "s", "m", "h", "d", and "w", representing seconds, minutes, hours, days and weeks\&. Implies +ttlid\&.
+.RE
+.PP
+\fB+[no]vc\fR
+.RS 4
+Use [do not use] TCP when querying name servers\&. This alternate syntax to
+\fI+[no]tcp\fR
+is provided for backwards compatibility\&. The "vc" stands for "virtual circuit"\&.
+.RE
+.SH "LOCAL OPTIONS"
+.PP
+The
+\fB\-c\fR
+option sets the query class to
+\fIclass\fR\&. It can be any valid query class which is supported in BIND 9\&. The default query class is "IN"\&.
+.PP
+The
+\fB\-t\fR
+option sets the query type to
+\fItype\fR\&. It can be any valid query type which is supported in BIND 9\&. The default query type is "A", unless the
+\fB\-x\fR
+option is supplied to indicate a reverse lookup with the "PTR" query type\&.
+.PP
+The
+\fB\-i\fR
+option sets the reverse domain for IPv6 addresses to IP6\&.INT\&.
+.PP
+Reverse lookups \(em mapping addresses to names \(em are simplified by the
+\fB\-x\fR
+option\&.
+\fIaddr\fR
+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address\&.
+\fBmdig\fR
+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\&. To use the older RFC1886 method using the IP6\&.INT domain specify the
+\fB\-i\fR
+option\&.
+.PP
+The local query options are:
+.PP
+\fB+[no]aaflag\fR
+.RS 4
+A synonym for
+\fI+[no]aaonly\fR\&.
+.RE
+.PP
+\fB+[no]aaonly\fR
+.RS 4
+Sets the "aa" flag in the query\&.
+.RE
+.PP
+\fB+[no]adflag\fR
+.RS 4
+Set [do 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 indicate that some part of the answer was insecure or not validated\&. This bit is set by default\&.
+.RE
+.PP
+\fB+bufsize=B\fR
+.RS 4
+Set the UDP message buffer size advertised using EDNS0 to
+\fIB\fR
+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 will cause a EDNS query to be sent\&.
+.RE
+.PP
+\fB+[no]cdflag\fR
+.RS 4
+Set [do not set] the CD (checking disabled) bit in the query\&. This requests the server to not perform DNSSEC validation of responses\&.
+.RE
+.PP
+\fB+[no]cookie\fR\fB[=####]\fR
+.RS 4
+Send a COOKIE EDNS option, with optional value\&. Replaying a COOKIE from a previous response will allow the server to identify a previous client\&. The default is
+\fB+nocookie\fR\&.
+.RE
+.PP
+\fB+[no]dnssec\fR
+.RS 4
+Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query\&.
+.RE
+.PP
+\fB+[no]edns[=#]\fR
+.RS 4
+Specify the EDNS version to query with\&. Valid values are 0 to 255\&. Setting the EDNS version will cause a EDNS query to be sent\&.
+\fB+noedns\fR
+clears the remembered EDNS version\&. EDNS is set to 0 by default\&.
+.RE
+.PP
+\fB+[no]ednsflags[=#]\fR
+.RS 4
+Set 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) will silently be ignored\&. By default, no Z bits are set\&.
+.RE
+.PP
+\fB+[no]ednsopt[=code[:value]]\fR
+.RS 4
+Specify EDNS option with code point
+\fBcode\fR
+and optionally payload of
+\fBvalue\fR
+as a hexadecimal string\&.
+\fB+noednsopt\fR
+clears the EDNS options to be sent\&.
+.RE
+.PP
+\fB+[no]expire\fR
+.RS 4
+Send an EDNS Expire option\&.
+.RE
+.PP
+\fB+[no]nsid\fR
+.RS 4
+Include an EDNS name server ID request when sending a query\&.
+.RE
+.PP
+\fB+[no]recurse\fR
+.RS 4
+Toggle the setting of the RD (recursion desired) bit in the query\&. This bit is set by default, which means
+\fBmdig\fR
+normally sends recursive queries\&.
+.RE
+.PP
+\fB+retry=T\fR
+.RS 4
+Sets the number of times to retry UDP queries to server to
+\fIT\fR
+instead of the default, 2\&. Unlike
+\fI+tries\fR, this does not include the initial query\&.
+.RE
+.PP
+\fB+[no]subnet=addr[/prefix\-length]\fR
+.RS 4
+Send (don\*(Aqt send) an EDNS Client Subnet option with the specified IP address or network prefix\&.
+.sp
+\fBmdig +subnet=0\&.0\&.0\&.0/0\fR, or simply
+\fBmdig +subnet=0\fR
+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\*(Aqs address information must
+\fInot\fR
+be used when resolving this query\&.
+.RE
+.PP
+\fB+timeout=T\fR
+.RS 4
+Sets the timeout for a query to
+\fIT\fR
+seconds\&. The default timeout is 5 seconds for UDP transport and 10 for TCP\&. An attempt to set
+\fIT\fR
+to less than 1 will result in a query timeout of 1 second being applied\&.
+.RE
+.PP
+\fB+tries=T\fR
+.RS 4
+Sets the number of times to try UDP queries to server to
+\fIT\fR
+instead of the default, 3\&. If
+\fIT\fR
+is less than or equal to zero, the number of tries is silently rounded up to 1\&.
+.RE
+.PP
+\fB+udptimeout=T\fR
+.RS 4
+Sets the timeout between UDP query retries\&.
+.RE
+.PP
+\fB+[no]unknownformat\fR
+.RS 4
+Print all RDATA in unknown RR type presentation format (RFC 3597)\&. The default is to print RDATA for known types in the type\*(Aqs presentation format\&.
+.RE
+.PP
+\fB+[no]zflag\fR
+.RS 4
+Set [do not set] the last unassigned DNS header flag in a DNS query\&. This flag is off by default\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+RFC1035\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2015-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c
new file mode 100644
index 0000000..4876875
--- /dev/null
+++ b/bin/tools/mdig.c
@@ -0,0 +1,2081 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/rdataclass.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <dns/events.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/types.h>
+
+#include <dst/result.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;
+static dns_requestmgr_t *requestmgr;
+static const char *batchname;
+static FILE *batchfp;
+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 bool display_rrcomments = true;
+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 continue_on_error = false;
+static uint32_t display_splitwidth = 0xffffffff;
+static isc_sockaddr_t srcaddr;
+static char *server;
+static isc_sockaddr_t dstaddr;
+static in_port_t port = 53;
+static isc_dscp_t dscp = -1;
+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 ip6_int;
+ 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 *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);
+ }
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
+ if (besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+ result = dns_request_getresponse(reqev->request, response, parseflags);
+ CHECK("dns_request_getresponse", result);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (display_comments)
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ if (display_unknown_format)
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ if (display_rrcomments)
+ 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;
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (display_multiline || (!display_ttl && !display_class))
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 24, 32, 80, 8,
+ display_splitwidth, mctx);
+ else if (!display_ttl || !display_class)
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 32, 40, 80, 8,
+ display_splitwidth, mctx);
+ else
+ result = dns_master_stylecreate2(&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;
+
+ result = isc_buffer_allocate(mctx, &buf, len);
+ CHECK("isc_buffer_allocate", result);
+
+ 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);
+ result = isc_buffer_allocate(mctx, &buf, len);
+ if (result == ISC_R_SUCCESS)
+ goto repopulate_buffer;
+ else
+ goto cleanup;
+ }
+ 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)
+ 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_destroy(&query);
+ if (response != NULL)
+ dns_message_destroy(&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;
+ dns_message_t *message;
+ dns_name_t *qname;
+ dns_rdataset_t *qrdataset;
+ 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);
+
+ message = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+ CHECK("dns_message_create", result);
+
+ 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);
+
+ qname = NULL;
+ result = dns_message_gettempname(message, &qname);
+ CHECK("dns_message_gettempname", result);
+
+ qrdataset = NULL;
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ CHECK("dns_message_gettemprdataset", result);
+
+ dns_name_init(qname, NULL);
+ 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 = 4096;
+ 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 | DNS_REQUESTOPT_SHARE;
+ request = NULL;
+ result = dns_request_createvia4(requestmgr, message,
+ have_src ? &srcaddr : NULL, &dstaddr,
+ dscp, options, NULL,
+ query->timeout, query->udptimeout,
+ query->udpretries, task,
+ recvresponse, message, &request);
+ CHECK("dns_request_createvia4", 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;
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fputs("Usage: mdig @server {global-opt} host\n"
+ " {local-opt} [ host {local-opt} [...]]\n",
+ stderr);
+ fputs("\nUse \"mdig -h\" (or \"mdig -h | more\") "
+ "for complete list of options\n",
+ stderr);
+ exit(1);
+}
+
+/*% help */
+static void
+help(void) {
+ fputs("Usage: mdig @server {global-opt} host\n"
+ " {local-opt} [ host {local-opt} [...]]\n",
+ stdout);
+ fputs(
+"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]dscp[=###] (Set the DSCP value to ### [0..63])\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"
+" -i (use IP6.INT for IPv6 reverse lookups)\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",
+ stdout);
+}
+
+static char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+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);
+ if (query->ednsopts == NULL)
+ fatal("out of memory");
+
+ 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);
+ if (buf == NULL) {
+ fatal("out of memory");
+ }
+ 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_result_t result = ISC_R_SUCCESS;
+ 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) {
+ *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 (sa == NULL)
+ fatal("out of memory");
+ 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,
+ bool ip6_int)
+{
+ 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;
+
+ if (ip6_int)
+ options |= DNS_BYADDROPT_IPV6INT;
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname2(&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 option_store[256];
+ char *cmd, *value, *ptr, *code;
+ uint32_t num;
+ bool state = true;
+ size_t n;
+
+ strlcpy(option_store, option, sizeof(option_store));
+ ptr = option_store;
+ cmd = next_token(&ptr, "=");
+ if (cmd == NULL) {
+ printf(";; Invalid option %s\n", option_store);
+ return;
+ }
+ value = ptr;
+ if (strncasecmp(cmd, "no", 2) == 0) {
+ cmd += 2;
+ state = false;
+ }
+
+#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;
+ 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':/* 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;
+ 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 */
+ FULLCHECK("dscp");
+ GLOBAL();
+ if (!state) {
+ dscp = -1;
+ break;
+ }
+ if (value == NULL)
+ goto need_value;
+ result = parse_uint(&num, value, 0x3f, "DSCP");
+ CHECK("parse_uint(DSCP)", result);
+ dscp = num;
+ 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 = next_token(&value, ":");
+ if (code == NULL) {
+ fatal("ednsopt no "
+ "code point "
+ "specified");
+ }
+ 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);
+ query->udpretries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("rrcomments");
+ GLOBAL();
+ display_rrcomments = state;
+ 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 = false;
+ }
+ 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 '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");
+ /* NOTREACHED */
+ return (false);
+ }
+ break;
+ case '6':
+ GLOBAL();
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ /* NOTREACHED */
+ return (false);
+ }
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ query->ip6_int = true;
+ break;
+ case 'm':
+ /*
+ * handled by preparse_args()
+ */
+ break;
+ case 'v':
+ fputs("mDiG " VERSION "\n", stderr);
+ 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, query->ip6_int);
+ 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();
+ }
+ /* NOTREACHED */
+ return (false);
+}
+
+static struct query *
+clone_default_query() {
+ struct query *query;
+
+ query = isc_mem_allocate(mctx, sizeof(struct query));
+ if (query == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ 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);
+ if (query->ecs_addr == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ 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];
+ }
+ }
+}
+
+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;
+ char *input;
+ bool global = 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 query" which won't actually be used
+ * anywhere, except for cloning into new queries
+ */
+
+ if (!is_batchfile) {
+ default_query.textname[0] = 0;
+ default_query.ip6_int = false;
+ 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 = 3;
+ 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) {
+ bargc = 1;
+ if (batchline[0] == '\r' || batchline[0] == '\n'
+ || batchline[0] == '#' || batchline[0] == ';')
+ continue;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 14) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ 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);
+ }
+}
+
+/*% Main processing routine for mdig */
+int
+main(int argc, char *argv[]) {
+ struct query *query;
+ isc_result_t result;
+ isc_sockaddr_t bind_any;
+ isc_log_t *lctx;
+ isc_logconfig_t *lcfg;
+ isc_entropy_t *ectx;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ unsigned int attrs, attrmask;
+ dns_dispatch_t *dispatchvx;
+ dns_view_t *view;
+ int ns;
+ unsigned int i;
+
+ RUNCHECK(isc_app_start());
+
+ dns_result_register();
+
+ 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);
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ lctx = NULL;
+ lcfg = NULL;
+ RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+ RUNCHECK(isc_entropy_getdata(ectx, cookie_secret,
+ sizeof(cookie_secret), NULL, 0));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ 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");
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
+
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY;
+ if (have_ipv4) {
+ isc_sockaddr_any(&bind_any);
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ } else {
+ isc_sockaddr_any6(&bind_any);
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ }
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchvx = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ have_src ? &srcaddr : &bind_any,
+ 4096, 100, 100, 17, 19,
+ attrs, attrmask, &dispatchvx));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr,
+ taskmgr, dispatchmgr,
+ have_ipv4 ? dispatchvx : NULL,
+ have_ipv6 ? dispatchvx : NULL,
+ &requestmgr));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+
+ query = ISC_LIST_HEAD(queries);
+ RUNCHECK(isc_app_onrun(mctx, task, sendqueries, query));
+
+ (void)isc_app_run();
+
+ 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);
+
+ dns_view_detach(&view);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchvx);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+
+ dst_lib_destroy();
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_log_destroy(&lctx);
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tools/mdig.docbook b/bin/tools/mdig.docbook
new file mode 100644
index 0000000..8d78916
--- /dev/null
+++ b/bin/tools/mdig.docbook
@@ -0,0 +1,698 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.mdig">
+ <info>
+ <date>2015-01-05</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle><application>mdig</application></refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname><application>mdig</application></refname>
+ <refpurpose>DNS pipelined lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>mdig</command>
+ <arg choice="req" rep="norepeat">@server</arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-m</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">address</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port#</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-i</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x <replaceable class="parameter">addr</replaceable></option></arg>
+ <arg choice="opt" rep="repeat">plusopt</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>mdig</command>
+ <arg choice="req" rep="norepeat">-h</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>mdig</command>
+ <arg choice="opt" rep="norepeat">@server</arg>
+ <arg choice="req" rep="repeat">global-opt</arg>
+ <arg choice="req" rep="repeat">
+ <arg choice="req" rep="repeat">local-opt</arg>
+ <arg choice="req" rep="norepeat">query</arg>
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>mdig</command>
+ is a multiple/pipelined query version of <command>dig</command>:
+ 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.
+ </para>
+
+ <para>
+ <command>mdig</command> options are a subset of the
+ <command>dig</command> 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.
+ </para>
+
+ <para>
+ The <arg choice="req" rep="norepeat">@server</arg> option is a mandatory global
+ option. It is the name or IP address of the name server to query.
+ (Unlike <command>dig</command>, this value is not retrieved from
+ <filename>/etc/resolv.conf</filename>.) It can be an IPv4 address
+ in dotted-decimal notation, an IPv6 address in colon-delimited
+ notation, or a hostname. When the supplied
+ <parameter>server</parameter> argument is a hostname,
+ <command>mdig</command> resolves that name before querying
+ the name server.
+ </para>
+
+ <para><command>mdig</command>
+ 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.
+ </para>
+
+ <para>
+ Each query option is identified by a keyword preceded by a plus
+ sign (<literal>+</literal>). Some keywords set or reset an
+ option. These may be preceded by the string <literal>no</literal>
+ to negate the meaning of that keyword. Other keywords assign
+ values to options like the timeout interval. They have the
+ form <option>+keyword=value</option>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ANYWHERE OPTIONS</title></info>
+
+
+ <para>
+ The <option>-f</option> option makes <command>mdig</command>
+ operate in batch mode by reading a list of lookup requests to
+ process from the file <parameter>filename</parameter>. 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 <command>mdig</command> using the command-line interface.
+ </para>
+
+ <para>
+ The <option>-h</option> causes <command>mdig</command> to
+ print the detailed help with the full list of options and exit.
+ </para>
+
+ <para>
+ The <option>-v</option> causes <command>mdig</command> to
+ print the version number and exit.
+ </para>
+ </refsection>
+
+ <refsection><info><title>GLOBAL OPTIONS</title></info>
+
+
+ <para>
+ The <option>-4</option> option forces <command>mdig</command> to
+ only use IPv4 query transport.
+ </para>
+
+ <para>
+ The <option>-6</option> option forces <command>mdig</command> to
+ only use IPv6 query transport.
+ </para>
+
+ <para>
+ The <option>-b</option> option sets the source IP address of the
+ query to <parameter>address</parameter>. 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
+ "#&lt;port&gt;"
+ </para>
+
+ <para>
+ The <option>-m</option> option enables memory usage debugging.
+ </para>
+
+ <para>
+ The <option>-p</option> option is used when a non-standard port
+ number is to be queried.
+ <parameter>port#</parameter> is the port number
+ that <command>mdig</command> will send its queries instead of
+ the standard DNS port number 53. This option would be used to
+ test a name server that has been configured to listen for
+ queries on a non-standard port number.
+ </para>
+
+ <para>
+ The global query options are:
+ <variablelist>
+
+ <varlistentry>
+ <term><option>+[no]additional</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the additional section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]all</option></term>
+ <listitem>
+ <para>
+ Set or clear all display flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]answer</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the answer section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]authority</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the authority section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]besteffort</option></term>
+ <listitem>
+ <para>
+ Attempt to display the contents of messages which are
+ malformed. The default is to not display malformed
+ answers.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cl</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the CLASS when printing the
+ record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]comments</option></term>
+ <listitem>
+ <para>
+ Toggle the display of comment lines in the output.
+ The default is to print comments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]continue</option></term>
+ <listitem>
+ <para>
+ Continue on errors (e.g. timeouts).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]crypto</option></term>
+ <listitem>
+ <para>
+ Toggle the display of cryptographic fields in DNSSEC
+ records. The contents of these field 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 ]".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+dscp[=value]</option></term> <listitem>
+ <para>
+ Set the DSCP code point to be used when sending the
+ query. Valid DSCP code points are in the range
+ [0..63]. By default no code point is explicitly set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]multiline</option></term>
+ <listitem>
+ <para>
+ 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 <command>mdig</command>
+ output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]question</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the question section of a query
+ when an answer is returned. The default is to print
+ the question section as a comment.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rrcomments</option></term>
+ <listitem>
+ <para>
+ Toggle 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]short</option></term>
+ <listitem>
+ <para>
+ Provide a terse answer. The default is to print the
+ answer in a verbose form.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+split=W</option></term>
+ <listitem>
+ <para>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <parameter>W</parameter>
+ characters (where <parameter>W</parameter> is rounded
+ up to the nearest multiple of 4).
+ <parameter>+nosplit</parameter> or
+ <parameter>+split=0</parameter> causes fields not to
+ be split at all. The default is 56 characters, or
+ 44 characters when multiline mode is active.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]tcp</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. The
+ default behavior is to use UDP.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlid</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL when printing the
+ record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlunits</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL in friendly human-readable
+ time units of "s", "m", "h", "d", and "w", representing
+ seconds, minutes, hours, days and weeks. Implies +ttlid.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]vc</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. This
+ alternate syntax to <parameter>+[no]tcp</parameter>
+ is provided for backwards compatibility. The "vc"
+ stands for "virtual circuit".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+ </refsection>
+
+ <refsection><info><title>LOCAL OPTIONS</title></info>
+
+
+ <para>
+ The <option>-c</option> option sets the query class to
+ <parameter>class</parameter>. It can be any valid query class
+ which is supported in BIND 9. The default query class is "IN".
+ </para>
+
+ <para>
+ The <option>-t</option> option sets the query type to
+ <parameter>type</parameter>. It can be any valid query type
+ which is supported in BIND 9. The default query type is "A",
+ unless the <option>-x</option> option is supplied to indicate
+ a reverse lookup with the "PTR" query type.
+ </para>
+
+ <para>
+ The <option>-i</option> option sets the reverse domain for
+ IPv6 addresses to IP6.INT.
+ </para>
+
+ <para>
+ Reverse lookups &mdash; mapping addresses to names &mdash; are
+ simplified by the <option>-x</option> option.
+ <parameter>addr</parameter> is an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ <command>mdig</command> automatically performs a lookup for a
+ query name like <literal>11.12.13.10.in-addr.arpa</literal> 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. To use the older RFC1886 method
+ using the IP6.INT domain specify the <option>-i</option> option.
+ </para>
+
+ <para>
+ The local query options are:
+ <variablelist>
+
+ <varlistentry>
+ <term><option>+[no]aaflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]aaonly</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]aaonly</option></term>
+ <listitem>
+ <para>
+ Sets the "aa" flag in the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]adflag</option></term>
+ <listitem>
+ <para>
+ Set [do 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 indicate that some part
+ of the answer was insecure or not validated. This
+ bit is set by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+bufsize=B</option></term>
+ <listitem>
+ <para>
+ Set the UDP message buffer size advertised using EDNS0
+ to <parameter>B</parameter> 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 will cause a
+ EDNS query to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cdflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the CD (checking disabled) bit in
+ the query. This requests the server to not perform
+ DNSSEC validation of responses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cookie<optional>=####</optional></option></term>
+ <listitem>
+ <para>
+ Send a COOKIE EDNS option, with optional value.
+ Replaying a COOKIE from a previous response will allow
+ the server to identify a previous client. The default
+ is <option>+nocookie</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]dnssec</option></term>
+ <listitem>
+ <para>
+ Requests DNSSEC records be sent by setting the DNSSEC
+ OK bit (DO) in the OPT record in the additional section
+ of the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]edns[=#]</option></term>
+ <listitem>
+ <para>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause
+ a EDNS query to be sent. <option>+noedns</option>
+ clears the remembered EDNS version. EDNS is set to
+ 0 by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsflags[=#]</option></term>
+ <listitem>
+ <para>
+ Set 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) will silently be
+ ignored. By default, no Z bits are set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsopt[=code[:value]]</option></term>
+ <listitem>
+ <para>
+ Specify EDNS option with code point <option>code</option>
+ and optionally payload of <option>value</option> as a
+ hexadecimal string. <option>+noednsopt</option>
+ clears the EDNS options to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]expire</option></term>
+ <listitem>
+ <para>
+ Send an EDNS Expire option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nsid</option></term>
+ <listitem>
+ <para>
+ Include an EDNS name server ID request when sending
+ a query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]recurse</option></term>
+ <listitem>
+ <para>
+ Toggle the setting of the RD (recursion desired) bit
+ in the query. This bit is set by default, which means
+ <command>mdig</command> normally sends recursive
+ queries.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+retry=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to retry UDP queries to
+ server to <parameter>T</parameter> instead of the
+ default, 2. Unlike <parameter>+tries</parameter>,
+ this does not include the initial query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]subnet=addr[/prefix-length]</option></term>
+ <listitem>
+ <para>
+ Send (don't send) an EDNS Client Subnet option with the
+ specified IP address or network prefix.
+ </para>
+ <para>
+ <command>mdig +subnet=0.0.0.0/0</command>, or simply
+ <command>mdig +subnet=0</command> 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
+ <emphasis>not</emphasis> be used when resolving
+ this query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+timeout=T</option></term>
+ <listitem>
+ <para>
+ Sets the timeout for a query to
+ <parameter>T</parameter> seconds. The default
+ timeout is 5 seconds for UDP transport and 10 for TCP.
+ An attempt to set <parameter>T</parameter> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+tries=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to try UDP queries to server
+ to <parameter>T</parameter> instead of the default,
+ 3. If <parameter>T</parameter> is less than or equal
+ to zero, the number of tries is silently rounded up
+ to 1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+udptimeout=T</option></term>
+ <listitem>
+ <para>
+ Sets the timeout between UDP query retries.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]unknownformat</option></term>
+ <listitem>
+ <para>
+ Print 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]zflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the last unassigned DNS header flag in a
+ DNS query. This flag is off by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC1035</citetitle>.
+ </para>
+ </refsection>
+</refentry>
diff --git a/bin/tools/mdig.html b/bin/tools/mdig.html
new file mode 100644
index 0000000..e41edf0
--- /dev/null
+++ b/bin/tools/mdig.html
@@ -0,0 +1,577 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>mdig</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.mdig"></a><div class="titlepage"></div>
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">mdig</span>
+ &#8212; DNS pipelined lookup utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">mdig</code>
+ {@server}
+ [<code class="option">-f <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-h</code>]
+ [<code class="option">-v</code>]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [<code class="option">-m</code>]
+ [<code class="option">-b <em class="replaceable"><code>address</code></em></code>]
+ [<code class="option">-p <em class="replaceable"><code>port#</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-i</code>]
+ [<code class="option">-x <em class="replaceable"><code>addr</code></em></code>]
+ [plusopt...]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">mdig</code>
+ {-h}
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">mdig</code>
+ [@server]
+ {global-opt...}
+ {
+ {local-opt...}
+ {query}
+ ...}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>mdig</strong></span>
+ is a multiple/pipelined query version of <span class="command"><strong>dig</strong></span>:
+ 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.
+ </p>
+
+ <p>
+ <span class="command"><strong>mdig</strong></span> options are a subset of the
+ <span class="command"><strong>dig</strong></span> 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.
+ </p>
+
+ <p>
+ The {@server} option is a mandatory global
+ option. It is the name or IP address of the name server to query.
+ (Unlike <span class="command"><strong>dig</strong></span>, this value is not retrieved from
+ <code class="filename">/etc/resolv.conf</code>.) It can be an IPv4 address
+ in dotted-decimal notation, an IPv6 address in colon-delimited
+ notation, or a hostname. When the supplied
+ <em class="parameter"><code>server</code></em> argument is a hostname,
+ <span class="command"><strong>mdig</strong></span> resolves that name before querying
+ the name server.
+ </p>
+
+ <p><span class="command"><strong>mdig</strong></span>
+ 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.
+ </p>
+
+ <p>
+ Each query option is identified by a keyword preceded by a plus
+ sign (<code class="literal">+</code>). Some keywords set or reset an
+ option. These may be preceded by the string <code class="literal">no</code>
+ to negate the meaning of that keyword. Other keywords assign
+ values to options like the timeout interval. They have the
+ form <code class="option">+keyword=value</code>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ANYWHERE OPTIONS</h2>
+
+
+ <p>
+ The <code class="option">-f</code> option makes <span class="command"><strong>mdig</strong></span>
+ operate in batch mode by reading a list of lookup requests to
+ process from the file <em class="parameter"><code>filename</code></em>. 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 <span class="command"><strong>mdig</strong></span> using the command-line interface.
+ </p>
+
+ <p>
+ The <code class="option">-h</code> causes <span class="command"><strong>mdig</strong></span> to
+ print the detailed help with the full list of options and exit.
+ </p>
+
+ <p>
+ The <code class="option">-v</code> causes <span class="command"><strong>mdig</strong></span> to
+ print the version number and exit.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>GLOBAL OPTIONS</h2>
+
+
+ <p>
+ The <code class="option">-4</code> option forces <span class="command"><strong>mdig</strong></span> to
+ only use IPv4 query transport.
+ </p>
+
+ <p>
+ The <code class="option">-6</code> option forces <span class="command"><strong>mdig</strong></span> to
+ only use IPv6 query transport.
+ </p>
+
+ <p>
+ The <code class="option">-b</code> option sets the source IP address of the
+ query to <em class="parameter"><code>address</code></em>. 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
+ "#&lt;port&gt;"
+ </p>
+
+ <p>
+ The <code class="option">-m</code> option enables memory usage debugging.
+ </p>
+
+ <p>
+ The <code class="option">-p</code> option is used when a non-standard port
+ number is to be queried.
+ <em class="parameter"><code>port#</code></em> is the port number
+ that <span class="command"><strong>mdig</strong></span> will send its queries instead of
+ the standard DNS port number 53. This option would be used to
+ test a name server that has been configured to listen for
+ queries on a non-standard port number.
+ </p>
+
+ <p>
+ The global query options are:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="option">+[no]additional</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the additional section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]all</code></span></dt>
+<dd>
+ <p>
+ Set or clear all display flags.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]answer</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the answer section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]authority</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the authority section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]besteffort</code></span></dt>
+<dd>
+ <p>
+ Attempt to display the contents of messages which are
+ malformed. The default is to not display malformed
+ answers.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cl</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the CLASS when printing the
+ record.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]comments</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of comment lines in the output.
+ The default is to print comments.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]continue</code></span></dt>
+<dd>
+ <p>
+ Continue on errors (e.g. timeouts).
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]crypto</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of cryptographic fields in DNSSEC
+ records. The contents of these field 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 ]".
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+dscp[=value]</code></span></dt>
+<dd>
+ <p>
+ Set the DSCP code point to be used when sending the
+ query. Valid DSCP code points are in the range
+ [0..63]. By default no code point is explicitly set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]multiline</code></span></dt>
+<dd>
+ <p>
+ 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 <span class="command"><strong>mdig</strong></span>
+ output.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]question</code></span></dt>
+<dd>
+ <p>
+ Print [do not print] the question section of a query
+ when an answer is returned. The default is to print
+ the question section as a comment.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rrcomments</code></span></dt>
+<dd>
+ <p>
+ Toggle 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]short</code></span></dt>
+<dd>
+ <p>
+ Provide a terse answer. The default is to print the
+ answer in a verbose form.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+split=W</code></span></dt>
+<dd>
+ <p>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <em class="parameter"><code>W</code></em>
+ characters (where <em class="parameter"><code>W</code></em> is rounded
+ up to the nearest multiple of 4).
+ <em class="parameter"><code>+nosplit</code></em> or
+ <em class="parameter"><code>+split=0</code></em> causes fields not to
+ be split at all. The default is 56 characters, or
+ 44 characters when multiline mode is active.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]tcp</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] TCP when querying name servers. The
+ default behavior is to use UDP.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttlid</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the TTL when printing the
+ record.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttlunits</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the TTL in friendly human-readable
+ time units of "s", "m", "h", "d", and "w", representing
+ seconds, minutes, hours, days and weeks. Implies +ttlid.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]vc</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] TCP when querying name servers. This
+ alternate syntax to <em class="parameter"><code>+[no]tcp</code></em>
+ is provided for backwards compatibility. The "vc"
+ stands for "virtual circuit".
+ </p>
+ </dd>
+</dl></div>
+<p>
+
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>LOCAL OPTIONS</h2>
+
+
+ <p>
+ The <code class="option">-c</code> option sets the query class to
+ <em class="parameter"><code>class</code></em>. It can be any valid query class
+ which is supported in BIND 9. The default query class is "IN".
+ </p>
+
+ <p>
+ The <code class="option">-t</code> option sets the query type to
+ <em class="parameter"><code>type</code></em>. It can be any valid query type
+ which is supported in BIND 9. The default query type is "A",
+ unless the <code class="option">-x</code> option is supplied to indicate
+ a reverse lookup with the "PTR" query type.
+ </p>
+
+ <p>
+ The <code class="option">-i</code> option sets the reverse domain for
+ IPv6 addresses to IP6.INT.
+ </p>
+
+ <p>
+ Reverse lookups &#8212; mapping addresses to names &#8212; are
+ simplified by the <code class="option">-x</code> option.
+ <em class="parameter"><code>addr</code></em> is an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ <span class="command"><strong>mdig</strong></span> automatically performs a lookup for a
+ query name like <code class="literal">11.12.13.10.in-addr.arpa</code> 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. To use the older RFC1886 method
+ using the IP6.INT domain specify the <code class="option">-i</code> option.
+ </p>
+
+ <p>
+ The local query options are:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="option">+[no]aaflag</code></span></dt>
+<dd>
+ <p>
+ A synonym for <em class="parameter"><code>+[no]aaonly</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]aaonly</code></span></dt>
+<dd>
+ <p>
+ Sets the "aa" flag in the query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]adflag</code></span></dt>
+<dd>
+ <p>
+ Set [do 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 indicate that some part
+ of the answer was insecure or not validated. This
+ bit is set by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+bufsize=B</code></span></dt>
+<dd>
+ <p>
+ Set the UDP message buffer size advertised using EDNS0
+ to <em class="parameter"><code>B</code></em> 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 will cause a
+ EDNS query to be sent.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cdflag</code></span></dt>
+<dd>
+ <p>
+ Set [do not set] the CD (checking disabled) bit in
+ the query. This requests the server to not perform
+ DNSSEC validation of responses.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cookie[<span class="optional">=####</span>]</code></span></dt>
+<dd>
+ <p>
+ Send a COOKIE EDNS option, with optional value.
+ Replaying a COOKIE from a previous response will allow
+ the server to identify a previous client. The default
+ is <code class="option">+nocookie</code>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]dnssec</code></span></dt>
+<dd>
+ <p>
+ Requests DNSSEC records be sent by setting the DNSSEC
+ OK bit (DO) in the OPT record in the additional section
+ of the query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]edns[=#]</code></span></dt>
+<dd>
+ <p>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause
+ a EDNS query to be sent. <code class="option">+noedns</code>
+ clears the remembered EDNS version. EDNS is set to
+ 0 by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsflags[=#]</code></span></dt>
+<dd>
+ <p>
+ Set 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) will silently be
+ ignored. By default, no Z bits are set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsopt[=code[:value]]</code></span></dt>
+<dd>
+ <p>
+ Specify EDNS option with code point <code class="option">code</code>
+ and optionally payload of <code class="option">value</code> as a
+ hexadecimal string. <code class="option">+noednsopt</code>
+ clears the EDNS options to be sent.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]expire</code></span></dt>
+<dd>
+ <p>
+ Send an EDNS Expire option.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]nsid</code></span></dt>
+<dd>
+ <p>
+ Include an EDNS name server ID request when sending
+ a query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]recurse</code></span></dt>
+<dd>
+ <p>
+ Toggle the setting of the RD (recursion desired) bit
+ in the query. This bit is set by default, which means
+ <span class="command"><strong>mdig</strong></span> normally sends recursive
+ queries.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+retry=T</code></span></dt>
+<dd>
+ <p>
+ Sets the number of times to retry UDP queries to
+ server to <em class="parameter"><code>T</code></em> instead of the
+ default, 2. Unlike <em class="parameter"><code>+tries</code></em>,
+ this does not include the initial query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]subnet=addr[/prefix-length]</code></span></dt>
+<dd>
+ <p>
+ Send (don't send) an EDNS Client Subnet option with the
+ specified IP address or network prefix.
+ </p>
+ <p>
+ <span class="command"><strong>mdig +subnet=0.0.0.0/0</strong></span>, or simply
+ <span class="command"><strong>mdig +subnet=0</strong></span> 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
+ <span class="emphasis"><em>not</em></span> be used when resolving
+ this query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+timeout=T</code></span></dt>
+<dd>
+ <p>
+ Sets the timeout for a query to
+ <em class="parameter"><code>T</code></em> seconds. The default
+ timeout is 5 seconds for UDP transport and 10 for TCP.
+ An attempt to set <em class="parameter"><code>T</code></em> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+tries=T</code></span></dt>
+<dd>
+ <p>
+ Sets the number of times to try UDP queries to server
+ to <em class="parameter"><code>T</code></em> instead of the default,
+ 3. If <em class="parameter"><code>T</code></em> is less than or equal
+ to zero, the number of tries is silently rounded up
+ to 1.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+udptimeout=T</code></span></dt>
+<dd>
+ <p>
+ Sets the timeout between UDP query retries.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]unknownformat</code></span></dt>
+<dd>
+ <p>
+ Print 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]zflag</code></span></dt>
+<dd>
+ <p>
+ Set [do not set] the last unassigned DNS header flag in a
+ DNS query. This flag is off by default.
+ </p>
+ </dd>
+</dl></div>
+<p>
+
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dig</span>(1)
+ </span>,
+ <em class="citetitle">RFC1035</em>.
+ </p>
+ </div>
+</div></body>
+</html>
diff --git a/bin/tools/named-journalprint.8 b/bin/tools/named-journalprint.8
new file mode 100644
index 0000000..191740e
--- /dev/null
+++ b/bin/tools/named-journalprint.8
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named-journalprint
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-12-04
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NAMED\-JOURNALPRINT" "8" "2009\-12\-04" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named-journalprint \- print zone journal in human\-readable form
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\-journalprint\fR\ 'u
+\fBnamed\-journalprint\fR {\fIjournal\fR}
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-journalprint\fR
+prints the contents of a zone journal file in a human\-readable form\&.
+.PP
+Journal files are automatically created by
+\fBnamed\fR
+when changes are made to dynamic zones (e\&.g\&., by
+\fBnsupdate\fR)\&. 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\&.
+.PP
+\fBnamed\-journalprint\fR
+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\&.
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBnsupdate\fR(1),
+BIND 9 Administrator Reference Manual\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/named-journalprint.c b/bin/tools/named-journalprint.c
new file mode 100644
index 0000000..1bca1b2
--- /dev/null
+++ b/bin/tools/named-journalprint.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+#include <config.h>
+
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#include <stdlib.h>
+
+/*
+ * 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;
+
+ RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
+ 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;
+ RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, 0) == ISC_R_SUCCESS);
+ 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;
+
+ if (argc != 2) {
+ printf("usage: %s journal\n", argv[0]);
+ return(1);
+ }
+
+ file = argv[1];
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(setup_logging(mctx, stderr, &lctx) == ISC_R_SUCCESS);
+
+ result = dns_journal_print(mctx, file, stdout);
+ if (result == DNS_R_NOJOURNAL)
+ fprintf(stderr, "%s\n", dns_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.docbook b/bin/tools/named-journalprint.docbook
new file mode 100644
index 0000000..0e80ac7
--- /dev/null
+++ b/bin/tools/named-journalprint.docbook
@@ -0,0 +1,93 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named-journalprint">
+ <info>
+ <date>2009-12-04</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named-journalprint</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>named-journalprint</application></refname>
+ <refpurpose>print zone journal in human-readable form</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>named-journalprint</command>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">journal</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>named-journalprint</command>
+ prints the contents of a zone journal file in a human-readable
+ form.
+ </para>
+ <para>
+ Journal files are automatically created by <command>named</command>
+ when changes are made to dynamic zones (e.g., by
+ <command>nsupdate</command>). 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
+ <filename>.jnl</filename> to the name of the corresponding
+ zone file.
+ </para>
+ <para>
+ <command>named-journalprint</command> 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.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>nsupdate</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/named-journalprint.html b/bin/tools/named-journalprint.html
new file mode 100644
index 0000000..693852c
--- /dev/null
+++ b/bin/tools/named-journalprint.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-journalprint</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named-journalprint"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">named-journalprint</span>
+ &#8212; print zone journal in human-readable form
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named-journalprint</code>
+ {<em class="replaceable"><code>journal</code></em>}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>named-journalprint</strong></span>
+ prints the contents of a zone journal file in a human-readable
+ form.
+ </p>
+ <p>
+ Journal files are automatically created by <span class="command"><strong>named</strong></span>
+ when changes are made to dynamic zones (e.g., by
+ <span class="command"><strong>nsupdate</strong></span>). 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
+ <code class="filename">.jnl</code> to the name of the corresponding
+ zone file.
+ </p>
+ <p>
+ <span class="command"><strong>named-journalprint</strong></span> 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.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">nsupdate</span>(1)
+ </span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/named-nzd2nzf.8 b/bin/tools/named-nzd2nzf.8
new file mode 100644
index 0000000..2211a32
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.8
@@ -0,0 +1,67 @@
+.\" Copyright (C) 2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named-nzd2nzf
+.\" Author: [see the "AUTHOR" section]
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: May 5, 2016
+.\" Manual: BIND9
+.\" Source: BIND9
+.\" Language: English
+.\"
+.TH "NAMED\-NZD2NZF" "8" "May 5, 2016" "BIND9" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named-nzd2nzf \- Convert an NZD database to NZF text format
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\-nzd2nzf\fR\ 'u
+\fBnamed\-nzd2nzf\fR {filename}
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-nzd2nzf\fR
+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
+\fBnamed\fR
+via
+\fBrndc addzone\fR\&. It can also be used to restore the old file format when rolling back from a newer version of BIND to an older version\&.
+.SH "ARGUMENTS"
+.PP
+filename
+.RS 4
+The name of the
+\&.nzd
+file whose contents should be printed\&.
+.RE
+.SH "SEE ALSO"
+.PP
+BIND 9 Administrator Reference Manual
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/named-nzd2nzf.c b/bin/tools/named-nzd2nzf.c
new file mode 100644
index 0000000..d1b6427
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#ifndef HAVE_LMDB
+#error This program requires the LMDB library.
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <lmdb.h>
+
+#include <dns/view.h>
+
+#include <isc/print.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.docbook b/bin/tools/named-nzd2nzf.docbook
new file mode 100644
index 0000000..04ef9f7
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.docbook
@@ -0,0 +1,94 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<refentry id="man.named-nzd2nzf">
+ <refentryinfo>
+ <date>May 5, 2016</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named-nzd2nzf</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>named-nzd2nzf</application></refname>
+ <refpurpose>
+ Convert an NZD database to NZF text format
+ </refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>named-nzd2nzf</command>
+ <arg choice="req">filename</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>named-nzd2nzf</command> 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
+ <command>named</command> via <command>rndc addzone</command>.
+ It can also be used to restore the old file format
+ when rolling back from a newer version
+ of BIND to an older version.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>ARGUMENTS</title>
+ <variablelist>
+ <varlistentry>
+ <term>filename</term>
+ <listitem>
+ <para>
+ The name of the <filename>.nzd</filename> file whose contents
+ should be printed.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/tools/named-nzd2nzf.html b/bin/tools/named-nzd2nzf.html
new file mode 100644
index 0000000..cfc9927
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-nzd2nzf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named-nzd2nzf"></a><div class="titlepage"></div>
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">named-nzd2nzf</span>
+ &#8212;
+ Convert an NZD database to NZF text format
+
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named-nzd2nzf</code>
+ {filename}
+ </p></div>
+ </div>
+
+ <div class="refsect1">
+<a name="id-1.6"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>named-nzd2nzf</strong></span> 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
+ <span class="command"><strong>named</strong></span> via <span class="command"><strong>rndc addzone</strong></span>.
+ It can also be used to restore the old file format
+ when rolling back from a newer version
+ of BIND to an older version.
+ </p>
+ </div>
+
+ <div class="refsect1">
+<a name="id-1.7"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">filename</span></dt>
+<dd>
+ <p>
+ The name of the <code class="filename">.nzd</code> file whose contents
+ should be printed.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsect1">
+<a name="id-1.8"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>
+ </p>
+ </div>
+
+ <div class="refsect1">
+<a name="id-1.9"></a><h2>AUTHOR</h2>
+
+ <p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/named-rrchecker.1 b/bin/tools/named-rrchecker.1
new file mode 100644
index 0000000..c3d5d41
--- /dev/null
+++ b/bin/tools/named-rrchecker.1
@@ -0,0 +1,81 @@
+.\" Copyright (C) 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: named-rrchecker
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2013-11-12
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NAMED\-RRCHECKER" "1" "2013\-11\-12" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+named-rrchecker \- syntax checker for individual DNS resource records
+.SH "SYNOPSIS"
+.HP \w'\fBnamed\-rrchecker\fR\ 'u
+\fBnamed\-rrchecker\fR [\fB\-h\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-p\fR] [\fB\-u\fR] [\fB\-C\fR] [\fB\-T\fR] [\fB\-P\fR]
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-rrchecker\fR
+read a individual DNS resource record from standard input and checks if it is syntactically correct\&.
+.PP
+The
+\fB\-h\fR
+prints out the help menu\&.
+.PP
+The
+\fB\-o \fR\fB\fIorigin\fR\fR
+option specifies a origin to be used when interpreting the record\&.
+.PP
+The
+\fB\-p\fR
+prints out the resulting record in canonical form\&. If there is no canonical form defined then the record will be printed in unknown record format\&.
+.PP
+The
+\fB\-u\fR
+prints out the resulting record in unknown record form\&.
+.PP
+The
+\fB\-C\fR,
+\fB\-T\fR
+and
+\fB\-P\fR
+print out the known class, standard type and private type mnemonics respectively\&.
+.SH "SEE ALSO"
+.PP
+RFC 1034,
+RFC 1035,
+\fBnamed\fR(8)
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/named-rrchecker.c b/bin/tools/named-rrchecker.c
new file mode 100644
index 0000000..5c1d36d
--- /dev/null
+++ b/bin/tools/named-rrchecker.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/print.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>
+#include <dns/result.h>
+
+static isc_mem_t *mctx;
+static isc_lex_t *lex;
+
+static isc_lexspecials_t specials;
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+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 "
+ "interpeting 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);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
+
+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);
+ 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);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ 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",
+ dns_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",
+ dns_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",
+ dns_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",
+ dns_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",
+ dns_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdatatype_totext(rdtype, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_totext: %s",
+ dns_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",
+ dns_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",
+ dns_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdatatype_tounknowntext(rdtype, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_tounknowntext: %s",
+ dns_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",
+ dns_result_totext(result));
+ }
+
+ printf("%.*s\n", (int)tbuf.used, (char*)tbuf.base);
+ fflush(stdout);
+ }
+
+ isc_lex_close(lex);
+ isc_lex_destroy(&lex);
+ isc_mem_destroy(&mctx);
+ return (0);
+}
diff --git a/bin/tools/named-rrchecker.docbook b/bin/tools/named-rrchecker.docbook
new file mode 100644
index 0000000..50c26f1
--- /dev/null
+++ b/bin/tools/named-rrchecker.docbook
@@ -0,0 +1,96 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named-rrchecker">
+ <info>
+ <date>2013-11-12</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle><application>named-rrchecker</application></refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname><application>named-rrchecker</application></refname>
+ <refpurpose>syntax checker for individual DNS resource records</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>named-rrchecker</command>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-u</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-C</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-T</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-P</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>named-rrchecker</command>
+ read a individual DNS resource record from standard input and checks if it
+ is syntactically correct.
+ </para>
+ <para>
+ The <option>-h</option> prints out the help menu.
+ </para>
+ <para>
+ The <option>-o <replaceable class="parameter">origin</replaceable></option>
+ option specifies a origin to be used when interpreting the record.
+ </para>
+ <para>
+ The <option>-p</option> prints out the resulting record in canonical
+ form. If there is no canonical form defined then the record will be
+ printed in unknown record format.
+ </para>
+ <para>
+ The <option>-u</option> prints out the resulting record in unknown record
+ form.
+ </para>
+ <para>
+ The <option>-C</option>, <option>-T</option> and <option>-P</option>
+ print out the known class, standard type and private type mnemonics
+ respectively.
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citetitle>RFC 1034</citetitle>,
+ <citetitle>RFC 1035</citetitle>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/named-rrchecker.html b/bin/tools/named-rrchecker.html
new file mode 100644
index 0000000..c6120e1
--- /dev/null
+++ b/bin/tools/named-rrchecker.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2013-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-rrchecker</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.named-rrchecker"></a><div class="titlepage"></div>
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">named-rrchecker</span>
+ &#8212; syntax checker for individual DNS resource records
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">named-rrchecker</code>
+ [<code class="option">-h</code>]
+ [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>]
+ [<code class="option">-p</code>]
+ [<code class="option">-u</code>]
+ [<code class="option">-C</code>]
+ [<code class="option">-T</code>]
+ [<code class="option">-P</code>]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>named-rrchecker</strong></span>
+ read a individual DNS resource record from standard input and checks if it
+ is syntactically correct.
+ </p>
+ <p>
+ The <code class="option">-h</code> prints out the help menu.
+ </p>
+ <p>
+ The <code class="option">-o <em class="replaceable"><code>origin</code></em></code>
+ option specifies a origin to be used when interpreting the record.
+ </p>
+ <p>
+ The <code class="option">-p</code> prints out the resulting record in canonical
+ form. If there is no canonical form defined then the record will be
+ printed in unknown record format.
+ </p>
+ <p>
+ The <code class="option">-u</code> prints out the resulting record in unknown record
+ form.
+ </p>
+ <p>
+ The <code class="option">-C</code>, <code class="option">-T</code> and <code class="option">-P</code>
+ print out the known class, standard type and private type mnemonics
+ respectively.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <em class="citetitle">RFC 1034</em>,
+ <em class="citetitle">RFC 1035</em>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/nsec3hash.8 b/bin/tools/nsec3hash.8
new file mode 100644
index 0000000..07e88e5
--- /dev/null
+++ b/bin/tools/nsec3hash.8
@@ -0,0 +1,78 @@
+.\" Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: nsec3hash
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-03-02
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NSEC3HASH" "8" "2009\-03\-02" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nsec3hash \- generate NSEC3 hash
+.SH "SYNOPSIS"
+.HP \w'\fBnsec3hash\fR\ 'u
+\fBnsec3hash\fR {\fIsalt\fR} {\fIalgorithm\fR} {\fIiterations\fR} {\fIdomain\fR}
+.SH "DESCRIPTION"
+.PP
+\fBnsec3hash\fR
+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\&.
+.SH "ARGUMENTS"
+.PP
+salt
+.RS 4
+The salt provided to the hash algorithm\&.
+.RE
+.PP
+algorithm
+.RS 4
+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\&.
+.RE
+.PP
+iterations
+.RS 4
+The number of additional times the hash should be performed\&.
+.RE
+.PP
+domain
+.RS 4
+The domain name to be hashed\&.
+.RE
+.SH "SEE ALSO"
+.PP
+BIND 9 Administrator Reference Manual,
+RFC 5155\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/tools/nsec3hash.c b/bin/tools/nsec3hash.c
new file mode 100644
index 0000000..1e10921
--- /dev/null
+++ b/bin/tools/nsec3hash.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.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 <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/nsec3.h>
+#include <dns/types.h>
+
+const char *program = "nsec3hash";
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
+
+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);
+ exit(1);
+}
+
+int
+main(int argc, char **argv) {
+ 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 length;
+ unsigned int iterations;
+ unsigned int salt_length;
+
+ if (argc != 5)
+ usage();
+
+ if (strcmp(argv[1], "-") == 0) {
+ salt_length = 0;
+ salt[0] = 0;
+ } else {
+ isc_buffer_init(&buffer, salt, sizeof(salt));
+ result = isc_hex_decodestring(argv[1], &buffer);
+ check_result(result, "isc_hex_decodestring(salt)");
+ salt_length = isc_buffer_usedlength(&buffer);
+ if (salt_length > DNS_NSEC3_SALTSIZE)
+ fatal("salt too long");
+ }
+ hash_alg = atoi(argv[2]);
+ if (hash_alg > 255U)
+ fatal("hash algorithm too large");
+ iterations = atoi(argv[3]);
+ if (iterations > 0xffffU)
+ fatal("iterations to large");
+
+ name = dns_fixedname_initname(&fixed);
+ isc_buffer_init(&buffer, argv[4], strlen(argv[4]));
+ isc_buffer_add(&buffer, strlen(argv[4]));
+ 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);
+ fprintf(stdout, "%.*s (salt=%s, hash=%u, iterations=%u)\n",
+ (int)isc_buffer_usedlength(&buffer), text, argv[1], hash_alg, iterations);
+ return(0);
+}
diff --git a/bin/tools/nsec3hash.docbook b/bin/tools/nsec3hash.docbook
new file mode 100644
index 0000000..1d44166
--- /dev/null
+++ b/bin/tools/nsec3hash.docbook
@@ -0,0 +1,116 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.nsec3hash">
+ <info>
+ <date>2009-03-02</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>nsec3hash</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>nsec3hash</application></refname>
+ <refpurpose>generate NSEC3 hash</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>nsec3hash</command>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">salt</replaceable></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">iterations</replaceable></arg>
+ <arg choice="req" rep="norepeat"><replaceable class="parameter">domain</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para>
+ <command>nsec3hash</command> 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.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term>salt</term>
+ <listitem>
+ <para>
+ The salt provided to the hash algorithm.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>algorithm</term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>iterations</term>
+ <listitem>
+ <para>
+ The number of additional times the hash should be performed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>domain</term>
+ <listitem>
+ <para>
+ The domain name to be hashed.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para>
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 5155</citetitle>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/tools/nsec3hash.html b/bin/tools/nsec3hash.html
new file mode 100644
index 0000000..94d85ce
--- /dev/null
+++ b/bin/tools/nsec3hash.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2009, 2014-2016, 2018, 2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nsec3hash</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.nsec3hash"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ <span class="application">nsec3hash</span>
+ &#8212; generate NSEC3 hash
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">nsec3hash</code>
+ {<em class="replaceable"><code>salt</code></em>}
+ {<em class="replaceable"><code>algorithm</code></em>}
+ {<em class="replaceable"><code>iterations</code></em>}
+ {<em class="replaceable"><code>domain</code></em>}
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p>
+ <span class="command"><strong>nsec3hash</strong></span> 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.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">salt</span></dt>
+<dd>
+ <p>
+ The salt provided to the hash algorithm.
+ </p>
+ </dd>
+<dt><span class="term">algorithm</span></dt>
+<dd>
+ <p>
+ 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.
+ </p>
+ </dd>
+<dt><span class="term">iterations</span></dt>
+<dd>
+ <p>
+ The number of additional times the hash should be performed.
+ </p>
+ </dd>
+<dt><span class="term">domain</span></dt>
+<dd>
+ <p>
+ The domain name to be hashed.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>SEE ALSO</h2>
+
+ <p>
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 5155</em>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/tools/win32/arpaname.dsp.in b/bin/tools/win32/arpaname.dsp.in
new file mode 100644
index 0000000..1871a32
--- /dev/null
+++ b/bin/tools/win32/arpaname.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="arpaname" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=arpaname - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "arpaname.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "arpaname.mak" CFG="arpaname - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "arpaname - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "arpaname - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "arpaname - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/arpaname.exe"
+
+!ELSEIF "$(CFG)" == "arpaname - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/arpaname.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "arpaname - @PLATFORM@ Release"
+# Name "arpaname - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\arpaname.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/arpaname.dsw b/bin/tools/win32/arpaname.dsw
new file mode 100644
index 0000000..ca616c0
--- /dev/null
+++ b/bin/tools/win32/arpaname.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "arpaname"=".\arpaname.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/arpaname.mak.in b/bin/tools/win32/arpaname.mak.in
new file mode 100644
index 0000000..7de36d8
--- /dev/null
+++ b/bin/tools/win32/arpaname.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on arpaname.dsp
+!IF "$(CFG)" == ""
+CFG=arpaname - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to arpaname - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "arpaname - @PLATFORM@ Release" && "$(CFG)" != "arpaname - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "arpaname.mak" CFG="arpaname - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "arpaname - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "arpaname - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "arpaname - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "arpaname - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\arpaname.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\arpaname.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\arpaname.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\arpaname.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\arpaname.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\arpaname.pdb" @MACHINE@ /out:"../../../Build/Release/arpaname.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\arpaname.obj"
+
+"..\..\..\Build\Release\arpaname.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "arpaname - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\arpaname.exe" "$(OUTDIR)\arpaname.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\arpaname.obj"
+ -@erase "$(INTDIR)\arpaname.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\arpaname.pdb"
+ -@erase "$(OUTDIR)\arpaname.bsc"
+ -@erase "..\..\..\Build\Debug\arpaname.exe"
+ -@erase "..\..\..\Build\Debug\arpaname.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\arpaname.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\arpaname.sbr"
+
+"$(OUTDIR)\arpaname.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\arpaname.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/arpaname.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\arpaname.obj"
+
+"..\..\..\Build\Debug\arpaname.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("arpaname.dep")
+!INCLUDE "arpaname.dep"
+!ELSE
+!MESSAGE Warning: cannot find "arpaname.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "arpaname - @PLATFORM@ Release" || "$(CFG)" == "arpaname - @PLATFORM@ Debug"
+SOURCE="..\arpaname.c"
+
+!IF "$(CFG)" == "arpaname - @PLATFORM@ Release"
+
+
+"$(INTDIR)\arpaname.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "arpaname - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\arpaname.obj" "$(INTDIR)\arpaname.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/arpaname.vcxproj.filters.in b/bin/tools/win32/arpaname.vcxproj.filters.in
new file mode 100644
index 0000000..129b93e
--- /dev/null
+++ b/bin/tools/win32/arpaname.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\arpaname.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/arpaname.vcxproj.in b/bin/tools/win32/arpaname.vcxproj.in
new file mode 100644
index 0000000..07b501d
--- /dev/null
+++ b/bin/tools/win32/arpaname.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{91E60FDA-E48C-4DA0-92A2-97F963348E00}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>arpaname</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <BrowseInformation>true</BrowseInformation>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\arpaname.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/arpaname.vcxproj.user b/bin/tools/win32/arpaname.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/arpaname.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/genrandom.dsp.in b/bin/tools/win32/genrandom.dsp.in
new file mode 100644
index 0000000..6358eb3
--- /dev/null
+++ b/bin/tools/win32/genrandom.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="genrandom" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=genrandom - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "genrandom.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "genrandom.mak" CFG="genrandom - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "genrandom - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "genrandom - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "genrandom - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/genrandom.exe"
+
+!ELSEIF "$(CFG)" == "genrandom - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/genrandom.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "genrandom - @PLATFORM@ Release"
+# Name "genrandom - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\genrandom.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/genrandom.dsw b/bin/tools/win32/genrandom.dsw
new file mode 100644
index 0000000..76feb02
--- /dev/null
+++ b/bin/tools/win32/genrandom.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "genrandom"=".\genrandom.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/genrandom.mak.in b/bin/tools/win32/genrandom.mak.in
new file mode 100644
index 0000000..a5d951a
--- /dev/null
+++ b/bin/tools/win32/genrandom.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on genrandom.dsp
+!IF "$(CFG)" == ""
+CFG=genrandom - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to genrandom - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "genrandom - @PLATFORM@ Release" && "$(CFG)" != "genrandom - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "genrandom.mak" CFG="genrandom - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "genrandom - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "genrandom - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "genrandom - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "genrandom - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\genrandom.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\genrandom.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\genrandom.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\genrandom.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\genrandom.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\genrandom.pdb" @MACHINE@ /out:"../../../Build/Release/genrandom.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\genrandom.obj" \
+
+"..\..\..\Build\Release\genrandom.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "genrandom - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\genrandom.exe" "$(OUTDIR)\genrandom.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\genrandom.obj"
+ -@erase "$(INTDIR)\genrandom.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\genrandom.pdb"
+ -@erase "$(OUTDIR)\genrandom.bsc"
+ -@erase "..\..\..\Build\Debug\genrandom.exe"
+ -@erase "..\..\..\Build\Debug\genrandom.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\genrandom.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\genrandom.sbr"
+
+"$(OUTDIR)\genrandom.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\genrandom.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/genrandom.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\genrandom.obj"
+
+"..\..\..\Build\Debug\genrandom.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("genrandom.dep")
+!INCLUDE "genrandom.dep"
+!ELSE
+!MESSAGE Warning: cannot find "genrandom.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "genrandom - @PLATFORM@ Release" || "$(CFG)" == "genrandom - @PLATFORM@ Debug"
+SOURCE="..\genrandom.c"
+
+!IF "$(CFG)" == "genrandom - @PLATFORM@ Release"
+
+
+"$(INTDIR)\genrandom.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "genrandom - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\genrandom.obj" "$(INTDIR)\genrandom.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/genrandom.vcxproj.filters.in b/bin/tools/win32/genrandom.vcxproj.filters.in
new file mode 100644
index 0000000..6e97767
--- /dev/null
+++ b/bin/tools/win32/genrandom.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\genrandom.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/genrandom.vcxproj.in b/bin/tools/win32/genrandom.vcxproj.in
new file mode 100644
index 0000000..22fc095
--- /dev/null
+++ b/bin/tools/win32/genrandom.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{B4AC7F81-E3DC-43E9-B339-4FA5149FA8F7}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>genrandom</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\genrandom.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/genrandom.vcxproj.user b/bin/tools/win32/genrandom.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/genrandom.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/ischmacfixup.dsp.in b/bin/tools/win32/ischmacfixup.dsp.in
new file mode 100755
index 0000000..82e9ee8
--- /dev/null
+++ b/bin/tools/win32/ischmacfixup.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="ischmacfixup" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=ischmacfixup - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ischmacfixup.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ischmacfixup.mak" CFG="ischmacfixup - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ischmacfixup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "ischmacfixup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ischmacfixup - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/isc-hmac-fixup.exe"
+
+!ELSEIF "$(CFG)" == "ischmacfixup - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/isc-hmac-fixup.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "ischmacfixup - @PLATFORM@ Release"
+# Name "ischmacfixup - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\isc-hmac-fixup.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/ischmacfixup.dsw b/bin/tools/win32/ischmacfixup.dsw
new file mode 100644
index 0000000..4ca034e
--- /dev/null
+++ b/bin/tools/win32/ischmacfixup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ischmacfixup"=".\ischmacfixup.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/ischmacfixup.mak.in b/bin/tools/win32/ischmacfixup.mak.in
new file mode 100755
index 0000000..7488caf
--- /dev/null
+++ b/bin/tools/win32/ischmacfixup.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on ischmacfixup.dsp
+!IF "$(CFG)" == ""
+CFG=ischmacfixup - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to ischmacfixup - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ischmacfixup - @PLATFORM@ Release" && "$(CFG)" != "ischmacfixup - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ischmacfixup.mak" CFG="ischmacfixup - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ischmacfixup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "ischmacfixup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "ischmacfixup - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "ischmacfixup - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\isc-hmac-fixup.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\isc-hmac-fixup.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\isc-hmac-fixup.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\isc-hmac-fixup.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\isc-hmac-fixup.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\isc-hmac-fixup.pdb" @MACHINE@ /out:"../../../Build/Release/isc-hmac-fixup.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\isc-hmac-fixup.obj"
+
+"..\..\..\Build\Release\isc-hmac-fixup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "ischmacfixup - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\isc-hmac-fixup.exe" "$(OUTDIR)\isc-hmac-fixup.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\isc-hmac-fixup.obj"
+ -@erase "$(INTDIR)\isc-hmac-fixup.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\isc-hmac-fixup.pdb"
+ -@erase "$(OUTDIR)\isc-hmac-fixup.bsc"
+ -@erase "..\..\..\Build\Debug\isc-hmac-fixup.exe"
+ -@erase "..\..\..\Build\Debug\isc-hmac-fixup.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\isc-hmac-fixup.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\isc-hmac-fixup.sbr"
+
+"$(OUTDIR)\isc-hmac-fixup.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\isc-hmac-fixup.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/isc-hmac-fixup.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\isc-hmac-fixup.obj"
+
+"..\..\..\Build\Debug\isc-hmac-fixup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("isc-hmac-fixup.dep")
+!INCLUDE "isc-hmac-fixup.dep"
+!ELSE
+!MESSAGE Warning: cannot find "isc-hmac-fixup.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "ischmacfixup - @PLATFORM@ Release" || "$(CFG)" == "ischmacfixup - @PLATFORM@ Debug"
+SOURCE="..\isc-hmac-fixup.c"
+
+!IF "$(CFG)" == "ischmacfixup - @PLATFORM@ Release"
+
+
+"$(INTDIR)\isc-hmac-fixup.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "ischmacfixup - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\isc-hmac-fixup.obj" "$(INTDIR)\isc-hmac-fixup.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/ischmacfixup.vcxproj.filters.in b/bin/tools/win32/ischmacfixup.vcxproj.filters.in
new file mode 100644
index 0000000..49d5814
--- /dev/null
+++ b/bin/tools/win32/ischmacfixup.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\isc-hmac-fixup.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/ischmacfixup.vcxproj.in b/bin/tools/win32/ischmacfixup.vcxproj.in
new file mode 100644
index 0000000..39c5580
--- /dev/null
+++ b/bin/tools/win32/ischmacfixup.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{70F2F0DF-665D-4444-A982-AEA31A861A22}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ischmacfixup</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>isc-hmac-fixup</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>isc-hmac-fixup</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\isc-hmac-fixup.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/ischmacfixup.vcxproj.user b/bin/tools/win32/ischmacfixup.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/ischmacfixup.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/journalprint.dsp.in b/bin/tools/win32/journalprint.dsp.in
new file mode 100644
index 0000000..268737b
--- /dev/null
+++ b/bin/tools/win32/journalprint.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="journalprint" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=journalprint - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "journalprint.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "journalprint.mak" CFG="journalprint - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "journalprint - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "journalprint - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "journalprint - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named-journalprint.exe"
+
+!ELSEIF "$(CFG)" == "journalprint - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/named-journalprint.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "journalprint - @PLATFORM@ Release"
+# Name "journalprint - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\named-journalprint.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/journalprint.dsw b/bin/tools/win32/journalprint.dsw
new file mode 100644
index 0000000..471f396
--- /dev/null
+++ b/bin/tools/win32/journalprint.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "journalprint"=".\journalprint.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/journalprint.mak.in b/bin/tools/win32/journalprint.mak.in
new file mode 100644
index 0000000..d21aca1
--- /dev/null
+++ b/bin/tools/win32/journalprint.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on journalprint.dsp
+!IF "$(CFG)" == ""
+CFG=journalprint - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to journalprint - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "journalprint - @PLATFORM@ Release" && "$(CFG)" != "journalprint - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "journalprint.mak" CFG="journalprint - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "journalprint - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "journalprint - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "journalprint - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "journalprint - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\named-journalprint.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\named-journalprint.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\named-journalprint.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\journalprint.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\journalprint.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-journalprint.pdb" @MACHINE@ /out:"../../../Build/Release/named-journalprint.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\named-journalprint.obj"
+
+"..\..\..\Build\Release\named-journalprint.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "journalprint - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\named-journalprint.exe" "$(OUTDIR)\journalprint.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\named-journalprint.obj"
+ -@erase "$(INTDIR)\named-journalprint.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\named-journalprint.pdb"
+ -@erase "$(OUTDIR)\journalprint.bsc"
+ -@erase "..\..\..\Build\Debug\named-journalprint.exe"
+ -@erase "..\..\..\Build\Debug\named-journalprint.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\journalprint.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\named-journalprint.sbr"
+
+"$(OUTDIR)\journalprint.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-journalprint.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/named-journalprint.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\named-journalprint.obj"
+
+"..\..\..\Build\Debug\named-journalprint.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("journalprint.dep")
+!INCLUDE "journalprint.dep"
+!ELSE
+!MESSAGE Warning: cannot find "journalprint.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "journalprint - @PLATFORM@ Release" || "$(CFG)" == "journalprint - @PLATFORM@ Debug"
+SOURCE="..\named-journalprint.c"
+
+!IF "$(CFG)" == "journalprint - @PLATFORM@ Release"
+
+
+"$(INTDIR)\named-journalprint.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "journalprint - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\named-journalprint.obj" "$(INTDIR)\named-journalprint.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/journalprint.vcxproj.filters.in b/bin/tools/win32/journalprint.vcxproj.filters.in
new file mode 100644
index 0000000..cb89470
--- /dev/null
+++ b/bin/tools/win32/journalprint.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-journalprint.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/journalprint.vcxproj.in b/bin/tools/win32/journalprint.vcxproj.in
new file mode 100644
index 0000000..bd438f9
--- /dev/null
+++ b/bin/tools/win32/journalprint.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{B19042CE-D3D9-469B-BCD2-C3140150939A}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>journalprint</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-journalprint.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/journalprint.vcxproj.user b/bin/tools/win32/journalprint.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/journalprint.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/mdig.dsp.in b/bin/tools/win32/mdig.dsp.in
new file mode 100644
index 0000000..e2f00f8
--- /dev/null
+++ b/bin/tools/win32/mdig.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="mdig" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=mdig - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mdig.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mdig.mak" CFG="mdig - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mdig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "mdig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mdig - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/mdig.exe"
+
+!ELSEIF "$(CFG)" == "mdig - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/mdig.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "mdig - @PLATFORM@ Release"
+# Name "mdig - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\mdig.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/mdig.dsw b/bin/tools/win32/mdig.dsw
new file mode 100644
index 0000000..91619b8
--- /dev/null
+++ b/bin/tools/win32/mdig.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "mdig"=".\mdig.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/mdig.mak.in b/bin/tools/win32/mdig.mak.in
new file mode 100644
index 0000000..0478d03
--- /dev/null
+++ b/bin/tools/win32/mdig.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on mdig.dsp
+!IF "$(CFG)" == ""
+CFG=mdig - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to mdig - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "mdig - @PLATFORM@ Release" && "$(CFG)" != "mdig - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mdig.mak" CFG="mdig - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mdig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "mdig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "mdig - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "mdig - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\mdig.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\mdig.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\mdig.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\mdig.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mdig.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\mdig.pdb" @MACHINE@ /out:"../../../Build/Release/mdig.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\mdig.obj"
+
+"..\..\..\Build\Release\mdig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "mdig - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\mdig.exe" "$(OUTDIR)\mdig.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\mdig.obj"
+ -@erase "$(INTDIR)\mdig.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\mdig.pdb"
+ -@erase "$(OUTDIR)\mdig.bsc"
+ -@erase "..\..\..\Build\Debug\mdig.exe"
+ -@erase "..\..\..\Build\Debug\mdig.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\mdig.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\mdig.sbr"
+
+"$(OUTDIR)\mdig.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\mdig.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/mdig.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\mdig.obj"
+
+"..\..\..\Build\Debug\mdig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("mdig.dep")
+!INCLUDE "mdig.dep"
+!ELSE
+!MESSAGE Warning: cannot find "mdig.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "mdig - @PLATFORM@ Release" || "$(CFG)" == "mdig - @PLATFORM@ Debug"
+SOURCE="..\mdig.c"
+
+!IF "$(CFG)" == "mdig - @PLATFORM@ Release"
+
+
+"$(INTDIR)\mdig.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "mdig - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\mdig.obj" "$(INTDIR)\mdig.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/mdig.vcxproj.filters.in b/bin/tools/win32/mdig.vcxproj.filters.in
new file mode 100644
index 0000000..fbb8ba4
--- /dev/null
+++ b/bin/tools/win32/mdig.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\mdig.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/bin/tools/win32/mdig.vcxproj.in b/bin/tools/win32/mdig.vcxproj.in
new file mode 100644
index 0000000..ca6d334
--- /dev/null
+++ b/bin/tools/win32/mdig.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{3115091C-8135-481F-9757-F013A26255E0}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdig</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;libbind9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;libbind9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\mdig.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/mdig.vcxproj.user b/bin/tools/win32/mdig.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/mdig.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/nsec3hash.dsp.in b/bin/tools/win32/nsec3hash.dsp.in
new file mode 100644
index 0000000..22648cd
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="nsec3hash" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=nsec3hash - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nsec3hash.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsec3hash.mak" CFG="nsec3hash - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsec3hash - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nsec3hash - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsec3hash - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/nsec3hash.exe"
+
+!ELSEIF "$(CFG)" == "nsec3hash - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/nsec3hash.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nsec3hash - @PLATFORM@ Release"
+# Name "nsec3hash - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\nsec3hash.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/nsec3hash.dsw b/bin/tools/win32/nsec3hash.dsw
new file mode 100644
index 0000000..7ad0819
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nsec3hash"=".\nsec3hash.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/nsec3hash.mak.in b/bin/tools/win32/nsec3hash.mak.in
new file mode 100644
index 0000000..af5cf00
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nsec3hash.dsp
+!IF "$(CFG)" == ""
+CFG=nsec3hash - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to nsec3hash - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nsec3hash - @PLATFORM@ Release" && "$(CFG)" != "nsec3hash - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsec3hash.mak" CFG="nsec3hash - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsec3hash - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nsec3hash - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "nsec3hash - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "nsec3hash - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\nsec3hash.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\nsec3hash.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\nsec3hash.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nsec3hash.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsec3hash.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nsec3hash.pdb" @MACHINE@ /out:"../../../Build/Release/nsec3hash.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\nsec3hash.obj"
+
+"..\..\..\Build\Release\nsec3hash.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "nsec3hash - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\nsec3hash.exe" "$(OUTDIR)\nsec3hash.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\nsec3hash.obj"
+ -@erase "$(INTDIR)\nsec3hash.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\nsec3hash.pdb"
+ -@erase "$(OUTDIR)\nsec3hash.bsc"
+ -@erase "..\..\..\Build\Debug\nsec3hash.exe"
+ -@erase "..\..\..\Build\Debug\nsec3hash.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsec3hash.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\nsec3hash.sbr"
+
+"$(OUTDIR)\nsec3hash.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nsec3hash.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/nsec3hash.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\nsec3hash.obj"
+
+"..\..\..\Build\Debug\nsec3hash.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("nsec3hash.dep")
+!INCLUDE "nsec3hash.dep"
+!ELSE
+!MESSAGE Warning: cannot find "nsec3hash.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "nsec3hash - @PLATFORM@ Release" || "$(CFG)" == "nsec3hash - @PLATFORM@ Debug"
+SOURCE="..\nsec3hash.c"
+
+!IF "$(CFG)" == "nsec3hash - @PLATFORM@ Release"
+
+
+"$(INTDIR)\nsec3hash.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nsec3hash - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\nsec3hash.obj" "$(INTDIR)\nsec3hash.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/nsec3hash.vcxproj.filters.in b/bin/tools/win32/nsec3hash.vcxproj.filters.in
new file mode 100644
index 0000000..009e970
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nsec3hash.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/nsec3hash.vcxproj.in b/bin/tools/win32/nsec3hash.vcxproj.in
new file mode 100644
index 0000000..305a839
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4EE91023-94C3-48C0-B71C-5333B726C2EE}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>nsec3hash</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nsec3hash.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/nsec3hash.vcxproj.user b/bin/tools/win32/nsec3hash.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/rrchecker.dsp.in b/bin/tools/win32/rrchecker.dsp.in
new file mode 100644
index 0000000..058f46e
--- /dev/null
+++ b/bin/tools/win32/rrchecker.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="rrchecker" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=rrchecker - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rrchecker.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rrchecker.mak" CFG="rrchecker - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rrchecker - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rrchecker - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rrchecker - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named-rrchecker.exe"
+
+!ELSEIF "$(CFG)" == "rrchecker - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/named-rrchecker.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rrchecker - @PLATFORM@ Release"
+# Name "rrchecker - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\named-rrchecker.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/tools/win32/rrchecker.dsw b/bin/tools/win32/rrchecker.dsw
new file mode 100644
index 0000000..76ff3a9
--- /dev/null
+++ b/bin/tools/win32/rrchecker.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rrchecker"=".\rrchecker.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tools/win32/rrchecker.mak.in b/bin/tools/win32/rrchecker.mak.in
new file mode 100644
index 0000000..3811c38
--- /dev/null
+++ b/bin/tools/win32/rrchecker.mak.in
@@ -0,0 +1,299 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on rrchecker.dsp
+!IF "$(CFG)" == ""
+CFG=rrchecker - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to rrchecker - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rrchecker - @PLATFORM@ Release" && "$(CFG)" != "rrchecker - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rrchecker.mak" CFG="rrchecker - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rrchecker - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "rrchecker - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "rrchecker - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "rrchecker - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\named-rrchecker.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\named-rrchecker.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\named-rrchecker.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\named-rrchecker.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\named-rrchecker.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-rrchecker.pdb" @MACHINE@ /out:"../../../Build/Release/named-rrchecker.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\named-rrchecker.obj"
+
+"..\..\..\Build\Release\named-rrchecker.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "rrchecker - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\named-rrchecker.exe" "$(OUTDIR)\named-rrchecker.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\named-rrchecker.obj"
+ -@erase "$(INTDIR)\named-rrchecker.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\named-rrchecker.pdb"
+ -@erase "$(OUTDIR)\named-rrchecker.bsc"
+ -@erase "..\..\..\Build\Debug\named-rrchecker.exe"
+ -@erase "..\..\..\Build\Debug\named-rrchecker.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\named-rrchecker.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\named-rrchecker.sbr"
+
+"$(OUTDIR)\named-rrchecker.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-rrchecker.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/named-rrchecker.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\named-rrchecker.obj"
+
+"..\..\..\Build\Debug\named-rrchecker.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("rrchecker.dep")
+!INCLUDE "rrchecker.dep"
+!ELSE
+!MESSAGE Warning: cannot find "rrchecker.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rrchecker - @PLATFORM@ Release" || "$(CFG)" == "rrchecker - @PLATFORM@ Debug"
+SOURCE="..\named-rrchecker.c"
+
+!IF "$(CFG)" == "rrchecker - @PLATFORM@ Release"
+
+
+"$(INTDIR)\named-rrchecker.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rrchecker - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\named-rrchecker.obj" "$(INTDIR)\named-rrchecker.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/tools/win32/rrchecker.vcxproj.filters.in b/bin/tools/win32/rrchecker.vcxproj.filters.in
new file mode 100644
index 0000000..d7f077d
--- /dev/null
+++ b/bin/tools/win32/rrchecker.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-rrchecker.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/bin/tools/win32/rrchecker.vcxproj.in b/bin/tools/win32/rrchecker.vcxproj.in
new file mode 100644
index 0000000..52b34e7
--- /dev/null
+++ b/bin/tools/win32/rrchecker.vcxproj.in
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{98743A7C-6AF8-467f-9911-FA69C451AF2B}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>rrchecker</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-rrchecker.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/rrchecker.vcxproj.user b/bin/tools/win32/rrchecker.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/tools/win32/rrchecker.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/win32/BINDInstall/AccountInfo.cpp b/bin/win32/BINDInstall/AccountInfo.cpp
new file mode 100644
index 0000000..73357a8
--- /dev/null
+++ b/bin/win32/BINDInstall/AccountInfo.cpp
@@ -0,0 +1,456 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* Compiled with UNICODE */
+
+#include "stdafx.h"
+
+#include <windows.h>
+#include <lm.h>
+#include <ntsecapi.h>
+
+#include <isc/ntgroups.h>
+#include <isc/result.h>
+#include "AccountInfo.h"
+
+#define MAX_NAME_LENGTH 256
+
+NTSTATUS
+OpenPolicy(
+ LPWSTR ServerName, /* machine to open policy on (Unicode) */
+ DWORD DesiredAccess, /* desired access to policy */
+ PLSA_HANDLE PolicyHandle /* resultant policy handle */
+ );
+
+BOOL
+GetAccountSid(
+ LPTSTR SystemName, /* where to lookup account */
+ LPTSTR AccountName, /* account of interest */
+ PSID *Sid /* resultant buffer containing SID */
+ );
+
+NTSTATUS
+SetPrivilegeOnAccount(
+ LSA_HANDLE PolicyHandle, /* open policy handle */
+ PSID AccountSid, /* SID to grant privilege to */
+ LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
+ BOOL bEnable /* enable or disable */
+ );
+
+NTSTATUS
+GetPrivilegesOnAccount(
+ LSA_HANDLE PolicyHandle, /* open policy handle */
+ PSID AccountSid, /* SID to grant privilege to */
+ wchar_t **PrivList, /* Ptr to List of Privileges found */
+ unsigned int *PrivCount /* total number of Privileges in list */
+ );
+
+NTSTATUS
+AddPrivilegeToAcccount(
+ LPTSTR AccountName, /* Name of the account */
+ LPWSTR PrivilegeName /* Privilege to Add */
+ );
+
+void
+InitLsaString(
+ PLSA_UNICODE_STRING LsaString, /* destination */
+ LPWSTR String /* source (Unicode) */
+ );
+
+void
+DisplayNtStatus(
+ LPSTR szAPI, /* pointer to function name (ANSI) */
+ NTSTATUS Status /* NTSTATUS error value */
+ );
+
+void
+DisplayWinError(
+ LPSTR szAPI, /* pointer to function name (ANSI) */
+ DWORD WinError /* DWORD WinError */
+ );
+
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#endif
+
+/*
+ * Note that this code only retrieves the list of privileges of the
+ * requested account or group. However, all accounts belong to the
+ * Everyone group even though that group is not returned by the
+ * calls to get the groups to which that account belongs.
+ * The Everyone group has two privileges associated with it:
+ * SeChangeNotifyPrivilege and SeNetworkLogonRight
+ * It is not advisable to disable or remove these privileges
+ * from the group nor can the account be removed from the Everyone
+ * group
+ * The None group has no privileges associated with it and is the group
+ * to which an account belongs if it is associated with no group.
+ */
+
+int
+GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
+ char **Accounts, unsigned int *totalAccounts,
+ int maxAccounts)
+{
+ LSA_HANDLE PolicyHandle;
+ TCHAR AccountName[256]; /* static account name buffer */
+ PSID pSid;
+ unsigned int i;
+ NTSTATUS Status;
+ isc_result_t istatus;
+ int iRetVal = RTN_ERROR; /* assume error from main */
+ int n;
+
+ /*
+ * Open the policy on the target machine.
+ */
+ if ((Status = OpenPolicy(NULL,
+ POLICY_LOOKUP_NAMES,
+ &PolicyHandle)) != STATUS_SUCCESS)
+ return (RTN_ERROR);
+
+ /*
+ * Let's see if the account exists. Return if not
+ */
+ n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"), name);
+ if (n < 0 || (size_t)n >= sizeof(AccountName)) {
+ LsaClose(PolicyHandle);
+ return (RTN_ERROR);
+ }
+
+ if (!GetAccountSid(NULL, AccountName, &pSid)) {
+ LsaClose(PolicyHandle);
+ return (RTN_NOACCOUNT);
+ }
+
+ /*
+ * Find out what groups the account belongs to
+ */
+ istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
+ totalAccounts);
+ if (istatus == ISC_R_NOMEMORY) {
+ LsaClose(PolicyHandle);
+ return (RTN_NOMEMORY);
+ } else if (istatus != ISC_R_SUCCESS) {
+ LsaClose(PolicyHandle);
+ return (RTN_ERROR);
+ }
+
+ Accounts[*totalAccounts] = name; /* Add the account to the list */
+ (*totalAccounts)++;
+
+ /*
+ * Loop through each Account to get the list of privileges
+ */
+ for (i = 0; i < *totalAccounts; i++) {
+ n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"),
+ Accounts[i]);
+ if (n < 0 || (size_t)n >= sizeof(AccountName)) {
+ continue;
+ }
+
+ /* Obtain the SID of the user/group. */
+ if (!GetAccountSid(NULL, AccountName, &pSid)) {
+ continue; /* Try the next one */
+ }
+
+ /* Get the Privileges allocated to this SID */
+ if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
+ PrivList, PrivCount)) == STATUS_SUCCESS)
+ {
+ iRetVal=RTN_OK;
+ if (pSid != NULL)
+ HeapFree(GetProcessHeap(), 0, pSid);
+ } else {
+ if (pSid != NULL)
+ HeapFree(GetProcessHeap(), 0, pSid);
+ continue; /* Try the next one */
+ }
+ }
+
+ /*
+ * Close the policy handle.
+ */
+ LsaClose(PolicyHandle);
+
+ (*totalAccounts)--; /* Correct for the number of groups */
+ return iRetVal;
+}
+
+BOOL
+CreateServiceAccount(char *name, char *password) {
+ NTSTATUS retstat;
+ USER_INFO_1 ui;
+ DWORD dwLevel = 1;
+ DWORD dwError = 0;
+ NET_API_STATUS nStatus;
+
+ size_t namelen = strlen(name);
+ size_t passwdlen = strlen(password);
+ wchar_t AccountName[MAX_NAME_LENGTH];
+ wchar_t AccountPassword[MAX_NAME_LENGTH];
+
+ mbstowcs(AccountName, name, namelen + 1);
+ mbstowcs(AccountPassword, password, passwdlen + 1);
+
+ /*
+ * Set up the USER_INFO_1 structure.
+ * USER_PRIV_USER: name is required here when creating an account
+ * rather than an administrator or a guest.
+ */
+
+ ui.usri1_name = (LPWSTR) &AccountName;
+ ui.usri1_password = (LPWSTR) &AccountPassword;
+ ui.usri1_priv = USER_PRIV_USER;
+ ui.usri1_home_dir = NULL;
+ ui.usri1_comment = L"ISC BIND Service Account";
+ ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD |
+ UF_SCRIPT;
+ ui.usri1_script_path = NULL;
+ /*
+ * Call the NetUserAdd function, specifying level 1.
+ */
+ nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
+
+ if (nStatus != NERR_Success)
+ return (FALSE);
+
+ retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
+ return (TRUE);
+}
+
+NTSTATUS
+AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
+ LSA_HANDLE PolicyHandle;
+ TCHAR AccountName[256]; /* static account name buffer */
+ PSID pSid;
+ NTSTATUS Status;
+ unsigned long err;
+ int n;
+
+ /*
+ * Open the policy on the target machine.
+ */
+ if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
+ != STATUS_SUCCESS)
+ return (RTN_ERROR);
+
+ /*
+ * Let's see if the account exists. Return if not
+ */
+ n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"), name);
+ if (n < 0 || (size_t)n >= sizeof(AccountName)) {
+ LsaClose(PolicyHandle);
+ return (RTN_ERROR);
+ }
+
+ if (!GetAccountSid(NULL, AccountName, &pSid)) {
+ LsaClose(PolicyHandle);
+ return (RTN_NOACCOUNT);
+ }
+
+ err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
+ pSid, PrivilegeName, TRUE));
+
+ LsaClose(PolicyHandle);
+ if (err == ERROR_SUCCESS)
+ return (RTN_OK);
+ else
+ return (err);
+}
+
+void
+InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
+ size_t StringLength;
+
+ if (String == NULL) {
+ LsaString->Buffer = NULL;
+ LsaString->Length = 0;
+ LsaString->MaximumLength = 0;
+ return;
+ }
+
+ StringLength = wcslen(String);
+ LsaString->Buffer = String;
+ LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
+ LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
+}
+
+NTSTATUS
+OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
+ LSA_OBJECT_ATTRIBUTES ObjectAttributes;
+ LSA_UNICODE_STRING ServerString;
+ PLSA_UNICODE_STRING Server = NULL;
+
+ /*
+ * Always initialize the object attributes to all zeroes.
+ */
+ ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
+
+ if (ServerName != NULL) {
+ /*
+ * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
+ */
+ InitLsaString(&ServerString, ServerName);
+ Server = &ServerString;
+ }
+
+ /*
+ * Attempt to open the policy.
+ */
+ return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
+ PolicyHandle));
+}
+
+BOOL
+GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
+ LPTSTR ReferencedDomain = NULL;
+ DWORD cbSid = 128; /* initial allocation attempt */
+ DWORD cbReferencedDomain = 16; /* initial allocation size */
+ SID_NAME_USE peUse;
+ BOOL bSuccess = FALSE; /* assume this function will fail */
+
+ __try {
+ /*
+ * initial memory allocations
+ */
+ if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
+ __leave;
+
+ if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
+ cbReferencedDomain)) == NULL) __leave;
+
+ /*
+ * Obtain the SID of the specified account on the specified system.
+ */
+ while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
+ ReferencedDomain, &cbReferencedDomain,
+ &peUse))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ /* reallocate memory */
+ if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
+ *Sid, cbSid)) == NULL) __leave;
+
+ if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
+ GetProcessHeap(), 0, ReferencedDomain,
+ cbReferencedDomain)) == NULL)
+ __leave;
+ }
+ else
+ __leave;
+ }
+ bSuccess = TRUE;
+ } /* finally */
+ __finally {
+
+ /* Cleanup and indicate failure, if appropriate. */
+
+ HeapFree(GetProcessHeap(), 0, ReferencedDomain);
+
+ if (!bSuccess) {
+ if (*Sid != NULL) {
+ HeapFree(GetProcessHeap(), 0, *Sid);
+ *Sid = NULL;
+ }
+ }
+
+ }
+
+ return (bSuccess);
+}
+
+NTSTATUS
+SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
+ LPWSTR PrivilegeName, BOOL bEnable)
+{
+ LSA_UNICODE_STRING PrivilegeString;
+
+ /* Create a LSA_UNICODE_STRING for the privilege name. */
+ InitLsaString(&PrivilegeString, PrivilegeName);
+
+ /* grant or revoke the privilege, accordingly */
+ if (bEnable)
+ return (LsaAddAccountRights(PolicyHandle, AccountSid,
+ &PrivilegeString, 1));
+ else
+ return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
+ FALSE, &PrivilegeString, 1));
+}
+
+NTSTATUS
+GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
+ wchar_t **PrivList, unsigned int *PrivCount)
+{
+ NTSTATUS Status;
+ LSA_UNICODE_STRING *UserRights;
+ ULONG CountOfRights;
+ unsigned int retlen = 0;
+ DWORD i, j;
+ int found;
+
+ Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
+ &UserRights, &CountOfRights);
+ /* Only continue if there is something */
+ if (UserRights == NULL || Status != STATUS_SUCCESS)
+ return (Status);
+
+ for (i = 0; i < CountOfRights; i++) {
+ found = -1;
+ retlen = UserRights[i].Length/sizeof(wchar_t);
+ for (j = 0; j < *PrivCount; j++) {
+ found = wcsncmp(PrivList[j], UserRights[i].Buffer,
+ retlen);
+ if (found == 0)
+ break;
+ }
+ if (found != 0) {
+ PrivList[*PrivCount] =
+ (wchar_t *)malloc(UserRights[i].MaximumLength);
+ if (PrivList[*PrivCount] == NULL)
+ return (RTN_NOMEMORY);
+
+ wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
+ retlen);
+ PrivList[*PrivCount][retlen] = L'\0';
+ (*PrivCount)++;
+ }
+
+ }
+
+ return (Status);
+}
+
+void
+DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
+ /* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
+ DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
+}
+
+void
+DisplayWinError(LPSTR szAPI, DWORD WinError) {
+ LPSTR MessageBuffer;
+ DWORD dwBufferLength;
+
+ if (dwBufferLength=FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, WinError, GetUserDefaultLangID(),
+ (LPSTR) &MessageBuffer, 0, NULL)){
+ DWORD dwBytesWritten; /* unused */
+
+ /* Output message string on stderr. */
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
+ dwBufferLength, &dwBytesWritten, NULL);
+
+ /* Free the buffer allocated by the system. */
+ LocalFree(MessageBuffer);
+ }
+}
diff --git a/bin/win32/BINDInstall/AccountInfo.h b/bin/win32/BINDInstall/AccountInfo.h
new file mode 100644
index 0000000..1eb684d
--- /dev/null
+++ b/bin/win32/BINDInstall/AccountInfo.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+
+#define RTN_OK 0
+#define RTN_NOACCOUNT 1
+#define RTN_NOMEMORY 2
+#define RTN_ERROR 10
+
+#define SE_SERVICE_LOGON_PRIV L"SeServiceLogonRight"
+
+/*
+ * This routine retrieves the list of all Privileges associated with
+ * a given account as well as the groups to which it beongs
+ */
+int
+GetAccountPrivileges(
+ char *name, /* Name of Account */
+ wchar_t **PrivList, /* List of Privileges returned */
+ unsigned int *PrivCount, /* Count of Privileges returned */
+ char **Groups, /* List of Groups to which account belongs */
+ unsigned int *totalGroups, /* Count of Groups returned */
+ int maxGroups /* Maximum number of Groups to return */
+ );
+
+/*
+ * This routine creates an account with the given name which has just
+ * the logon service privilege and no membership of any groups,
+ * i.e. it's part of the None group.
+ */
+BOOL
+CreateServiceAccount(char *name, char *password);
diff --git a/bin/win32/BINDInstall/BINDInstall.cpp b/bin/win32/BINDInstall/BINDInstall.cpp
new file mode 100644
index 0000000..5ee0981
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.cpp
@@ -0,0 +1,98 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * 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 NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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 "stdafx.h"
+#include "BINDInstall.h"
+#include "BINDInstallDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallApp
+
+BEGIN_MESSAGE_MAP(CBINDInstallApp, CWinApp)
+ //{{AFX_MSG_MAP(CBINDInstallApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallApp construction
+
+CBINDInstallApp::CBINDInstallApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CBINDInstallApp object
+
+CBINDInstallApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallApp initialization
+
+BOOL CBINDInstallApp::InitInstance()
+{
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+#if _MSC_VER < 1300
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+#endif
+
+ CBINDInstallDlg dlg;
+ m_pMainWnd = &dlg;
+ INT_PTR nResponse = dlg.DoModal();
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
diff --git a/bin/win32/BINDInstall/BINDInstall.dsp.in b/bin/win32/BINDInstall/BINDInstall.dsp.in
new file mode 100644
index 0000000..11d2dfa
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.dsp.in
@@ -0,0 +1,177 @@
+# Microsoft Developer Studio Project File - Name="BINDInstall" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Application" 0x0101
+
+CFG=BINDInstall - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "BINDInstall.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "BINDInstall.mak" CFG="BINDInstall - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BINDInstall - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Application")
+!MESSAGE "BINDInstall - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /I "..\..\.." /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ @USE_PYTHON@ /Yu"stdafx.h" /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows @MACHINE@
+# ADD LINK32 version.lib netapi32.lib /nologo /subsystem:windows /pdb:none @MACHINE@ /out:"..\..\..\Build\Release\BINDInstall.exe"
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /Zi /Od /I "..\..\.." /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ @USE_PYTHON@ /FR /Yu"stdafx.h" /FD /TP /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 version.lib netapi32.lib /nologo /subsystem:windows /pdb:none /debug @MACHINE@ /out:"..\..\..\Build\Debug\BINDInstall.exe"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BINDInstall - @PLATFORM@ Release"
+# Name "BINDInstall - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\AccountInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstall.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstallDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DirBrowse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\lib\isc\win32\ntgroups.c
+# SUBTRACT CPP @COPTY@ /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\VersionInfo.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Accountinfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstall.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstallDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DirBrowse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\lib\isc\win32\include\isc\ntgroups.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\VersionInfo.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\BINDInstall.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\BINDInstall.rc2
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\BINDInstall.rc
+# End Source File
+# End Target
+# End Project
diff --git a/bin/win32/BINDInstall/BINDInstall.dsw b/bin/win32/BINDInstall/BINDInstall.dsw
new file mode 100644
index 0000000..c949bc7
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BINDInstall"=.\BINDInstall.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/win32/BINDInstall/BINDInstall.h b/bin/win32/BINDInstall/BINDInstall.h
new file mode 100644
index 0000000..1d12d5e
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.h
@@ -0,0 +1,57 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * 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 NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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.
+ */
+
+#ifndef BINDINSTALL_H
+#define BINDINSTALL_H
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+class CBINDInstallApp : public CWinApp
+{
+public:
+ CBINDInstallApp();
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBINDInstallApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+ //{{AFX_MSG(CBINDInstallApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif
diff --git a/bin/win32/BINDInstall/BINDInstall.mak.in b/bin/win32/BINDInstall/BINDInstall.mak.in
new file mode 100644
index 0000000..5b53ea2
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.mak.in
@@ -0,0 +1,428 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on BINDInstall.dsp
+!IF "$(CFG)" == ""
+CFG=BINDInstall - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to BINDInstall - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "BINDInstall - @PLATFORM@ Release" && "$(CFG)" != "BINDInstall - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "BINDInstall.mak" CFG="BINDInstall - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BINDInstall - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Application")
+!MESSAGE "BINDInstall - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\BINDInstall.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\AccountInfo.obj"
+ -@erase "$(INTDIR)\BINDInstall.obj"
+ -@erase "$(INTDIR)\BINDInstall.pch"
+ -@erase "$(INTDIR)\BINDInstall.res"
+ -@erase "$(INTDIR)\BINDInstallDlg.obj"
+ -@erase "$(INTDIR)\DirBrowse.obj"
+ -@erase "$(INTDIR)\ntgroups.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\VersionInfo.obj"
+ -@erase "..\..\..\Build\Release\BINDInstall.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MT /W3 @COPTX@ @COPTI@ /O2 /I "..\..\.." /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ @USE_PYTHON@ /Fp"$(INTDIR)\BINDInstall.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\BINDInstall.res" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\BINDInstall.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=version.lib netapi32.lib /nologo /subsystem:windows /pdb:none @MACHINE@ /out:"..\..\..\Build\Release\BINDInstall.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\AccountInfo.obj" \
+ "$(INTDIR)\BINDInstall.obj" \
+ "$(INTDIR)\BINDInstallDlg.obj" \
+ "$(INTDIR)\DirBrowse.obj" \
+ "$(INTDIR)\ntgroups.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\VersionInfo.obj" \
+ "$(INTDIR)\BINDInstall.res"
+
+"..\..\..\Build\Release\BINDInstall.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\BINDInstall.exe" "$(OUTDIR)\BINDInstall.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\AccountInfo.obj"
+ -@erase "$(INTDIR)\AccountInfo.sbr"
+ -@erase "$(INTDIR)\BINDInstall.obj"
+ -@erase "$(INTDIR)\BINDInstall.pch"
+ -@erase "$(INTDIR)\BINDInstall.res"
+ -@erase "$(INTDIR)\BINDInstall.sbr"
+ -@erase "$(INTDIR)\BINDInstallDlg.obj"
+ -@erase "$(INTDIR)\BINDInstallDlg.sbr"
+ -@erase "$(INTDIR)\DirBrowse.obj"
+ -@erase "$(INTDIR)\DirBrowse.sbr"
+ -@erase "$(INTDIR)\ntgroups.obj"
+ -@erase "$(INTDIR)\ntgroups.sbr"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\StdAfx.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\VersionInfo.obj"
+ -@erase "$(INTDIR)\VersionInfo.sbr"
+ -@erase "$(OUTDIR)\BINDInstall.bsc"
+ -@erase "..\..\..\Build\Debug\BINDInstall.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /Zi /Od /I "..\..\.." /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ @USE_PYTHON@ /FR"$(INTDIR)\\" /Fp"$(INTDIR)\BINDInstall.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\BINDInstall.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\BINDInstall.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\AccountInfo.sbr" \
+ "$(INTDIR)\BINDInstall.sbr" \
+ "$(INTDIR)\BINDInstallDlg.sbr" \
+ "$(INTDIR)\DirBrowse.sbr" \
+ "$(INTDIR)\ntgroups.sbr" \
+ "$(INTDIR)\StdAfx.sbr" \
+ "$(INTDIR)\VersionInfo.sbr"
+
+"$(OUTDIR)\BINDInstall.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=version.lib netapi32.lib /nologo /subsystem:windows /pdb:none /debug @MACHINE@ /out:"..\..\..\Build\Debug\BINDInstall.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\AccountInfo.obj" \
+ "$(INTDIR)\BINDInstall.obj" \
+ "$(INTDIR)\BINDInstallDlg.obj" \
+ "$(INTDIR)\DirBrowse.obj" \
+ "$(INTDIR)\ntgroups.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\VersionInfo.obj" \
+ "$(INTDIR)\BINDInstall.res"
+
+"..\..\..\Build\Debug\BINDInstall.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("BINDInstall.dep")
+!INCLUDE "BINDInstall.dep"
+!ELSE
+!MESSAGE Warning: cannot find "BINDInstall.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release" || "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+SOURCE=.\AccountInfo.cpp
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+
+"$(INTDIR)\AccountInfo.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\AccountInfo.obj" "$(INTDIR)\AccountInfo.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\BINDInstall.cpp
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+
+"$(INTDIR)\BINDInstall.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\BINDInstall.obj" "$(INTDIR)\BINDInstall.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\BINDInstallDlg.cpp
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+
+"$(INTDIR)\BINDInstallDlg.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\BINDInstallDlg.obj" "$(INTDIR)\BINDInstallDlg.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\DirBrowse.cpp
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+
+"$(INTDIR)\DirBrowse.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\DirBrowse.obj" "$(INTDIR)\DirBrowse.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=..\..\..\lib\isc\win32\ntgroups.c
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+CPP_SWITCHES=/nologo /MT /W3 @COPTX@ @COPTI@ /O2 /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /c
+
+"$(INTDIR)\ntgroups.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+CPP_SWITCHES=/nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /Zi /Od /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /GZ /c
+
+"$(INTDIR)\ntgroups.obj" "$(INTDIR)\ntgroups.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\StdAfx.cpp
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+CPP_SWITCHES=/nologo /MT /W3 @COPTX@ @COPTI@ /O2 /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ /Fp"$(INTDIR)\BINDInstall.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /c
+
+"$(INTDIR)\StdAfx.obj" "$(INTDIR)\BINDInstall.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+CPP_SWITCHES=/nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /Zi /Od /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @CRYPTO@ @USE_GSSAPI@ /FR"$(INTDIR)\\" /Fp"$(INTDIR)\BINDInstall.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /GZ /c
+
+"$(INTDIR)\StdAfx.obj" "$(INTDIR)\StdAfx.sbr" "$(INTDIR)\BINDInstall.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\VersionInfo.cpp
+
+!IF "$(CFG)" == "BINDInstall - @PLATFORM@ Release"
+
+
+"$(INTDIR)\VersionInfo.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\VersionInfo.obj" "$(INTDIR)\VersionInfo.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\BINDInstall.rc
+
+"$(INTDIR)\BINDInstall.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/win32/BINDInstall/BINDInstall.rc b/bin/win32/BINDInstall/BINDInstall.rc
new file mode 100644
index 0000000..be9550b
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.rc
@@ -0,0 +1,324 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif //_WIN32\r\n"
+ "#include ""res\\BINDInstall.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON "res\\BINDInstall.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_BINDINSTALL_DIALOG DIALOGEX 0, 0, 210, 311
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "BIND 9 Installer"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_TARGETDIR,7,62,196,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_ACCOUNT_NAME,7,94,196,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_ACCOUNT_PASSWORD,7,122,196,14,ES_PASSWORD | ES_AUTOHSCROLL
+ EDITTEXT IDC_ACCOUNT_PASSWORD_CONFIRM,7,151,196,14,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Install",IDC_INSTALL,153,7,50,14
+ PUSHBUTTON "E&xit",IDC_EXIT,153,39,50,14
+ CONTROL "&Tools Only",IDC_TOOLS_ONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,185,72,10
+ CONTROL "&Automatic Startup",IDC_AUTO_START,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,195,72,10
+ CONTROL "&Keep Config Files After Uninstall",IDC_KEEP_FILES,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,205,116,10
+ CONTROL "&Start BIND Service After Install",IDC_START,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,215,113,10
+ PUSHBUTTON "&Uninstall",IDC_UNINSTALL,153,23,50,14
+ PUSHBUTTON "Browse",IDC_BROWSE,7,22,50,14
+ LTEXT "Target Directory:",IDC_STATIC,7,53,54,8
+ GROUPBOX "Progress",IDC_STATIC,7,234,196,70
+ RTEXT "",IDC_COPY_TAG,14,271,78,8
+ LTEXT "",IDC_COPY_FILE,105,271,90,8
+ RTEXT "",IDC_SERVICE_TAG,15,281,77,8
+ LTEXT "",IDC_REG_SERVICE,105,281,89,8
+ RTEXT "",IDC_MESSAGE_TAG,15,291,77,8
+ LTEXT "",IDC_REG_MESSAGE,105,291,88,8
+ RTEXT "",IDC_DIR_TAG,15,261,77,8
+ GROUPBOX "Options",IDC_STATIC,7,172,196,60
+ CTEXT "Version Unknown",IDC_VERSION,7,7,61,10,SS_CENTERIMAGE | SS_SUNKEN
+ RTEXT "Current Operation:",IDC_CURRENT_TAG,34,245,58,8
+ LTEXT "",IDC_CURRENT,105,245,90,8
+ LTEXT "",IDC_CREATE_DIR,105,261,88,8
+ LTEXT "Service Account Name",IDC_STATIC,7,84,74,8
+ LTEXT "Service Account Password",IDC_STATIC,7,112,86,8
+ LTEXT "Confirm Service Account Password",IDC_STATIC,7,140,112,8
+END
+
+IDD_BROWSE DIALOG 0, 0, 227, 117
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Select Directory"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,170,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,170,24,50,14
+ LISTBOX IDC_DIRLIST,7,28,155,82,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_CURDIR,7,7,155,14,ES_AUTOHSCROLL
+ COMBOBOX IDC_DRIVES,170,98,50,74,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_DIALOG1 DIALOG 0, 0, 186, 95
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,0,0,0
+ PRODUCTVERSION 3,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Internet Systems Consortium"
+ VALUE "FileDescription", "ISC BIND 9 Install Utility"
+ VALUE "FileVersion", "3.0.0"
+ VALUE "InternalName", "BINDInstall"
+ VALUE "LegalCopyright", "Copyright © 2000,2014"
+ VALUE "OriginalFilename", "BINDInstall.EXE"
+ VALUE "ProductName", "ISC BIND 9"
+ VALUE "ProductVersion", "9.10.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_BINDINSTALL_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 203
+ VERTGUIDE, 14
+ VERTGUIDE, 92
+ VERTGUIDE, 105
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 294
+ HORZGUIDE, 195
+ HORZGUIDE, 205
+ HORZGUIDE, 215
+ HORZGUIDE, 239
+ HORZGUIDE, 255
+ HORZGUIDE, 265
+ HORZGUIDE, 275
+ HORZGUIDE, 285
+ HORZGUIDE, 295
+ END
+
+ IDD_BROWSE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 220
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 110
+ END
+
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_MAINFRAME "BIND 9 Installer"
+ IDS_CREATEDIR "Directory %s does not exist.\nDo you wish to create it?"
+ IDS_SUCCESS "BIND installation completed successfully"
+ IDS_FAIL "BIND installation failed"
+ IDS_DIREXIST "Directory %s exists.\n Install here anyway?"
+ IDS_INSTALL_DIR "Create Directories..."
+ IDS_INSTALL_FILE "Copy Files..."
+ IDS_INSTALL_SERVICE "Register Service..."
+ IDS_INSTALL_MESSAGE "Register Messages..."
+ IDS_UNINSTALL "Do you wish to uninstall BIND?"
+ IDS_UNINSTALL_DONE "BIND Uninstall Completed"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_CREATE_KEY "Creating BIND registry key"
+ IDS_ADD_REMOVE "Setting up Add/Remove Programs entry"
+ IDS_CLEANUP "Cleaning up"
+ IDS_INSTALL_DONE "Finished Installing"
+ IDS_CREATE_DIR "Creating directory %s"
+ IDS_REMOVE_DIR "Removing directory %s"
+ IDS_COPY_FILE "Copying file %s"
+ IDS_DELETE_FILE "Deleting file %s"
+ IDS_OPEN_SCM "Opening Service Control Manager"
+ IDS_CREATE_SERVICE "Creating BIND service"
+ IDS_OPEN_SERVICE "Opening BIND service"
+ IDS_REMOVE_SERVICE "Removing BIND service"
+ IDS_REGISTER_MESSAGES "Registering BIND message source"
+ IDS_UNREGISTER_MESSAGES "Unregistering BIND message source"
+ IDS_STOP_SERVICE "Stopping BIND service"
+ IDS_START_SERVICE "Starting BIND service"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_UNINSTALL_DIR "Remove Directories..."
+ IDS_UNINSTALL_FILES "Delete Files..."
+ IDS_UNINSTALL_SERVICE "Unregister Service..."
+ IDS_UNINSTALL_MESSAGE "Unregister Messages..."
+ IDS_ERR_OPEN_SCM "Could not open Service Control Manager\n(%s)"
+ IDS_ERR_OPEN_SERVICE "Could not open BIND Service\n(%s)"
+ IDS_ERR_STOP_SERVICE "Could not stop BIND Service\n(%s)"
+ IDS_ERR_NONCRIT_FILE "An error occurred while copying non-critical file %s\n(%s)\nDo you wish to continue?"
+ IDS_ERR_COPY_FILE "An error occurred while copying file %s\n(%s)\nInstallation will be terminated"
+ IDS_ERR_CREATE_SERVICE "Error creating service\n(%s)"
+ IDS_ERR_REMOVE_SERVICE "Error removing service\n(%s)"
+ IDS_REBOOT "BINDInstall needs to restart Windows.\nDo you wish to restart now?"
+ IDS_BAD_PRIVILEGES "This user cannot acquire the privileges necessary to install BIND. Please ensure you are logged on as a member of the Administrators group."
+ IDS_ERR_CREATE_DIR "An error occurred while creating directory %s\n(%s)"
+ IDS_VERSION "Version %s"
+ IDS_ERR_CREATE_KEY "An error occured while creating registry keys\n(%s)"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_ERR_SET_VALUE "An error occured while setting registry key values\n(%s)"
+ IDS_NO_VERSION "Version Unknown"
+ IDS_EXISTING_NEWER "%s\nThe existing version of this file is newer than the version being installed.\nDo you wish to overwrite the existing file?"
+ IDS_FILE_BAD "Could not retrieve version info for file %s. Do you wish to continue?\n(Continuing may overwrite a newer version of the file) "
+ IDS_ERR_TOOPRIVED "Chosen account has too many privileges. Do you wish to choose a different account name?"
+ IDS_ERR_BADACCOUNT "Error Validating Account. Unable to install service using this account."
+ IDS_ERR_WRONGPRIV "The wrong privilege: %s was detected. Only the Service Logon Right privilege should be enabled for this account."
+ IDS_CREATEACCOUNT_FAILED "Unable to Create Account for the Service."
+ IDS_ERR_PASSWORD "Passwords entered did not match. Please reenter password."
+ IDS_ERR_UPDATE_SERVICE "Error updating service\n(%s)"
+ IDS_ERR_NULLPASSWORD "Service account password cannot be null"
+ IDS_ERR_WHITESPACE "Service account password has leading/trailing whitespace"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\BINDInstall.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/bin/win32/BINDInstall/BINDInstall.vcxproj.filters.in b/bin/win32/BINDInstall/BINDInstall.vcxproj.filters.in
new file mode 100644
index 0000000..0cb0eb4
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.vcxproj.filters.in
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\lib\isc\win32\include\isc\ntgroups.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="AccountInfo.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="BINDInstall.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="BINDInstallDlg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="DirBrowse.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="StdAfx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="VersionInfo.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="AccountInfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="BINDInstall.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="BINDInstallDlg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DirBrowse.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="StdAfx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="VersionInfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\lib\isc\win32\ntgroups.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\BINDInstall.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\BINDInstall.rc2">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="BINDInstall.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/win32/BINDInstall/BINDInstall.vcxproj.in b/bin/win32/BINDInstall/BINDInstall.vcxproj.in
new file mode 100644
index 0000000..255b72b
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.vcxproj.in
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{190CC424-E8CC-46F2-9013-3152D6905118}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>BINDInstall</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <UseOfMfc>Static</UseOfMfc>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <UseOfMfc>Static</UseOfMfc>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@@USE_GSSAPI@@USE_PYTHON@_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\include;..\..\..\include;..\..\named\win32\include;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <StringPooling>
+ </StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>nafxcwd.lib;version.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <EnableUAC>false</EnableUAC>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>false</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@@USE_GSSAPI@@USE_PYTHON@NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\include;..\..\..\include;..\..\named\win32\include;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>nafxcw.lib;version.lib;netapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <EnableUAC>false</EnableUAC>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\lib\isc\win32\include\isc\ntgroups.h" />
+ <ClInclude Include="AccountInfo.h" />
+ <ClInclude Include="BINDInstall.h" />
+ <ClInclude Include="BINDInstallDlg.h" />
+ <ClInclude Include="DirBrowse.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="StdAfx.h" />
+ <ClInclude Include="VersionInfo.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\lib\isc\win32\ntgroups.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="AccountInfo.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">UNICODE;WIN32;@CRYPTO@@USE_GSSAPI@@USE_PYTHON@NDEBUG;_WINDOWS;_MBCS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">UNICODE;WIN32;@CRYPTO@@USE_GSSAPI@@USE_PYTHON@_DEBUG;_WINDOWS;_MBCS</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="BINDInstall.cpp" />
+ <ClCompile Include="BINDInstallDlg.cpp" />
+ <ClCompile Include="DirBrowse.cpp" />
+ <ClCompile Include="StdAfx.cpp">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="VersionInfo.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\BINDInstall.ico" />
+ <None Include="res\BINDInstall.rc2" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="BINDInstall.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/win32/BINDInstall/BINDInstall.vcxproj.user b/bin/win32/BINDInstall/BINDInstall.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/win32/BINDInstall/BINDInstallDlg.cpp b/bin/win32/BINDInstall/BINDInstallDlg.cpp
new file mode 100644
index 0000000..f3446e5
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstallDlg.cpp
@@ -0,0 +1,1590 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * 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 NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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.
+ */
+
+/*
+ * Define this to make a standalone installer that will copy msvcrt.dll
+ * and/or msvcrtd.dll during the install
+ */
+// #define BINARIES_INSTALL
+
+/*
+ * msvcrt.dll is the release c-runtime library for MSVC. msvcrtd.dll
+ * is the debug c-runtime library for MSVC. If you have debug
+ * binaries you want to have DEBUG_BINARIES defined. If you have
+ * release binaries you want to have RELEASE_BINARIES defined.
+ * If you have both, then define them both.
+ * Of course, you need msvcrt[d].dll present to install it!
+ */
+#ifdef BINARIES_INSTALL
+// # define DEBUG_BINARIES
+// # define RELEASE_BINARIES
+#endif
+
+#include "stdafx.h"
+#include "BINDInstall.h"
+#include "BINDInstallDlg.h"
+#include "DirBrowse.h"
+#include <winsvc.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <named/ntservice.h>
+#include <isc/bind_registry.h>
+#include <isc/ntgroups.h>
+#include <direct.h>
+#include "AccountInfo.h"
+#include "versioninfo.h"
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <config.h>
+
+#undef open
+
+#define MAX_GROUPS 100
+#define MAX_PRIVS 50
+
+#define LOCAL_SERVICE "NT AUTHORITY\\LocalService"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+typedef struct _xexception
+{
+ _xexception(UINT string, ...);
+
+ CString resString;
+} Exception;
+
+_xexception::_xexception(UINT string, ...)
+{
+ CString format;
+ va_list va;
+
+ format.LoadString(string);
+
+ va_start(va, string);
+ resString.FormatV(format, va);
+ va_end(va);
+}
+
+typedef struct _filedata {
+ enum FileDestinations {TargetDir, BinDir, EtcDir, WinSystem};
+ enum FileImportance {Trivial, Normal, Critical};
+
+ char filename[128];
+ int destination;
+ int importance;
+ BOOL checkVer;
+ BOOL withTools;
+} FileData;
+
+#if no_longer_used
+
+const FileData installFiles[] =
+{
+#ifdef BINARIES_INSTALL
+# ifdef DEBUG_BINARIES
+ {"msvcrtd.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+# endif
+# ifdef RELEASE_BINARIES
+ {"msvcrt.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+# endif
+#endif
+#if _MSC_VER < 1400
+#if _MSC_VER >= 1310
+ {"mfc71.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+ {"msvcr71.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+#elif _MSC_VER > 1200 && _MSC_VER < 1310
+ {"mfc70.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+ {"msvcr70.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+#endif
+#endif
+ {"bindevt.dll", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"libbind9.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libisc.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libisccfg.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libisccc.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libdns.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"liblwres.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libirs.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#ifdef OPENSSL
+ {"libeay32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#ifdef HAVE_LIBXML2
+ {"libxml2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#ifdef USE_GSSAPI
+#ifndef _WIN64
+ {"gssapi32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"krb5_32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#else
+ {"gssapi64.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"krb5_64.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#endif
+#ifdef HAVE_GEOIP
+ {"libgeoip.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#ifdef WITH_IDN
+ {"idnkit.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"iconv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+ {"named.exe", FileData::BinDir, FileData::Critical, FALSE, FALSE},
+ {"nsupdate.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"BINDInstall.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"rndc.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dig.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"host.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"mdig.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"nslookup.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"delv.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"arpaname.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"nsec3hash.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"genrandom.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"rndc-confgen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"ddns-confgen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"tsig-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-signzone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-dsfromkey.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-importkey.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-keyfromlabel.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-revoke.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-settime.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-verify.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-checkconf.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-checkzone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-compilezone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-journalprint.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-rrchecker.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"isc-hmac-fixup.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+#ifdef USE_PKCS11
+ {"pkcs11-destroy.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"pkcs11-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"pkcs11-list.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"pkcs11-tokens.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+#endif
+#ifdef USE_PYTHON
+ {"dnssec-checkds.py", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-coverage.py", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+#endif
+ {"readme1st.txt", FileData::BinDir, FileData::Trivial, FALSE, TRUE},
+ {NULL, -1, -1}
+};
+
+#else
+
+typedef std::vector<FileData> FileDatas;
+FileDatas installFiles;
+BOOL forwin64 = FALSE;
+BOOL runvcredist = FALSE;
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallDlg dialog
+
+CBINDInstallDlg::CBINDInstallDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CBINDInstallDlg::IDD, pParent) {
+ char winsys[MAX_PATH];
+
+ //{{AFX_DATA_INIT(CBINDInstallDlg)
+ m_targetDir = _T("");
+ m_version = _T("");
+ m_toolsOnly = FALSE;
+ m_autoStart = FALSE;
+ m_keepFiles = FALSE;
+ m_current = _T("");
+ m_startOnInstall = FALSE;
+ m_accountName = _T("");
+ m_accountPassword = _T("");
+ //}}AFX_DATA_INIT
+ // Note that LoadIcon does not require a subsequent
+ // DestroyIcon in Win32
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+ GetSystemDirectory(winsys, MAX_PATH);
+ m_winSysDir = winsys;
+
+ m_defaultDir = "notyetknown";
+
+ m_installed = FALSE;
+ m_accountExists = FALSE;
+ m_accountUsed = FALSE;
+ m_serviceExists = TRUE;
+ GetCurrentServiceAccountName();
+ m_currentAccount = m_accountName;
+ if (m_accountName == "") {
+ m_accountName = "named";
+ }
+}
+
+void CBINDInstallDlg::DoDataExchange(CDataExchange* pDX) {
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBINDInstallDlg)
+ DDX_Text(pDX, IDC_TARGETDIR, m_targetDir);
+ DDX_Text(pDX, IDC_VERSION, m_version);
+ DDX_Text(pDX, IDC_ACCOUNT_NAME, m_accountName);
+ DDX_Text(pDX, IDC_ACCOUNT_PASSWORD, m_accountPassword);
+ DDX_Text(pDX, IDC_ACCOUNT_PASSWORD_CONFIRM, m_accountPasswordConfirm);
+ DDX_Check(pDX, IDC_TOOLS_ONLY, m_toolsOnly);
+ DDX_Check(pDX, IDC_AUTO_START, m_autoStart);
+ DDX_Check(pDX, IDC_KEEP_FILES, m_keepFiles);
+ DDX_Text(pDX, IDC_CURRENT, m_current);
+ DDX_Check(pDX, IDC_START, m_startOnInstall);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CBINDInstallDlg, CDialog)
+ //{{AFX_MSG_MAP(CBINDInstallDlg)
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
+ ON_BN_CLICKED(IDC_INSTALL, OnInstall)
+ ON_BN_CLICKED(IDC_EXIT, OnExit)
+ ON_BN_CLICKED(IDC_UNINSTALL, OnUninstall)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallDlg message handlers
+
+BOOL CBINDInstallDlg::OnInitDialog() {
+ CDialog::OnInitDialog();
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ char filename[MAX_PATH];
+ char dirname[MAX_PATH];
+ char *fptr = &filename[0];
+ GetModuleFileName(NULL, filename, MAX_PATH);
+ char *dptr = strrchr(filename,'\\');
+ size_t index = dptr - fptr;
+ strncpy(dirname, filename, index);
+ dirname[index] = '\0';
+ CString Dirname(dirname);
+ m_currentDir = Dirname;
+
+ ReadInstallFlags();
+ char progfiles[MAX_PATH];
+ int id_program_files;
+ if (forwin64)
+ id_program_files = CSIDL_PROGRAM_FILES;
+ else
+ id_program_files = CSIDL_PROGRAM_FILESX86;
+ SHGetFolderPath(NULL, CSIDL_FLAG_CREATE|id_program_files,
+ NULL, SHGFP_TYPE_CURRENT, progfiles);
+
+ m_defaultDir = progfiles;
+ m_defaultDir += "\\ISC BIND 9";
+
+ CVersionInfo bindInst(filename);
+ if(bindInst.IsValid())
+ m_version.Format(IDS_VERSION, bindInst.GetFileVersionString());
+ else
+ m_version.LoadString(IDS_NO_VERSION);
+
+ DWORD dwBufLen = MAX_PATH;
+ char buf[MAX_PATH];
+ HKEY hKey;
+
+ m_startOnInstall = CheckBINDService();
+
+ /* See if we are installed already */
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
+ == ERROR_SUCCESS) {
+ m_installed = TRUE;
+ memset(buf, 0, MAX_PATH);
+ // Get the install directory
+ if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL, (LPBYTE)buf,
+ &dwBufLen) == ERROR_SUCCESS)
+ if (strcmp(buf, ""))
+ m_defaultDir = buf;
+
+ RegCloseKey(hKey);
+ }
+ m_targetDir = m_defaultDir;
+
+ // Set checkbox defaults
+ m_autoStart = TRUE;
+ m_keepFiles = TRUE;
+
+ UpdateData(FALSE);
+
+ return (TRUE); /* return(TRUE) unless you set the focus to a control */
+}
+
+/*
+ * If you add a minimize button to your dialog, you will need the code below
+ * to draw the icon. For MFC applications using the document/view model,
+ * this is automatically done for you by the framework.
+ */
+
+void CBINDInstallDlg::OnPaint() {
+ if (IsIconic()) {
+ CPaintDC dc(this); // device context for painting
+
+ SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else {
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this to obtain the cursor to display while the user drags
+// the minimized window.
+HCURSOR CBINDInstallDlg::OnQueryDragIcon() {
+ return((HCURSOR)m_hIcon);
+}
+
+void CBINDInstallDlg::OnBrowse() {
+
+ CDirBrowse browse;
+
+ if (browse.DoModal() == IDOK) {
+ //m_targetDir = browse.m_selectedDir;
+ UpdateData(FALSE);
+ }
+}
+
+/*
+ * User pressed the exit button
+ */
+void CBINDInstallDlg::OnExit() {
+ EndDialog(0);
+}
+
+/*
+ * User pressed the uninstall button. Make it go.
+ */
+void CBINDInstallDlg::OnUninstall() {
+ UpdateData();
+
+ if (MsgBox(IDS_UNINSTALL, MB_YESNO) == IDYES) {
+ if (CheckBINDService())
+ StopBINDService();
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
+ SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ return;
+ }
+
+ SC_HANDLE hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hService && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST){
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ return;
+ }
+
+ SERVICE_STATUS ss;
+ QueryServiceStatus(hService, &ss);
+ if (ss.dwCurrentState == SERVICE_RUNNING) {
+ BOOL rc = ControlService(hService,
+ SERVICE_CONTROL_STOP, &ss);
+ if (rc == FALSE || ss.dwCurrentState != SERVICE_STOPPED) {
+ MsgBox(IDS_ERR_STOP_SERVICE, GetErrMessage());
+ return;
+ }
+
+ }
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+
+ // Directories
+ m_etcDir = m_targetDir + "\\etc";
+ m_binDir = m_targetDir + "\\bin";
+
+ UninstallTags();
+ UnregisterMessages(TRUE);
+ UnregisterService(TRUE);
+ ReadInstallFileList();
+ DeleteFiles(TRUE);
+ if (m_keepFiles == FALSE)
+ RemoveDirs(TRUE);
+ else
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("Not Removed");
+
+
+ // Delete registry keys for named
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SESSION_SUBKEY);
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY);
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY);
+
+ ProgramGroup(FALSE);
+
+ SetCurrent(IDS_UNINSTALL_DONE);
+ MsgBox(IDS_UNINSTALL_DONE);
+ }
+}
+
+/*
+ * User pressed the install button. Make it go.
+ */
+void CBINDInstallDlg::OnInstall() {
+ BOOL success = FALSE;
+ int oldlen;
+ int n;
+
+ if (CheckBINDService())
+ StopBINDService();
+
+ InstallTags();
+
+ UpdateData();
+
+ if (!m_toolsOnly && m_accountName != LOCAL_SERVICE) {
+ /*
+ * Check that the Passwords entered match.
+ */
+ if (m_accountPassword != m_accountPasswordConfirm) {
+ MsgBox(IDS_ERR_PASSWORD);
+ return;
+ }
+
+ /*
+ * Check that there is not leading / trailing whitespace.
+ * This is for compatibility with the standard password dialog.
+ * Passwords really should be treated as opaque blobs.
+ */
+ oldlen = m_accountPassword.GetLength();
+ m_accountPassword.TrimLeft();
+ m_accountPassword.TrimRight();
+ if (m_accountPassword.GetLength() != oldlen) {
+ MsgBox(IDS_ERR_WHITESPACE);
+ return;
+ }
+
+ /*
+ * Check the entered account name.
+ */
+ if (ValidateServiceAccount() == FALSE)
+ return;
+
+ /*
+ * For Registration we need to know if account was changed.
+ */
+ if (m_accountName != m_currentAccount)
+ m_accountUsed = FALSE;
+
+ if (m_accountUsed == FALSE && m_serviceExists == FALSE)
+ {
+ /*
+ * Check that the Password is not null.
+ */
+ if (m_accountPassword.GetLength() == 0) {
+ MsgBox(IDS_ERR_NULLPASSWORD);
+ return;
+ }
+ }
+ } else if (m_accountName == LOCAL_SERVICE) {
+ /* The LocalService always exists. */
+ m_accountExists = TRUE;
+ if (m_accountName != m_currentAccount)
+ m_accountUsed = FALSE;
+ }
+
+ /* Directories */
+ m_etcDir = m_targetDir + "\\etc";
+ m_binDir = m_targetDir + "\\bin";
+
+ if (m_defaultDir != m_targetDir) {
+ if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
+ {
+ int install = MsgBox(IDS_DIREXIST,
+ MB_YESNO | MB_ICONQUESTION, m_targetDir);
+ if (install == IDNO)
+ return;
+ }
+ else {
+ int createDir = MsgBox(IDS_CREATEDIR,
+ MB_YESNO | MB_ICONQUESTION, m_targetDir);
+ if (createDir == IDNO)
+ return;
+ }
+ }
+
+ if (!m_toolsOnly) {
+ if (m_accountExists == FALSE) {
+ success = CreateServiceAccount(m_accountName.GetBuffer(30),
+ m_accountPassword.GetBuffer(30));
+ if (success == FALSE) {
+ MsgBox(IDS_CREATEACCOUNT_FAILED);
+ return;
+ }
+ m_accountExists = TRUE;
+ }
+ }
+
+ ProgramGroup(FALSE);
+
+ /*
+ * Install Visual Studio libraries. As per:
+ * http://blogs.msdn.com/astebner/archive/2006/08/23/715755.aspx
+ *
+ * Vcredist_x86.exe /q:a /c:"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log"
+ */
+ /*system(".\\Vcredist_x86.exe /q:a /c:\"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log\"");*/
+
+ /*
+ * Enclose full path to Vcredist_x86.exe in quotes as
+ * m_currentDir may contain spaces.
+ */
+ if (runvcredist) {
+ char Vcredist_x86[MAX_PATH];
+ if (forwin64)
+ n = snprintf(Vcredist_x86, sizeof(Vcredist_x86),
+ "\"%s\\Vcredist_x64.exe\"",
+ (LPCTSTR) m_currentDir);
+ else
+ n = snprintf(Vcredist_x86, sizeof(Vcredist_x86),
+ "\"%s\\Vcredist_x86.exe\"",
+ (LPCTSTR) m_currentDir);
+ if (n >= 0 && (size_t)n < sizeof(Vcredist_x86))
+ system(Vcredist_x86);
+ }
+ try {
+ CreateDirs();
+ ReadInstallFileList();
+ CopyFiles();
+ if (!m_toolsOnly)
+ RegisterService();
+ RegisterMessages();
+
+ HKEY hKey;
+
+ /* Create a new key for named */
+ SetCurrent(IDS_CREATE_KEY);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY,
+ &hKey) == ERROR_SUCCESS) {
+ // Get the install directory
+ RegSetValueEx(hKey, "InstallDir", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)m_targetDir,
+ m_targetDir.GetLength());
+ RegCloseKey(hKey);
+ }
+
+
+ SetCurrent(IDS_ADD_REMOVE);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY,
+ &hKey) == ERROR_SUCCESS) {
+ CString buf(BIND_DISPLAY_NAME);
+
+ RegSetValueEx(hKey, "DisplayName", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)buf, buf.GetLength());
+
+ buf.Format("%s\\BINDInstall.exe", m_binDir);
+
+ CStringA installLocA(buf);
+ const char *str = (const char *) installLocA;
+ char pathBuffer[2 * MAX_PATH];
+ strncpy(pathBuffer, str, sizeof(pathBuffer) - 1);
+ pathBuffer[sizeof(pathBuffer) - 1] = 0;
+ PathQuoteSpaces(pathBuffer);
+
+ RegSetValueEx(hKey, "UninstallString", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)pathBuffer, strlen(pathBuffer));
+ RegCloseKey(hKey);
+ }
+
+ ProgramGroup(FALSE);
+
+ if (m_startOnInstall)
+ StartBINDService();
+ }
+ catch(Exception e) {
+ MessageBox(e.resString);
+ SetCurrent(IDS_CLEANUP);
+ FailedInstall();
+ MsgBox(IDS_FAIL);
+ return;
+ }
+ catch(DWORD dw) {
+ CString msg;
+ msg.Format("A fatal error occured\n(%s)", GetErrMessage(dw));
+ MessageBox(msg);
+ SetCurrent(IDS_CLEANUP);
+ FailedInstall();
+ MsgBox(IDS_FAIL);
+ return;
+ }
+
+ SetCurrent(IDS_INSTALL_DONE);
+ MsgBox(IDS_SUCCESS);
+}
+
+/*
+ * Methods to do the work
+ */
+void CBINDInstallDlg::CreateDirs() {
+ /* s'OK if the directories already exist */
+ SetCurrent(IDS_CREATE_DIR, m_targetDir);
+ if (!CreateDirectory(m_targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_targetDir, GetErrMessage()));
+
+ SetCurrent(IDS_CREATE_DIR, m_etcDir);
+ if (!CreateDirectory(m_etcDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_etcDir, GetErrMessage()));
+
+ SetCurrent(IDS_CREATE_DIR, m_binDir);
+ if (!CreateDirectory(m_binDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_binDir, GetErrMessage()));
+
+ SetItemStatus(IDC_CREATE_DIR);
+}
+
+void CBINDInstallDlg::RemoveDirs(BOOL uninstall) {
+ if (!m_keepFiles) {
+ SetCurrent(IDS_REMOVE_DIR, m_binDir);
+ // Check for existence then remove if present
+ if (GetFileAttributes(m_binDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_binDir);
+
+ SetCurrent(IDS_REMOVE_DIR, m_etcDir);
+ if (GetFileAttributes(m_etcDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_etcDir);
+
+ SetCurrent(IDS_REMOVE_DIR, m_targetDir);
+ if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_targetDir);
+ }
+
+ if (uninstall)
+ SetItemStatus(IDC_CREATE_DIR, TRUE);
+}
+
+// InstallFlags: runvcredist and forwin64 options
+void CBINDInstallDlg::ReadInstallFlags() {
+ std::ifstream ff(m_currentDir + "\\InstallFlags");
+ if (!ff) {
+ throw(Exception(IDS_FILE_BAD, "InstallFlags", "can't open"));
+ }
+ while (!ff.eof()) {
+ std::string line;
+ getline(ff, line);
+ if (line.compare("runvcredist") == 0)
+ runvcredist = TRUE;
+ else if (line.compare("forwin64") == 0)
+ forwin64 = TRUE;
+ }
+}
+
+// InstallFiles: {filename-divt}*
+// destination: TBEW
+// importance: TNC
+// checkVer and withTools: TF (boolean)
+void CBINDInstallDlg::ReadInstallFileList() {
+ std::ifstream fl(m_currentDir + "\\InstallFiles");
+ if (!fl) {
+ throw(Exception(IDS_FILE_BAD, "InstallFiles", "can't open"));
+ }
+ while (!fl.eof()) {
+ std::string line;
+ getline(fl, line);
+ if (line.empty())
+ continue;
+ if (line[0] == '#')
+ continue;
+ // zip -l adds spurious \r: remove trailing space chars
+ size_t finish = line.find_last_not_of(" \t\r\n\t\v");
+ if ((finish != std::string::npos) &&
+ (finish + 1 != line.size())) {
+ line.erase(finish + 1);
+ }
+ size_t flags = line.find_last_of('-');
+ if ((flags == std::string::npos) ||
+ (flags + 5 != line.size()))
+ goto bad;
+ std::string file = line.substr(0, flags);
+ if (file.empty() || (file.size() > 127))
+ goto bad;
+ FileData entry;
+ memmove(entry.filename, file.c_str(), file.size() + 1);
+ switch (line[flags + 1]) {
+ case 'T':
+ entry.destination = FileData::TargetDir;
+ break;
+ case 'B':
+ entry.destination = FileData::BinDir;
+ break;
+ case 'E':
+ entry.destination = FileData::EtcDir;
+ break;
+ case 'W':
+ entry.destination = FileData::WinSystem;
+ break;
+ default:
+ goto bad;
+ }
+ switch (line[flags + 2]) {
+ case 'T':
+ entry.importance = FileData::Trivial;
+ break;
+ case 'N':
+ entry.importance = FileData::Normal;
+ break;
+ case 'C':
+ entry.importance = FileData::Critical;
+ break;
+ default:
+ goto bad;
+ }
+ switch (line[flags + 3]) {
+ case 'T':
+ entry.checkVer = TRUE;
+ break;
+ case 'F':
+ entry.checkVer = FALSE;
+ break;
+ default:
+ goto bad;
+ }
+ switch (line[flags + 4]) {
+ case 'T':
+ entry.withTools = TRUE;
+ break;
+ case 'F':
+ entry.withTools = FALSE;
+ break;
+ default:
+ goto bad;
+ }
+ installFiles.push_back(entry);
+ }
+ return;
+
+bad:
+ throw(Exception(IDS_FILE_BAD, "InstallFiles", "syntax error"));
+}
+
+void CBINDInstallDlg::CopyFiles() {
+ CString destFile;
+
+ for (FileDatas::iterator fd = installFiles.begin();
+ fd != installFiles.end(); ++fd) {
+ if (m_toolsOnly && !fd->withTools)
+ continue;
+ SetCurrent(IDS_COPY_FILE, fd->filename);
+
+ destFile = DestDir(fd->destination) + "\\" + fd->filename;
+ CString filespec = m_currentDir + "\\" + fd->filename;
+ CVersionInfo bindFile(destFile);
+
+ CVersionInfo origFile(filespec);
+ if (!origFile.IsValid() && fd->checkVer) {
+ if (MsgBox(IDS_FILE_BAD, MB_YESNO,
+ fd->filename) == IDNO)
+ throw(Exception(IDS_ERR_COPY_FILE,
+ fd->filename,
+ GetErrMessage()));
+ }
+
+ try {
+/*
+ * Ignore Version checking. We need to make sure that all files get
+ * copied regardless of whether or not they are earlier or later
+ * versions since we cannot guarantee that we have either backward or
+ * forward compatibility between versions.
+ */
+ bindFile.CopyFileNoVersion(origFile);
+ }
+ catch(...) {
+ if (fd->importance != FileData::Trivial) {
+ if (fd->importance == FileData::Critical ||
+ MsgBox(IDS_ERR_NONCRIT_FILE, MB_YESNO,
+ fd->filename,
+ GetErrMessage()) == IDNO)
+ {
+ SetItemStatus(IDC_COPY_FILE, FALSE);
+ throw(Exception(IDS_ERR_COPY_FILE,
+ fd->filename,
+ GetErrMessage()));
+ }
+ }
+ }
+ }
+
+ SetItemStatus(IDC_COPY_FILE);
+}
+
+void CBINDInstallDlg::DeleteFiles(BOOL uninstall) {
+ CString destFile;
+
+ for (FileDatas::iterator fd = installFiles.begin();
+ fd != installFiles.end(); ++fd) {
+ if (fd->checkVer)
+ continue;
+
+ destFile = DestDir(fd->destination) + "\\" + fd->filename;
+
+ if (uninstall)
+ SetCurrent(IDS_DELETE_FILE, fd->filename);
+
+ DeleteFile(destFile);
+ }
+
+ if (!m_keepFiles) {
+ WIN32_FIND_DATA findData;
+ CString file = m_etcDir + "\\*.*";
+ BOOL rc;
+ HANDLE hFile;
+
+ hFile = FindFirstFile(file, &findData);
+ rc = hFile != INVALID_HANDLE_VALUE;
+
+ while (rc == TRUE) {
+ if (strcmp(findData.cFileName, ".") &&
+ strcmp(findData.cFileName, "..")) {
+ file = m_etcDir + "\\" + findData.cFileName;
+ SetCurrent(IDS_DELETE_FILE, file);
+ DeleteFile(file);
+ }
+ rc = FindNextFile(hFile, &findData);
+ }
+ FindClose(hFile);
+ }
+
+ if (uninstall)
+ SetItemStatus(IDC_COPY_FILE, TRUE);
+}
+
+/*
+ * Get the service account name out of the registry, if any
+ */
+void
+CBINDInstallDlg::GetCurrentServiceAccountName() {
+ HKEY hKey;
+ BOOL keyFound = FALSE;
+ char accountName[MAX_PATH];
+ DWORD nameLen = MAX_PATH;
+ CString Tmp;
+ m_accountUsed = FALSE;
+
+ memset(accountName, 0, nameLen);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SERVICE_SUBKEY, 0, KEY_READ,
+ &hKey) == ERROR_SUCCESS) {
+ keyFound = TRUE;
+ }
+ else {
+ m_serviceExists = FALSE;
+ }
+
+ if (keyFound == TRUE) {
+ /* Get the named service account, if one was specified */
+ if (RegQueryValueEx(hKey, "ObjectName", NULL, NULL,
+ (LPBYTE)accountName, &nameLen) != ERROR_SUCCESS)
+ keyFound = FALSE;
+ }
+
+ RegCloseKey(hKey);
+ if (keyFound == FALSE)
+ m_accountName = "";
+ else if (!strcmp(accountName, LOCAL_SERVICE)) {
+ m_accountName = LOCAL_SERVICE;
+ m_accountUsed = TRUE;
+ } else {
+ /*
+ * LocalSystem is not a regular account and is equivalent
+ * to no account but with lots of privileges
+ */
+ Tmp = accountName;
+ if (Tmp == ".\\LocalSystem")
+ m_accountName = "";
+ /* Found account strip any ".\" from it */
+ if (Tmp.Left(2) == ".\\") {
+ m_accountName = Tmp.Mid(2);
+ m_accountUsed = TRUE;
+ }
+ }
+}
+
+BOOL
+CBINDInstallDlg::ValidateServiceAccount() {
+ wchar_t *PrivList[MAX_PRIVS];
+ unsigned int PrivCount = 0;
+ char *Groups[MAX_GROUPS];
+ unsigned int totalGroups = 0;
+ int status;
+ char *name;
+
+ name = m_accountName.GetBuffer(30);
+
+ status = GetAccountPrivileges(name, PrivList, &PrivCount,
+ Groups, &totalGroups, MAX_GROUPS);
+ if (status == RTN_NOACCOUNT) {
+ m_accountExists = FALSE;
+ /* We need to do this in case an account was previously used */
+ m_accountUsed = FALSE;
+ return (TRUE);
+ }
+ if (status != RTN_OK) {
+ MsgBox(IDS_ERR_BADACCOUNT);
+ return (FALSE);
+ }
+
+ m_accountExists = TRUE;
+ if (PrivCount > 1) {
+ if (MsgBox(IDS_ERR_TOOPRIVED, MB_YESNO) == IDYES)
+ return (FALSE);
+ else
+ return (TRUE);
+ }
+
+ /* See if we have the correct privilege */
+ if (wcscmp(PrivList[0], SE_SERVICE_LOGON_PRIV) != 0) {
+ MsgBox(IDS_ERR_WRONGPRIV, PrivList[0]);
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+void
+CBINDInstallDlg::RegisterService() {
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+ CString StartName;
+
+ if (m_accountName == LOCAL_SERVICE)
+ StartName = LOCAL_SERVICE;
+ else
+ StartName = ".\\" + m_accountName;
+ /*
+ * We need to change the service rather than create it
+ * if the service already exists. Do nothing if we are already
+ * using that account
+ */
+ if (m_serviceExists == TRUE) {
+ if (m_accountUsed == FALSE) {
+ UpdateService(StartName);
+ SetItemStatus(IDC_REG_SERVICE);
+ return;
+ } else {
+ SetItemStatus(IDC_REG_SERVICE);
+ return;
+ }
+ }
+
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager)
+ throw(Exception(IDS_ERR_OPEN_SCM, GetErrMessage()));
+
+ DWORD dwStart = SERVICE_DEMAND_START;
+ if (m_autoStart)
+ dwStart = SERVICE_AUTO_START;
+
+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+ CString namedLoc;
+ namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
+
+ CStringA namedLocA(namedLoc);
+ const char *str = (const char *) namedLocA;
+ char pathBuffer[2 * MAX_PATH];
+ strncpy(pathBuffer, str, sizeof(pathBuffer) - 1);
+ pathBuffer[sizeof(pathBuffer) - 1] = 0;
+ PathQuoteSpaces(pathBuffer);
+
+ SetCurrent(IDS_CREATE_SERVICE);
+ hService = CreateService(hSCManager, BIND_SERVICE_NAME,
+ BIND_DISPLAY_NAME, SERVICE_ALL_ACCESS, dwServiceType, dwStart,
+ SERVICE_ERROR_NORMAL, pathBuffer, NULL, NULL, NULL, StartName,
+ m_accountPassword);
+
+ if (!hService && GetLastError() != ERROR_SERVICE_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_SERVICE, GetErrMessage()));
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ SetItemStatus(IDC_REG_SERVICE);
+}
+
+void
+CBINDInstallDlg::UpdateService(CString StartName) {
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+
+ if(m_toolsOnly)
+ return;
+
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ return;
+ }
+
+ DWORD dwStart = SERVICE_DEMAND_START;
+ if (m_autoStart)
+ dwStart = SERVICE_AUTO_START;
+
+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+ CString namedLoc;
+ namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
+
+ CStringA namedLocA(namedLoc);
+ const char *str = (const char *) namedLocA;
+ char pathBuffer[2 * MAX_PATH];
+ strncpy(pathBuffer, str, sizeof(pathBuffer) - 1);
+ pathBuffer[sizeof(pathBuffer) - 1] = 0;
+ PathQuoteSpaces(pathBuffer);
+
+ SetCurrent(IDS_OPEN_SERVICE);
+ hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_CHANGE_CONFIG);
+ if (!hService)
+ {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+ return;
+ } else {
+ if (ChangeServiceConfig(hService, dwServiceType, dwStart,
+ SERVICE_ERROR_NORMAL, pathBuffer, NULL, NULL, NULL,
+ StartName, m_accountPassword, BIND_DISPLAY_NAME)
+ != TRUE) {
+ DWORD err = GetLastError();
+ MsgBox(IDS_ERR_UPDATE_SERVICE, GetErrMessage());
+ }
+ }
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ SetItemStatus(IDC_REG_SERVICE);
+}
+
+void CBINDInstallDlg::UnregisterService(BOOL uninstall) {
+ BOOL rc = FALSE;
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+
+ while(1) {
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager && uninstall == TRUE) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ break;
+ }
+
+ SetCurrent(IDS_OPEN_SERVICE);
+ hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ STANDARD_RIGHTS_REQUIRED);
+ if (!hService && uninstall == TRUE)
+ {
+ if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ break;
+ }
+ }
+ else {
+ SetCurrent(IDS_REMOVE_SERVICE);
+ if (!DeleteService(hService) && uninstall == TRUE) {
+ DWORD err = GetLastError();
+ if (err != ERROR_SERVICE_MARKED_FOR_DELETE &&
+ err != ERROR_SERVICE_DOES_NOT_EXIST) {
+ MsgBox(IDS_ERR_REMOVE_SERVICE,
+ GetErrMessage());
+ break;
+ }
+ }
+ }
+
+ rc = TRUE;
+ break;
+ }
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ if (uninstall)
+ SetItemStatus(IDC_REG_SERVICE, rc);
+}
+
+void CBINDInstallDlg::RegisterMessages() {
+ HKEY hKey;
+ DWORD dwData;
+ char pszMsgDLL[MAX_PATH];
+ int n;
+
+ n = snprintf(pszMsgDLL, sizeof(pszMsgDLL), "%s\\%s",
+ (LPCTSTR)m_binDir, "bindevt.dll");
+ if (n < 0 || (size_t)n >= sizeof(pszMsgDLL))
+ throw(Exception(IDS_ERR_CREATE_KEY,
+ "<m_binDir>\\bindevt.dll too long"));
+
+ SetCurrent(IDS_REGISTER_MESSAGES);
+ /* Create a new key for named */
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_MESSAGE_SUBKEY, &hKey)
+ != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_CREATE_KEY, GetErrMessage()));
+
+ /* Add the Event-ID message-file name to the subkey. */
+ if (RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ,
+ (LPBYTE)pszMsgDLL, (DWORD)(strlen(pszMsgDLL) + 1)) != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
+
+ /* Set the supported types flags and addit to the subkey. */
+ dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+ if (RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD,
+ (LPBYTE)&dwData, sizeof(DWORD)) != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
+
+ RegCloseKey(hKey);
+
+ SetItemStatus(IDC_REG_MESSAGE);
+}
+
+void CBINDInstallDlg::UnregisterMessages(BOOL uninstall) {
+ BOOL rc = FALSE;
+ HKEY hKey = NULL;
+
+ while(1) {
+ SetCurrent(IDS_UNREGISTER_MESSAGES);
+ /* Open key for Application Event Log */
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, EVENTLOG_APP_SUBKEY, &hKey)
+ != ERROR_SUCCESS)
+ break;
+
+ /* Remove named from the list of messages sources */
+ if (RegDeleteKey(hKey, BIND_MESSAGE_NAME) != ERROR_SUCCESS)
+ break;
+
+ rc = TRUE;
+ break;
+ }
+
+ if (hKey)
+ RegCloseKey(hKey);
+
+ if (uninstall)
+ SetItemStatus(IDC_REG_MESSAGE, rc);
+}
+
+/*
+ * Install failed - clean up quietly
+ */
+void CBINDInstallDlg::FailedInstall() {
+ UnregisterMessages(FALSE);
+ UnregisterService(FALSE);
+ DeleteFiles(FALSE);
+ RemoveDirs(FALSE);
+}
+
+/*
+ * Set the checklist tags for install
+ */
+void CBINDInstallDlg::InstallTags() {
+ CString tag;
+
+ tag.LoadString(IDS_INSTALL_FILE);
+ GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
+
+ tag.LoadString(IDS_INSTALL_DIR);
+ GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
+ GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
+
+ tag.LoadString(IDS_INSTALL_SERVICE);
+ GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
+
+ tag.LoadString(IDS_INSTALL_MESSAGE);
+ GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
+}
+
+/*
+ * Set the checklist tags for uninstall
+ */
+void CBINDInstallDlg::UninstallTags() {
+ CString tag;
+
+ tag.LoadString(IDS_UNINSTALL_FILES);
+ GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_DIR);
+ GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_SERVICE);
+ GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_MESSAGE);
+ GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
+}
+
+void CBINDInstallDlg::SetItemStatus(UINT nID, BOOL bSuccess) {
+ GetDlgItem(nID)->SetWindowText(bSuccess == TRUE ? "Done" : "Failed");
+}
+
+
+/*
+ * Set the text in the current operation field - use a string table string
+ */
+void CBINDInstallDlg::SetCurrent(int id, ...) {
+ CString format;
+ va_list va;
+ char buf[128];
+
+ format.LoadString(id);
+ memset(buf, 0, 128);
+
+ va_start(va, id);
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(va);
+
+ m_current.Format("%s", buf);
+ UpdateData(FALSE);
+}
+
+/*
+ * Stop the BIND service
+ */
+void CBINDInstallDlg::StopBINDService() {
+ SERVICE_STATUS svcStatus;
+
+ SetCurrent(IDS_STOP_SERVICE);
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ }
+
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hBINDSvc) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ }
+
+ BOOL rc = ControlService(hBINDSvc, SERVICE_CONTROL_STOP, &svcStatus);
+}
+
+/*
+ * Start the BIND service
+ */
+void CBINDInstallDlg::StartBINDService() {
+ SetCurrent(IDS_START_SERVICE);
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ }
+
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hBINDSvc) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ }
+ BOOL rc = StartService(hBINDSvc, 0, NULL);
+}
+
+/*
+ * Check to see if the BIND service is running or not
+ */
+BOOL CBINDInstallDlg::CheckBINDService() {
+ SERVICE_STATUS svcStatus;
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSCManager) {
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (hBINDSvc) {
+ BOOL rc = ControlService(hBINDSvc,
+ SERVICE_CONTROL_INTERROGATE, &svcStatus);
+ if (!rc)
+ DWORD err = GetLastError();
+
+ return (svcStatus.dwCurrentState == SERVICE_RUNNING);
+ }
+ }
+ return (FALSE);
+}
+
+/*
+ * Display message boxes with variable args, using string table strings
+ * for the format specifiers
+ */
+int CBINDInstallDlg::MsgBox(int id, ...) {
+ CString format;
+ va_list va;
+ char buf[BUFSIZ];
+
+ format.LoadString(id);
+ memset(buf, 0, BUFSIZ);
+
+ va_start(va, id);
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(va);
+
+ return (MessageBox(buf));
+}
+
+int CBINDInstallDlg::MsgBox(int id, UINT type, ...) {
+ CString format;
+ va_list va;
+ char buf[BUFSIZ];
+
+ format.LoadString(id);
+ memset(buf, 0, BUFSIZ);
+
+ va_start(va, type);
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(va);
+
+ return(MessageBox(buf, NULL, type));
+}
+
+/*
+ * Call GetLastError(), retrieve the message associated with the error
+ */
+CString CBINDInstallDlg::GetErrMessage(DWORD err) {
+ LPVOID msgBuf;
+ static char buf[BUFSIZ];
+
+ DWORD len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err == -1 ? GetLastError() : err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgBuf, 0, NULL );
+
+
+ strcpy(buf, (LPTSTR)msgBuf);
+ LocalFree(msgBuf);
+ /* Strip off the period and the \n */
+ buf[len - 3] = 0;
+ return(buf);
+}
+
+void CBINDInstallDlg::ProgramGroupCreate(TCHAR *commonPath) {
+ HRESULT hres;
+ IShellLink *psl = NULL;
+ ITEMIDLIST *itemList = NULL;
+ TCHAR fileloc[MAX_PATH];
+ TCHAR linkpath[MAX_PATH];
+ TCHAR path[MAX_PATH];
+ int n;
+
+ n = snprintf(path, sizeof(path), "%s\\ISC", commonPath);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ return;
+ CreateDirectory(path, NULL);
+
+ n = snprintf(path, sizeof(path), "%s\\ISC\\BIND", commonPath);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ return;
+ CreateDirectory(path, NULL);
+
+ hres = CoInitialize(NULL);
+ if (!SUCCEEDED(hres))
+ return;
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLink, (LPVOID *)&psl);
+ if (!SUCCEEDED(hres)) {
+ goto cleanup;
+ }
+
+ IPersistFile* ppf;
+ n = snprintf(linkpath, sizeof(linkpath), "%s\\BINDCtrl.lnk", path);
+ if (n < 0 || (size_t)n >= sizeof(path)) {
+ goto cleanup;
+ }
+
+ n = snprintf(fileloc, sizeof(fileloc), "%s\\BINDCtrl.exe",
+ (LPCTSTR) m_binDir);
+ if (n < 0 || (size_t)n >= sizeof(path)) {
+ goto cleanup;
+ }
+
+ psl->SetPath(fileloc);
+ psl->SetDescription("BIND Control Panel");
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ WCHAR wsz[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
+ hres = ppf->Save(wsz, TRUE);
+ ppf->Release();
+ }
+
+ if (GetFileAttributes("readme.txt") == -1) {
+ goto cleanup;
+ }
+
+ n = snprintf(fileloc, sizeof(fileloc), "%s\\Readme.txt",
+ (LPCTSTR) m_targetDir);
+ if (n < 0 || (size_t)n >= sizeof(fileloc)) {
+ goto cleanup;
+ }
+
+ n = snprintf(linkpath, sizeof(linkpath), "%s\\Readme.lnk", path);
+ if (n < 0 || (size_t)n >= sizeof(linkpath)) {
+ goto cleanup;
+ }
+
+ psl->SetPath(fileloc);
+ psl->SetDescription("BIND Readme");
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ WCHAR wsz[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
+ hres = ppf->Save(wsz, TRUE);
+ ppf->Release();
+ }
+
+ cleanup:
+ if (psl)
+ psl->Release();
+ CoUninitialize();
+}
+
+void CBINDInstallDlg::ProgramGroupRemove(TCHAR *commonPath) {
+ HANDLE hFind;
+ TCHAR filename[MAX_PATH];
+ TCHAR path[MAX_PATH];
+ WIN32_FIND_DATA fd;
+ int n;
+
+ n = snprintf(path, sizeof(path), "%s\\ISC\\BIND", commonPath);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ goto remove_isc;
+
+ n = snprintf(filename, sizeof(filename), "%s\\*.*", path);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ goto remove_isc_bind;
+
+ hFind = FindFirstFile(filename, &fd);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ if (strcmp(fd.cFileName, ".") == 0 ||
+ strcmp(fd.cFileName, "..") == 0)
+ continue;
+ n = snprintf(filename, sizeof(filename), "%s\\%s",
+ path, fd.cFileName);
+ if (n >= 0 && (size_t)n < sizeof(filename)) {
+ DeleteFile(filename);
+ }
+ } while (FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+
+ remove_isc_bind:
+ RemoveDirectory(path);
+
+ remove_isc:
+ n = snprintf(path, sizeof(path), "%s\\ISC", commonPath);
+ if (n >= 0 && (size_t)n < sizeof(path))
+ RemoveDirectory(path);
+}
+
+void CBINDInstallDlg::ProgramGroup(BOOL create) {
+ HRESULT hr;
+ ITEMIDLIST *itemList = NULL;
+ LPMALLOC pMalloc = NULL;
+ TCHAR commonPath[MAX_PATH];
+
+ hr = SHGetMalloc(&pMalloc);
+ if (hr != NOERROR) {
+ MessageBox("Could not get a handle to Shell memory object");
+ return;
+ }
+
+ hr = SHGetSpecialFolderLocation(m_hWnd, CSIDL_COMMON_PROGRAMS,
+ &itemList);
+ if (hr != NOERROR) {
+ MessageBox("Could not get a handle to the Common Programs "
+ "folder");
+ if (itemList) {
+ pMalloc->Free(itemList);
+ }
+ return;
+ }
+
+ hr = SHGetPathFromIDList(itemList, commonPath);
+ pMalloc->Free(itemList);
+
+ if (create) {
+ ProgramGroupCreate(commonPath);
+ } else {
+ ProgramGroupRemove(commonPath);
+ }
+}
+
+CString CBINDInstallDlg::DestDir(int destination) {
+ switch(destination) {
+ case FileData::TargetDir:
+ return m_targetDir;
+ case FileData::BinDir:
+ return m_binDir;
+ case FileData::EtcDir:
+ return m_etcDir;
+ case FileData::WinSystem:
+ return m_winSysDir;
+ }
+ return("");
+}
diff --git a/bin/win32/BINDInstall/BINDInstallDlg.h b/bin/win32/BINDInstall/BINDInstallDlg.h
new file mode 100644
index 0000000..cdc3a43
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstallDlg.h
@@ -0,0 +1,126 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * 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 NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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.
+ */
+
+#ifndef BINDINSTALLDLG_H
+#define BINDINSTALLDLG_H
+
+class CBINDInstallDlg : public CDialog
+{
+public:
+ CBINDInstallDlg(CWnd* pParent = NULL); // standard constructor
+
+ //{{AFX_DATA(CBINDInstallDlg)
+ enum { IDD = IDD_BINDINSTALL_DIALOG };
+ CString m_targetDir;
+ CString m_version;
+ BOOL m_autoStart;
+ BOOL m_keepFiles;
+ BOOL m_toolsOnly;
+ CString m_current;
+ BOOL m_startOnInstall;
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBINDInstallDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+protected:
+ void StartBINDService();
+ void StopBINDService();
+
+ void InstallTags();
+ void UninstallTags();
+
+ void CreateDirs();
+ void RemoveDirs(BOOL uninstall);
+
+ void ReadInstallFlags();
+ void ReadInstallFileList();
+
+ void CopyFiles();
+ void DeleteFiles(BOOL uninstall);
+
+ void RegisterService();
+ void UpdateService(CString StartName);
+ void UnregisterService(BOOL uninstall);
+
+ void RegisterMessages();
+ void UnregisterMessages(BOOL uninstall);
+
+ void FailedInstall();
+ void SetItemStatus(UINT nID, BOOL bSuccess = TRUE);
+
+ void GetCurrentServiceAccountName();
+ BOOL ValidateServiceAccount();
+protected:
+ CString DestDir(int destination);
+ int MsgBox(int id, ...);
+ int MsgBox(int id, UINT type, ...);
+ CString GetErrMessage(DWORD err = -1);
+ BOOL CheckBINDService();
+ void SetCurrent(int id, ...);
+ void ProgramGroup(BOOL create = TRUE);
+ void ProgramGroupCreate(TCHAR *commonPath);
+ void ProgramGroupRemove(TCHAR *commonPath);
+
+ HICON m_hIcon;
+ CString m_defaultDir;
+ CString m_etcDir;
+ CString m_binDir;
+ CString m_winSysDir;
+ BOOL m_installed;
+ CString m_currentDir;
+ BOOL m_accountExists;
+ BOOL m_accountUsed;
+ CString m_currentAccount;
+ CString m_accountName;
+ CString m_accountPasswordConfirm;
+ CString m_accountPassword;
+ BOOL m_serviceExists;
+
+ // Generated message map functions
+ //{{AFX_MSG(CBINDInstallDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ afx_msg void OnBrowse();
+ afx_msg void OnChangeTargetdir();
+ afx_msg void OnInstall();
+ afx_msg void OnExit();
+ afx_msg void OnUninstall();
+ afx_msg void OnAutoStart();
+ afx_msg void OnKeepFiles();
+ afx_msg void OnStartOnInstall();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif
diff --git a/bin/win32/BINDInstall/DirBrowse.cpp b/bin/win32/BINDInstall/DirBrowse.cpp
new file mode 100644
index 0000000..758dc60
--- /dev/null
+++ b/bin/win32/BINDInstall/DirBrowse.cpp
@@ -0,0 +1,95 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * 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 NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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 "stdafx.h"
+#include "BINDInstall.h"
+#include "DirBrowse.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirBrowse dialog
+
+
+CDirBrowse::CDirBrowse(CString initialDir, CWnd* pParent /*=NULL*/)
+ : CDialog(CDirBrowse::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDirBrowse)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ m_selectedDir = initialDir;
+}
+
+
+void CDirBrowse::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDirBrowse)
+ // NOTE: the ClassWizard will add DDX and DDV calls here
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDirBrowse, CDialog)
+ //{{AFX_MSG_MAP(CDirBrowse)
+ ON_LBN_DBLCLK(IDC_DIRLIST, OnDblclkDirlist)
+ ON_LBN_SELCHANGE(IDC_DIRLIST, OnSelchangeDirlist)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirBrowse message handlers
+
+BOOL CDirBrowse::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ DlgDirList((LPTSTR)(LPCTSTR)m_selectedDir, IDC_DIRLIST, IDC_CURDIR, DDL_DIRECTORY);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CDirBrowse::OnDblclkDirlist()
+{
+ CListBox *lb = (CListBox *)GetDlgItem(IDC_DIRLIST);
+ CString curSel;
+
+ lb->GetText(lb->GetCurSel(), curSel);
+ DlgDirList((LPTSTR)(LPCTSTR)curSel, IDC_DIRLIST, IDC_CURDIR, DDL_DIRECTORY);
+}
+
+void CDirBrowse::OnSelchangeDirlist()
+{
+ // TODO: Add your control notification handler code here
+
+}
diff --git a/bin/win32/BINDInstall/DirBrowse.h b/bin/win32/BINDInstall/DirBrowse.h
new file mode 100644
index 0000000..080cacf
--- /dev/null
+++ b/bin/win32/BINDInstall/DirBrowse.h
@@ -0,0 +1,64 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * 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 NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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.
+ */
+
+#ifndef DIRBROWSE_H
+#define DIRBROWSE_H
+
+class CDirBrowse : public CDialog
+{
+// Construction
+public:
+ CDirBrowse(CString initialDir = "\\", CWnd* pParent = NULL); // standard constructor
+ CString GetSelectedDir() {return(m_selectedDir);}
+
+ //{{AFX_DATA(CDirBrowse)
+ enum { IDD = IDD_BROWSE };
+ // NOTE: the ClassWizard will add data members here
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDirBrowse)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CDirBrowse)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDblclkDirlist();
+ afx_msg void OnSelchangeDirlist();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+ CString m_selectedDir;
+};
+
+#endif
diff --git a/bin/win32/BINDInstall/StdAfx.cpp b/bin/win32/BINDInstall/StdAfx.cpp
new file mode 100644
index 0000000..a4195ca
--- /dev/null
+++ b/bin/win32/BINDInstall/StdAfx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// BINDInstall.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
diff --git a/bin/win32/BINDInstall/StdAfx.h b/bin/win32/BINDInstall/StdAfx.h
new file mode 100644
index 0000000..099ecb2
--- /dev/null
+++ b/bin/win32/BINDInstall/StdAfx.h
@@ -0,0 +1,36 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+/*
+ * Minimum version is Windows XP SP1
+ */
+#define _WIN32_WINNT 0x0501
+#define NTDDI_VERSION 0x05010100
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#if !defined(AFX_STDAFX_H__61537819_39FC_11D3_A97A_00105A12BD65__INCLUDED_)
+#define AFX_STDAFX_H__61537819_39FC_11D3_A97A_00105A12BD65__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__61537819_39FC_11D3_A97A_00105A12BD65__INCLUDED_)
diff --git a/bin/win32/BINDInstall/VersionInfo.cpp b/bin/win32/BINDInstall/VersionInfo.cpp
new file mode 100644
index 0000000..e83348f
--- /dev/null
+++ b/bin/win32/BINDInstall/VersionInfo.cpp
@@ -0,0 +1,293 @@
+// VersionInfo.cpp: implementation of the CVersionInfo class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "bindinstall.h"
+#include "VersionInfo.h"
+#include <winver.h>
+
+#include <config.h>
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CVersionInfo::CVersionInfo(CString filename)
+{
+ HANDLE hFile;
+ WIN32_FIND_DATA fd;
+ memset(&fd, 0, sizeof(WIN32_FIND_DATA));
+
+ m_status = ERROR_SUCCESS;
+ m_isValid = FALSE;
+ m_filename = filename;
+
+ // See if the given file exists
+ hFile = FindFirstFile(filename, &fd);
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ m_status = ERROR_FILE_NOT_FOUND;
+ m_versionInfo = NULL;
+ return;
+ }
+ FindClose(hFile);
+
+ // Extract the file info
+ DWORD handle;
+ DWORD viSize = GetFileVersionInfoSize((LPTSTR)(LPCTSTR)filename, &handle);
+ m_versionInfo = NULL;
+
+ if(viSize == 0)
+ {
+ m_status = GetLastError();
+ }
+ else
+ {
+ m_versionInfo = new char[viSize];
+
+ // Get the block of version info from the file
+ if(!GetFileVersionInfo((LPTSTR)(LPCTSTR)filename, handle, viSize, m_versionInfo))
+ {
+ if(m_versionInfo)
+ {
+ delete [] m_versionInfo;
+ m_versionInfo = NULL;
+ }
+ return;
+ }
+
+ // Now extract the sub block we are interested in
+ UINT versionLen = 0;
+ LPVOID viBlob = NULL;
+ if(!VerQueryValue(m_versionInfo, "\\", &viBlob, &versionLen))
+ {
+ if(m_versionInfo)
+ {
+ delete [] m_versionInfo;
+ m_versionInfo = NULL;
+ }
+ return;
+ }
+
+ // And finally the version info is ours
+ m_fixedInfo = (VS_FIXEDFILEINFO *)viBlob;
+
+ UINT blobLen = 0;
+
+ // If we got here, all is good
+ }
+ m_isValid = TRUE;
+}
+
+CVersionInfo::~CVersionInfo()
+{
+ m_fixedInfo = NULL;
+ if(m_versionInfo)
+ {
+ delete [] m_versionInfo;
+ m_versionInfo = NULL;
+ }
+}
+
+CString CVersionInfo::GetFileVersionString()
+{
+ return(QueryStringValue("FileVersion"));
+}
+
+CString CVersionInfo::GetProductVersionString()
+{
+ return(QueryStringValue("ProductVersion"));
+}
+
+CString CVersionInfo::GetComments()
+{
+ return(QueryStringValue("Comments"));
+}
+
+CString CVersionInfo::GetFileDescription()
+{
+ return(QueryStringValue("FileDescription"));
+}
+
+CString CVersionInfo::GetInternalName()
+{
+ return(QueryStringValue("InternalName"));
+}
+
+CString CVersionInfo::GetLegalCopyright()
+{
+ return(QueryStringValue("LegalCopyright"));
+}
+
+CString CVersionInfo::GetLegalTrademarks()
+{
+ return(QueryStringValue("LegalTrademarks"));
+}
+
+CString CVersionInfo::GetOriginalFileName()
+{
+ return(QueryStringValue("OriginalFilename"));
+}
+
+CString CVersionInfo::GetProductName()
+{
+ return(QueryStringValue("ProductName"));
+}
+
+CString CVersionInfo::GetSpecialBuildString()
+{
+ return(QueryStringValue("SpecialBuild"));
+}
+
+CString CVersionInfo::GetPrivateBuildString()
+{
+ return(QueryStringValue("PrivateBuild"));
+}
+
+CString CVersionInfo::GetCompanyName()
+{
+ return(QueryStringValue("CompanyName"));
+}
+
+#ifdef NOTUSED
+BOOL CVersionInfo::CopyFileCheckVersion(CVersionInfo &originalFile)
+{
+ _int64 myVer = GetFileVersion();
+ _int64 origVer = originalFile.GetFileVersion();
+
+ if(origVer > myVer)
+ {
+ CString msg;
+ msg.Format(IDS_EXISTING_NEWER, m_filename);
+ DWORD query = AfxMessageBox(msg, MB_YESNO);
+ if(query == IDNO)
+ return(TRUE);
+ }
+
+ return(CopyFileNoVersion(originalFile));
+}
+#endif
+
+BOOL CVersionInfo::CopyFileNoVersion(CVersionInfo &originalFile)
+{
+ return(CopyFile(originalFile.GetFilename(), m_filename, FALSE));
+}
+
+
+_int64 CVersionInfo::GetFileVersion()
+{
+ _int64 ver = 0;
+
+ if(m_versionInfo)
+ {
+ ver = m_fixedInfo->dwFileVersionMS;
+ ver <<= 32;
+ ver += m_fixedInfo->dwFileVersionLS;
+ }
+ return(ver);
+}
+
+_int64 CVersionInfo::GetProductVersion()
+{
+ _int64 ver = 0;
+
+ if(m_versionInfo)
+ {
+ ver = m_fixedInfo->dwProductVersionMS;
+ ver <<= 32;
+ ver += m_fixedInfo->dwProductVersionLS;
+ }
+ return(ver);
+}
+
+_int64 CVersionInfo::GetFileDate()
+{
+ _int64 fDate = 0;
+
+ if(m_versionInfo)
+ {
+ fDate = m_fixedInfo->dwFileDateMS;
+ fDate <<= 32;
+ fDate += m_fixedInfo->dwFileDateLS;
+ }
+ return(fDate);
+}
+
+DWORD CVersionInfo::GetFileFlagMask()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileFlagsMask);
+ }
+ return(0);
+}
+
+DWORD CVersionInfo::GetFileFlags()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileFlags);
+ }
+ return(0);
+}
+
+DWORD CVersionInfo::GetFileOS()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileOS);
+ }
+ return(VOS_UNKNOWN);
+}
+
+DWORD CVersionInfo::GetFileType()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileType);
+ }
+ return(VFT_UNKNOWN);
+}
+
+DWORD CVersionInfo::GetFileSubType()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileSubtype);
+ }
+ return(VFT2_UNKNOWN);
+}
+
+CString CVersionInfo::QueryStringValue(CString value)
+{
+ UINT blobLen = 0;
+ LPVOID viBlob = NULL;
+ int n;
+
+ if(m_versionInfo)
+ {
+ char queryString[256];
+
+ // This code page value is for American English.
+ // If you change the resources to be other than that
+ // You probably should change this to match it.
+ DWORD codePage = 0x040904B0;
+
+ n = snprintf(queryString, sizeof(queryString),
+ "\\StringFileInfo\\%08X\\%s",
+ codePage, (LPCTSTR) value);
+ if (n >= 0 && (size_t)n < sizeof(queryString)) {
+ if(VerQueryValue(m_versionInfo, queryString,
+ &viBlob, &blobLen))
+ return((char *)viBlob);
+ }
+ }
+ return("Not Available");
+}
diff --git a/bin/win32/BINDInstall/VersionInfo.h b/bin/win32/BINDInstall/VersionInfo.h
new file mode 100644
index 0000000..ec21540
--- /dev/null
+++ b/bin/win32/BINDInstall/VersionInfo.h
@@ -0,0 +1,62 @@
+// VersionInfo.h: interface for the CVersionInfo class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_VERSIONINFO_H__F82E9FF3_5298_11D4_AB87_00C04F789BA0__INCLUDED_)
+#define AFX_VERSIONINFO_H__F82E9FF3_5298_11D4_AB87_00C04F789BA0__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CVersionInfo
+{
+public:
+ CVersionInfo(CString filename);
+ virtual ~CVersionInfo();
+ BOOL IsValid() {return m_isValid;}
+ DWORD GetStatus() {return m_status;}
+
+ BOOL CopyFileCheckVersion(CVersionInfo &originalFile);
+ BOOL CopyFileNoVersion(CVersionInfo &originalFile);
+
+ const CString &GetFilename() {return m_filename;}
+
+ // Extract the elements of the file's string info block
+ CString GetFileVersionString();
+ CString GetProductVersionString();
+ CString GetComments();
+ CString GetFileDescription();
+ CString GetInternalName();
+ CString GetLegalCopyright();
+ CString GetLegalTrademarks();
+ CString GetOriginalFileName();
+ CString GetProductName();
+ CString GetSpecialBuildString();
+ CString GetPrivateBuildString();
+ CString GetCompanyName();
+
+
+ // Extract the elements of the file's VS_FIXEDFILEINFO block
+ _int64 GetFileVersion();
+ _int64 GetProductVersion();
+ _int64 GetFileDate();
+
+ DWORD GetFileFlagMask();
+ DWORD GetFileFlags();
+ DWORD GetFileOS();
+ DWORD GetFileType();
+ DWORD GetFileSubType();
+
+private:
+ CString m_filename;
+ BOOL m_isValid;
+ LPVOID m_versionInfo;
+ VS_FIXEDFILEINFO *m_fixedInfo;
+ DWORD m_codePage;
+ DWORD m_status;
+
+ CString QueryStringValue(CString value);
+};
+
+#endif // !defined(AFX_VERSIONINFO_H__F82E9FF3_5298_11D4_AB87_00C04F789BA0__INCLUDED_)
diff --git a/bin/win32/BINDInstall/res/BINDInstall.ico b/bin/win32/BINDInstall/res/BINDInstall.ico
new file mode 100644
index 0000000..2cf25fe
--- /dev/null
+++ b/bin/win32/BINDInstall/res/BINDInstall.ico
Binary files differ
diff --git a/bin/win32/BINDInstall/res/BINDInstall.rc2 b/bin/win32/BINDInstall/res/BINDInstall.rc2
new file mode 100644
index 0000000..4fc93bb
--- /dev/null
+++ b/bin/win32/BINDInstall/res/BINDInstall.rc2
@@ -0,0 +1,13 @@
+//
+// BINDINSTALL.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/bin/win32/BINDInstall/resource.h b/bin/win32/BINDInstall/resource.h
new file mode 100644
index 0000000..b176fe0
--- /dev/null
+++ b/bin/win32/BINDInstall/resource.h
@@ -0,0 +1,104 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by BINDInstall.rc
+//
+#define IDS_MAINFRAME 1
+#define IDS_CREATEDIR 2
+#define IDS_SUCCESS 3
+#define IDS_FAIL 4
+#define IDS_DIREXIST 5
+#define IDS_INSTALL_DIR 6
+#define IDS_INSTALL_FILE 7
+#define IDS_INSTALL_SERVICE 8
+#define IDS_INSTALL_MESSAGE 9
+#define IDS_UNINSTALL 14
+#define IDS_UNINSTALL_DONE 15
+#define IDS_CREATE_KEY 16
+#define IDS_ADD_REMOVE 17
+#define IDS_CLEANUP 18
+#define IDS_INSTALL_DONE 19
+#define IDS_CREATE_DIR 20
+#define IDS_REMOVE_DIR 21
+#define IDS_COPY_FILE 22
+#define IDS_DELETE_FILE 23
+#define IDS_OPEN_SCM 24
+#define IDS_CREATE_SERVICE 25
+#define IDS_OPEN_SERVICE 26
+#define IDS_REMOVE_SERVICE 27
+#define IDS_REGISTER_MESSAGES 28
+#define IDS_UNREGISTER_MESSAGES 29
+#define IDS_STOP_SERVICE 30
+#define IDS_START_SERVICE 31
+#define IDS_UNINSTALL_DIR 32
+#define IDS_UNINSTALL_FILES 33
+#define IDS_UNINSTALL_SERVICE 34
+#define IDS_UNINSTALL_MESSAGE 35
+#define IDS_ERR_OPEN_SCM 36
+#define IDS_ERR_OPEN_SERVICE 37
+#define IDS_ERR_STOP_SERVICE 38
+#define IDS_ERR_NONCRIT_FILE 39
+#define IDS_ERR_CRITICAL_FILE 40
+#define IDS_ERR_COPY_FILE 40
+#define IDS_ERR_CREATE_SERVICE 41
+#define IDS_ERR_REMOVE_SERVICE 42
+#define IDS_REBOOT 43
+#define IDS_BAD_PRIVILEGES 44
+#define IDS_ERR_CREATE_DIR 45
+#define IDS_VERSION 46
+#define IDS_ERR_CREATE_KEY 47
+#define IDS_ERR_SET_VALUE 48
+#define IDS_NO_VERSION 49
+#define IDS_EXISTING_NEWER 50
+#define IDS_FILE_BAD 51
+#define IDS_ERR_TOOPRIVED 52
+#define IDS_ERR_BADACCOUNT 53
+#define IDS_ERR_WRONGPRIV 54
+#define IDS_CREATEACCOUNT_FAILED 55
+#define IDS_ERR_PASSWORD 56
+#define IDS_ERR_UPDATE_SERVICE 57
+#define IDS_ERR_NULLPASSWORD 58
+#define IDS_ERR_WHITESPACE 59
+#define IDD_BINDINSTALL_DIALOG 102
+#define IDR_MAINFRAME 128
+#define IDD_BROWSE 129
+#define IDI_CHECK 130
+#define IDI_X 132
+#define IDC_CURSOR1 142
+#define IDD_DIALOG1 143
+#define IDC_TARGETDIR 1001
+#define IDC_BROWSE 1002
+#define IDC_DIRLIST 1004
+#define IDC_CURDIR 1005
+#define IDC_INSTALL 1006
+#define IDC_COPY_FILE 1007
+#define IDC_REG_SERVICE 1008
+#define IDC_REG_MESSAGE 1009
+#define IDC_CREATE_DIR 1010
+#define IDC_EXIT 1011
+#define IDC_DIR_TAG 1012
+#define IDC_COPY_TAG 1013
+#define IDC_SERVICE_TAG 1014
+#define IDC_MESSAGE_TAG 1015
+#define IDC_AUTO_START 1016
+#define IDC_UNINSTALL 1017
+#define IDC_VERSION 1018
+#define IDC_KEEP_FILES 1019
+#define IDC_CURRENT_TAG 1020
+#define IDC_DRIVES 1021
+#define IDC_CURRENT 1021
+#define IDC_START 1022
+#define IDC_ACCOUNT_NAME 1030
+#define IDC_ACCOUNT_PASSWORD 1031
+#define IDC_ACCOUNT_PASSWORD_CONFIRM 1032
+#define IDC_TOOLS_ONLY 1033
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 144
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1027
+#define _APS_NEXT_SYMED_VALUE 104
+#endif
+#endif
diff --git a/bind.keys b/bind.keys
new file mode 100644
index 0000000..5e5a32b
--- /dev/null
+++ b/bind.keys
@@ -0,0 +1,50 @@
+# The bind.keys file is used to override the built-in DNSSEC trust anchors
+# which are included as part of BIND 9. The only trust anchors it contains
+# are for the DNS root zone ("."). Trust anchors for any other zones MUST
+# be configured elsewhere; if they are configured here, they will not be
+# recognized or used by named.
+#
+# The built-in trust anchors are provided for convenience of configuration.
+# They are not activated within named.conf unless specifically switched on.
+# To use the built-in key, use "dnssec-validation auto;" in the
+# named.conf options. Without this option being set, the keys in this
+# file are ignored.
+#
+# This file is NOT expected to be user-configured.
+#
+# These keys are current as of October 2017. If any key fails to
+# initialize correctly, it may have expired. In that event you should
+# replace this file with a current version. The latest version of
+# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.
+#
+# See https://data.iana.org/root-anchors/root-anchors.xml
+# for current trust anchor information for the root zone.
+
+managed-keys {
+ # 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/bind.keys.h b/bind.keys.h
new file mode 100644
index 0000000..746dfa2
--- /dev/null
+++ b/bind.keys.h
@@ -0,0 +1,108 @@
+#ifndef BIND_KEYS_H
+#define BIND_KEYS_H 1
+#define TRUSTED_KEYS "\
+# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\
+# which are included as part of BIND 9. The only trust anchors it contains\n\
+# are for the DNS root zone (\".\"). Trust anchors for any other zones MUST\n\
+# be configured elsewhere; if they are configured here, they will not be\n\
+# recognized or used by named.\n\
+#\n\
+# The built-in trust anchors are provided for convenience of configuration.\n\
+# They are not activated within named.conf unless specifically switched on.\n\
+# To use the built-in key, use \"dnssec-validation auto;\" in the\n\
+# named.conf options. Without this option being set, the keys in this\n\
+# file are ignored.\n\
+#\n\
+# This file is NOT expected to be user-configured.\n\
+#\n\
+# These keys are current as of October 2017. If any key fails to\n\
+# initialize correctly, it may have expired. In that event you should\n\
+# replace this file with a current version. The latest version of\n\
+# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\
+#\n\
+# See https://data.iana.org/root-anchors/root-anchors.xml\n\
+# for current trust anchor information for the root zone.\n\
+\n\
+trusted-keys {\n\
+ # This key (19036) is to be phased out starting in 2017. It will\n\
+ # remain in the root zone for some time after its successor key\n\
+ # has been added. It will remain this file until it is removed from\n\
+ # the root zone.\n\
+ . 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\
+ QxA+Uk1ihz0=\";\n\
+\n\
+ # This key (20326) was published in the root zone in 2017.\n\
+ # Servers which were already using the old key (19036) should\n\
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers\n\
+ # being set up for the first time can use the contents of this\n\
+ # file as initializing keys; thereafter, the keys in the\n\
+ # managed key database will be trusted and maintained\n\
+ # automatically.\n\
+ . 257 3 8 \"AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3\n\
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv\n\
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF\n\
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e\n\
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd\n\
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN\n\
+ R1AkUTV74bU=\";\n\
+};\n\
+"
+
+#define MANAGED_KEYS "\
+# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\
+# which are included as part of BIND 9. The only trust anchors it contains\n\
+# are for the DNS root zone (\".\"). Trust anchors for any other zones MUST\n\
+# be configured elsewhere; if they are configured here, they will not be\n\
+# recognized or used by named.\n\
+#\n\
+# The built-in trust anchors are provided for convenience of configuration.\n\
+# They are not activated within named.conf unless specifically switched on.\n\
+# To use the built-in key, use \"dnssec-validation auto;\" in the\n\
+# named.conf options. Without this option being set, the keys in this\n\
+# file are ignored.\n\
+#\n\
+# This file is NOT expected to be user-configured.\n\
+#\n\
+# These keys are current as of October 2017. If any key fails to\n\
+# initialize correctly, it may have expired. In that event you should\n\
+# replace this file with a current version. The latest version of\n\
+# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\
+#\n\
+# See https://data.iana.org/root-anchors/root-anchors.xml\n\
+# for current trust anchor information for the root zone.\n\
+\n\
+managed-keys {\n\
+ # This key (19036) is to be phased out starting in 2017. It will\n\
+ # remain in the root zone for some time after its successor key\n\
+ # has been added. It will remain this file until it is removed from\n\
+ # the root zone.\n\
+ . initial-key 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\
+ QxA+Uk1ihz0=\";\n\
+\n\
+ # This key (20326) was published in the root zone in 2017.\n\
+ # Servers which were already using the old key (19036) should\n\
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers\n\
+ # being set up for the first time can use the contents of this\n\
+ # file as initializing keys; thereafter, the keys in the\n\
+ # managed key database will be trusted and maintained\n\
+ # automatically.\n\
+ . initial-key 257 3 8 \"AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3\n\
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv\n\
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF\n\
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e\n\
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd\n\
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN\n\
+ R1AkUTV74bU=\";\n\
+};\n\
+"
+#endif /* BIND_KEYS_H */